git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Merge with git-pasky II.

From
Linus Torvalds <torvalds@osdl.org>
Date
Apr 15, 2005, 15:32 UTC
Message-ID
<Pine.LNX.4.58.0504150753440.7211@ppc970.osdl.org>
In-Reply-To
<1113559330.12012.292.camel@baythorne.infradead.org>
On Fri, 15 Apr 2005, David Woodhouse wrote:
> 
> And you're right; it shouldn't have to be for renames only. There's no
> need for us to limit it to one "source" and one "destination"; the SCM
> can use it to track content as it sees fit.
Listen to yourself, and think about the problem for a second.

First off, let's just posit that "files" do not matter. The only thing that matters is how "content" moved in the tree. Ok? If I copy a function from one fiel to another, the perfect SCM will notice that, and show it as a diff that removes it from one file and adds it to another, and is _still_ able to track authorship past the move. Agreed?

Now, you basically propose to put that information in the "commit" log, and that's certainly valid. You can have the commit log say "lines 50-89 in file kernel/sched.c moved to lines 100-139 in kernel/timer.c", and then renames fall out of that as one very small special case.

You can even say "lines 50-89 in file kernel/sched.c copied to.." and allow data to be tracked past not just movement, but also duplication.

Do you agree that this is kind of what you'd want to aim for? That's a winning SCM concept.

How do you think the SCM _gets_ at this information? In particular, how are you proposing that we determine this, especially since 90% of all stuff comes in as patches etc?

You propose that we spend time when generating the tree on doing so. I'm telling you that that is wrong, for several reasons:

 - you're ignoring different paths for the same data. For example, you 
   will make it impossible to merge two trees that have done exactly the 
   same thing, except one did it as a patch (create/delete) and one did it 
   using some other heuristic.
 - you're doing the work at the wrong point. Doing it _well_ is quite 
   expensive. So if you do it at commit time, you cannot _afford_ to do it 
   well, and you'll always fall back to doing an ass-backwards job that 
   doesn't really get you to the good state, and only gets you to a 
   not-very-interesting easy 1% of the solution (ie full file renames).
 - you're doing the work at the wrong point for _another_ reason. You're 
   freezing your (crappy) algorithm at tree creation time, and basically 
   making it pointless to ever create something better later, because even 
   if hardware and software improves, you've codified that "we have to
   have crappy information".
Now, look at my proposal: 
 - the actual information tracking tracks _nothing_ but information. You 
   have an SCM that tracks what changed at the only level that really 
   matters, namely the whole project. None of the information actually 
   makes any sense at all at a smaller granularity, since by definition, a
   "project" depends on the other files, or it wouldn't be a project, it
   would be _two_ projects or more.
 - When you're interested in the history of the information, you actually 
   track it, and you try to be _intelligent_ about it. You can actually do 
   a HELL of a lot better than whet you propose if you go the extra mile. 
   For example, let's say that you have a visualization tool that you can 
   use for finding out where a line of code came from. You start out at 
   some arbitrary point in the tree, and you drill down. That's how it 
   works, right?
   So how do you drill down? You simply go backwards in history for that 
   project, tracking when that file+line changed (a "file+line" thing is 
   actually a "sensible" tracking unit at this point, because it makes
   sense within the query you're doing - it's _not_ a sensible thing to
   track at "commit" time, but when you ask yourself "where did this line
   come from", that _question_ makes it sensible. Also note that "where 
   did this _file_ come from is not a sensible question, since the file 
   may have been the combination (or split) of several files, so there is
   no _answer_ to that question"
   So the question then becomes: "how can you reasonably _efficiently_
   find the history of one particular line", and in fact it turns out that 
   by asking the question that way, it's pretty obvious: now that you
   don't have to track the whole repository, you can always try to 
   minimize the thing you're looking for.
   So what you do is walk back the history, and look at the tree objects 
   (both sides when you hit a merge), eand see if that file ever changes. 
   That's actually a very efficient operation in GIT - it matches
   _exactly_ how git tracks things anyway. So it's not expensive at all.
   When that file changes, you need to look if that _line_ changed (and 
   here is where it comes down to usability: from a practical standpoint
   you probably don't care about a single line, you really _probably_ want
   to see changes around it too). So you diff the old state and the new 
   state, and you see if you can still find where you were. If you still 
   can, and the line (and a few lines around it) is still the same, you 
   just continue to drill down. So that's not the interesting case.
   So what happens when you found "ok, that area changed"? Your 
   visualization tool now shows it to the user, AND BECAUSE IT SEES THE 
   WHOLE TREE DIFF, it also shows where it probably came from. At _that_ 
   point, it is actually very trivial to use a modest amount of CPU time, 
   and look for probable sources within that diff. You can do it on modern 
   hardware in basically no time, so your visualization tool can actually 
   notice that
 
	"oops, that line didn't even exist in the previous version, BUT I
	 FOUND FIVE PLACES that matched almost perfectly in the same diff,
	 and here they are"
   and voila, your tool now very efficiently showed the programmer that
   the source of the line in question was actually that we had merged 5 
   copies of the same code in different archtiectures into one common
   helper function.
   And if you didn't find some source that matched, or if the old file was
   actually very similar around that line, and that line hadn't been
   "totally new"? That's the easy case again - you show the programmer the
   diff at that point in time, and you let him decide whether that diff 
   was what he was looking for, or whether he wants to continue to "zoom
   down" into the history.

The above tool is (a) fairly easy to write for git (if you can do visualization tools and (b) _exactly_ what I think most programmers actually want. Tell me I'm wrong. Honestly..

And notice? My clearly _superior_ algorithm never needed any rename information at all. It would have been a total waste of time. It would also have hidden the _real_ pattern, which was that a piece of code was merged from several other matching pieces of code into one new helper function. But if it _had_ been a pure rename, my superior tool would have trivially found that _too_. So rename infomation really really doesn't matter.

So I'm claiming that any SCM that tries to track renames is fundamentally broken unless it does so for internal reasons (ie to allow efficient deltas), exactly because renames do not matter. They don't help you, and they aren't what you were interested in _anyway_.

What matters is finding "where did this come from", and the git architecture does that very well indeed - much better than anything else out there. I outlined a simple algorithm that can be fairly trivially coded up by somebody who really cares. Sure, pattern matching isn't trivial, but you start out with just saying "let's find that exact line, and two lines on each side", and then you start improving on that.

And that "where did this come from" decision should be done at _search_ time, not commit time. Because at that time it's not only trivial to do, but at that time you can _dynamically_ change your search criteria. For example, you can make the "match" algorithm be dependent on what you are looking at.

If it's C source code, it might want to ignore vairable names when it searches for matching code. And if it's a OpenOffice document, you might have some open-office-specific tools to do so. See? Also, the person doing the searches can say whether he is interested in that particular line (or even that particial _identifier_ on a line), or whether he wants to see the changes "around" that line.

All of which are very valid things to do, and all of which my world-view supports very well indeed. And all of which your pitiful "files matter" world-view totally doesn't get at all.

In other words, I'm right. I'm always right, but sometimes I'm more right than other times. And dammit, when I say "files don't matter", I'm really really Right(tm).

Please stop this "track files" crap. Git tracks _exactly_ what matters, namely "collections of files". Nothing else is relevant, and even _thinking_ that it is relevant only limits your world-view. Notice how the notion of CVS "annotate" always inevitably ends up limiting how people use it. I think it's a totally useless piece of crap, and I've described something that I think is a million times more useful, and it all fell out _exactly_ because I'm not limiting my thinking to the wrong model of the world.

			Linus
Previous: David WoodhouseNext: David Woodhouse
Message 23 of 130 in “Merge with git-pasky II.”
  1. Petr BaudisApr 14, 2005
  2. Christopher LiApr 13, 2005
  3. Petr BaudisApr 14, 2005
  4. Christopher LiApr 13, 2005
  5. Linus TorvaldsApr 14, 2005
  6. Christopher LiApr 14, 2005
  7. Paul JacksonApr 14, 2005
  8. Christopher LiApr 14, 2005
  9. Paul JacksonApr 14, 2005
  10. Junio C HamanoApr 14, 2005
  11. Linus TorvaldsApr 14, 2005
  12. Junio C HamanoApr 14, 2005
  13. Linus TorvaldsApr 14, 2005
  14. Junio C HamanoApr 14, 2005
  15. Petr BaudisApr 14, 2005
  16. Junio C HamanoApr 14, 2005
  17. Linus TorvaldsApr 14, 2005
  18. Junio C HamanoApr 14, 2005
  19. Petr BaudisApr 14, 2005
  20. Linus TorvaldsApr 15, 2005
  21. Barry SilvermanApr 15, 2005
  22. David WoodhouseApr 15, 2005
  23. Linus TorvaldsApr 15, 2005
  24. David WoodhouseApr 15, 2005
  25. C. Scott AnanianApr 15, 2005
  26. Linus TorvaldsApr 15, 2005
  27. Johannes SchindelinApr 16, 2005
  28. David WoodhouseApr 17, 2005
  29. Paul JacksonApr 15, 2005
  30. Simon FowlerApr 16, 2005
  31. David LangApr 16, 2005
  32. Simon FowlerApr 16, 2005
  33. Petr BaudisApr 16, 2005
  34. Simon FowlerApr 16, 2005
  35. Linus TorvaldsApr 16, 2005
  36. David LangApr 16, 2005
  37. Ingo MolnarApr 17, 2005
  38. Brad RobertsApr 17, 2005
  39. Ingo MolnarApr 17, 2005
  40. Ingo MolnarApr 17, 2005
  41. Linus TorvaldsApr 17, 2005
  42. Herbert XuApr 17, 2005
  43. Linus TorvaldsApr 17, 2005
  44. Herbert XuApr 17, 2005
  45. Petr BaudisApr 17, 2005
  46. Kenneth JohanssonApr 17, 2005
  47. Herbert XuApr 18, 2005
  48. Petr BaudisApr 18, 2005
  49. Linus TorvaldsApr 17, 2005
  50. Sanjoy MahajanApr 18, 2005
  51. Ingo MolnarApr 18, 2005
  52. Sanjoy MahajanApr 16, 2005
  53. Linus TorvaldsApr 16, 2005
  54. ls-tree enhancementsJunio C Hamano, Apr 15, 2005
  55. Petr BaudisApr 15, 2005
  56. Junio C HamanoApr 15, 2005
  57. David WoodhouseApr 15, 2005
  58. Ingo MolnarApr 15, 2005
  59. David WoodhouseApr 15, 2005
  60. Ingo MolnarApr 15, 2005
  61. David WoodhouseApr 15, 2005
  62. Johannes SchindelinApr 15, 2005
  63. Theodore Ts'oApr 15, 2005
  64. Linus TorvaldsApr 15, 2005
  65. David WoodhouseApr 15, 2005
  66. Linus TorvaldsApr 15, 2005
  67. Paul JacksonApr 15, 2005
  68. C. Scott AnanianApr 15, 2005
  69. Paul JacksonApr 15, 2005
  70. Christopher LiApr 14, 2005
  71. Petr BaudisApr 14, 2005
  72. Live Merging from remote repositoriesBarry Silverman, Apr 14, 2005
  73. Junio C HamanoApr 14, 2005
  74. Question about git process modelBarry Silverman, Apr 15, 2005
  75. Erik van KonijnenburgApr 14, 2005
  76. Petr BaudisApr 14, 2005
  77. Junio C HamanoApr 14, 2005
  78. Christopher LiApr 14, 2005
  79. Petr BaudisApr 14, 2005
  80. Christopher LiApr 14, 2005
  81. Christopher LiApr 14, 2005
  82. Christopher LiApr 14, 2005
  83. Junio C HamanoApr 15, 2005
  84. Christopher LiApr 14, 2005
  85. Junio C HamanoApr 15, 2005
  86. Christopher LiApr 15, 2005
  87. Junio C HamanoApr 15, 2005
  88. Petr BaudisApr 15, 2005
  89. Junio C HamanoApr 15, 2005
  90. Petr BaudisApr 15, 2005
  91. Junio C HamanoApr 15, 2005
  92. Junio C HamanoApr 15, 2005
  93. Linus TorvaldsApr 15, 2005
  94. Petr BaudisApr 14, 2005
  95. git mergePetr Baudis, Apr 14, 2005
  96. Linus TorvaldsApr 15, 2005
  97. Petr BaudisApr 15, 2005
  98. Linus TorvaldsApr 15, 2005
  99. Petr BaudisApr 15, 2005
  100. Linus TorvaldsApr 16, 2005
  101. Daniel BarkalowApr 16, 2005
  102. Linus TorvaldsApr 16, 2005
  103. Daniel BarkalowApr 16, 2005
  104. Linus TorvaldsApr 16, 2005
  105. Daniel BarkalowApr 16, 2005
  106. Paul JacksonApr 16, 2005
  107. Petr BaudisApr 16, 2005
  108. Junio C HamanoApr 15, 2005
  109. C. Scott AnanianApr 15, 2005
  110. Petr BaudisApr 15, 2005
  111. Junio C HamanoApr 15, 2005
  112. 1/2 merge-trees script for Linus gitJunio C Hamano, Apr 15, 2005
  113. 2/2 merge-trees script for Linus gitJunio C Hamano, Apr 15, 2005
  114. 3/2 merge-trees script for Linus gitJunio C Hamano, Apr 15, 2005
  115. Linus TorvaldsApr 16, 2005
  116. Junio C HamanoApr 16, 2005
  117. Linus TorvaldsApr 16, 2005
  118. Linus TorvaldsApr 16, 2005
  119. Junio C HamanoApr 16, 2005
  120. Byteorder fix for read-tree, new -m semantics version.Junio C Hamano, Apr 16, 2005
  121. 1/2 Add --stage to show-files for new stage dircache.Junio C Hamano, Apr 16, 2005
  122. 2/2 Add --stage to show-files for new stage dircache.Junio C Hamano, Apr 16, 2005
  123. Issues with higher-order stages in dircacheJunio C Hamano, Apr 16, 2005
  124. Junio C HamanoApr 17, 2005
  125. Linus TorvaldsApr 17, 2005
  126. Junio C HamanoApr 17, 2005
  127. Summary of "read-tree -m O A B" mechanismJunio C Hamano, Apr 17, 2005
  128. Linus TorvaldsApr 16, 2005
  129. Linus TorvaldsApr 16, 2005
  130. Junio C HamanoApr 16, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.