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

Re: Command-line interface thoughts (ad-hominem attacks)

From
Jeff King <peff@peff.net>
Date
Jun 9, 2011, 00:43 UTC
Message-ID
<20110609004347.GC19715@sigill.intra.peff.net>
In-Reply-To
<BANLkTinibF0xmibeuJ6f9FUjaMmxavMJig@mail.gmail.com>
On Wed, Jun 08, 2011 at 02:57:09PM -0400, Michael Nahas wrote:
Show 13 quoted lines
> > Isn't this going to be behavior change, since your NEXT is not quite the
> > same as the index? How do I now get an n-way combined diff of the
> > unmerged files in the index?
> 
> The index is a file in .git/ that serves many purposes.  NEXT is an
> image of the whole project.  NEXT can be computed from the index and
> HEAD.
> 
> During a conflicted merge, stage 0 of the index holds the resolved
> files.  WTREE holds all merge files: the resolved and the unresolved
> (which have <<<< ==== >>>> blocks in them).  I propose that during a
> conflicted merge, that NEXT be computed as HEAD plus the resolved
> files, that is, the files in stage 0 of the index.

OK. So NEXT actually has less information than the whole index, because it doesn't contain information on what was on either side of the merge originally (or in the merge base).

Show 6 quoted lines
> "git diff HEAD NEXT" would print the resolved changes.
> "git diff NEXT WTREE" would print the unresolved changes
> "git diff HEAD WTREE" would print all changes.
> 
> I believe that is the same behaviour as "git diff", "git diff
> --cached" and "git diff HEAD" during a conflicted merge.
I assume you don't mean respectively here, but rather:
  git diff          => git diff NEXT WTREE
  git diff --cached => git diff HEAD NEXT
  git diff HEAD     => git diff HEAD WTREE
But even still, I don't think "git diff" is the same. Try this:
  git init repo && cd repo
  echo one >file && git add file && git commit -m one &&
  echo two >file && git add file && git commit -m two &&
  git checkout -b other HEAD^ &&
  echo three >file && git add file && git commit -m three &&
  ! git merge master &&
  git diff
I get:
  diff --cc file
  index 2bdf67a,f719efd..0000000
  --- a/file
  +++ b/file
  @@@ -1,1 -1,1 +1,5 @@@
  ++<<<<<<< HEAD
   +three
  ++=======
  + two
  ++>>>>>>> master

Note that this is _not_ a diff between NEXT and the working tree. It is a 3-way "combined" diff of what's in the working tree compared to each side of the merge.

If NEXT is a tree that contains HEAD plus stage 0 files, then we would see a 2-way diff of the HEAD version of "file" and the working tree version. I.e., the same as "git diff HEAD -- file":

  diff --git a/file b/file
  index 2bdf67a..087e97e 100644
  --- a/file
  +++ b/file
  @@ -1 +1,5 @@
  +<<<<<<< HEAD
   three
  +=======
  +two
  +>>>>>>> master

which looks similar, because we haven't started resolving anything yet. But try resolving it like this:

  cat >file <<'EOF'
  three
  and
  two
  EOF
Now try "git diff" again. You should get:
  diff --cc file
  index 2bdf67a,f719efd..0000000
  --- a/file
  +++ b/file
  @@@ -1,1 -1,1 +1,3 @@@
   +three
  ++and
  + two

This shows us that "three" came from one side of the merge, "two" from the other, and that "and" was found in neither side.

Compare to the 2-way that shows:
  diff --git a/file b/file
  index 2bdf67a..1ecff7e 100644
  --- a/file
  +++ b/file
  @@ -1 +1,3 @@
   three
  +and
  +two

There's nothing to distinguish added code pulled from the other side of the merge versus changes that were made as part of the resolution.

I think this is what Junio was talking about when he said that the index is more than a tree. There may be times when you want to treat the items in stage 0 as a tree, but diffing against the index is more than just diffing against that tree.

> I do not know how "n-way" merge works.  I saw somewhere that indicated
> that it was a series of N-1 two-way merges.

Git history can represent a merge of any number of branches (an "octopus merge"), because the commits store only the final state and a list of parent commits. The combined diff format is capable of handling an arbitrary number of parents.

I should have just said "3-way", though, because it's not relevant here. The index only has 2 stage bits, so we can only represent four stages ("resolved", "base", "ours", and "theirs"). So you can't represent an n-way merge in the index.

So "git merge" just punts on an octopus merge if there are actual merge conflicts that would need to go in the index. So in practice, people just tend to do N-1 pair-wise merges.

You can see some example octopus merges (and their combined diff) if you have a recent git (that supports --min-parents) with:

  git log --min-parents=3 -p --cc
in both git.git and linux-2.6.git.
-Peff
Previous: Michael NahasNext: Michael Nahas
Message 52 of 98 in “Command-line interface thoughts”
  1. Michael NahasJun 4, 2011
  2. Jakub NarebskiJun 4, 2011
  3. Michael NahasJun 5, 2011
  4. Jakub NarebskiJun 5, 2011
  5. Scott ChaconJun 5, 2011
  6. Jakub NarebskiJun 5, 2011
  7. Junio C HamanoJun 6, 2011
  8. Michael J GruberJun 6, 2011
  9. Michael NahasJun 6, 2011
  10. Jakub NarebskiJun 6, 2011
  11. Michael J GruberJun 6, 2011
  12. Jakub NarebskiJun 8, 2011
  13. Junio C HamanoJun 6, 2011
  14. Drew NorthupJun 6, 2011
  15. Junio C HamanoJun 6, 2011
  16. Michael J GruberJun 6, 2011
  17. Junio C HamanoJun 6, 2011
  18. Scott ChaconJun 6, 2011
  19. Junio C HamanoJun 6, 2011
  20. Michael J GruberJun 7, 2011
  21. Jonathan NiederJun 7, 2011
  22. Holger HellmuthJun 7, 2011
  23. Jonathan NiederJun 7, 2011
  24. Jakub NarebskiJun 7, 2011
  25. Holger HellmuthJun 8, 2011
  26. Jakub NarebskiJun 8, 2011
  27. Holger HellmuthJun 9, 2011
  28. Jakub NarebskiJun 10, 2011
  29. Holger HellmuthJun 10, 2011
  30. Jakub NarebskiJun 10, 2011
  31. Holger HellmuthJun 10, 2011
  32. git diff --added (Re: Command-line interface thoughts)Jonathan Nieder, Jun 13, 2011
  33. Miles BaderJun 13, 2011
  34. Miles BaderJun 13, 2011
  35. Jonathan NiederJun 13, 2011
  36. Junio C HamanoJun 13, 2011
  37. Junio C HamanoJun 13, 2011
  38. Holger HellmuthJun 13, 2011
  39. Michael NahasJun 13, 2011
  40. Jakub NarebskiJun 13, 2011
  41. Holger HellmuthJun 13, 2011
  42. Michael HaggertyJun 14, 2011
  43. Jakub NarebskiJun 14, 2011
  44. René ScharfeJun 7, 2011
  45. Jakub NarebskiJun 7, 2011
  46. Jakub NarebskiJun 8, 2011
  47. Michael NahasJun 8, 2011
  48. Jakub NarebskiJun 8, 2011
  49. Michael NahasJun 8, 2011
  50. Jeff KingJun 8, 2011
  51. Michael NahasJun 8, 2011
  52. Jeff KingJun 9, 2011
  53. Michael NahasJun 9, 2011
  54. Jakub NarebskiJun 10, 2011
  55. Jakub NarebskiJun 9, 2011
  56. Michael NahasJun 9, 2011
  57. Jakub NarebskiJun 9, 2011
  58. Jakub NarebskiJun 9, 2011
  59. Michael HaggertyJun 9, 2011
  60. Andreas EricssonJun 9, 2011
  61. Thomas RastJun 9, 2011
  62. Jeff KingJun 9, 2011
  63. Jay SoffianJun 9, 2011
  64. Jeff KingJun 9, 2011
  65. Junio C HamanoJun 9, 2011
  66. Jay SoffianJun 9, 2011
  67. Junio C HamanoJun 9, 2011
  68. Michael HaggertyJun 9, 2011
  69. Junio C HamanoJun 9, 2011
  70. Michael HaggertyJun 9, 2011
  71. Jeff KingJun 9, 2011
  72. Michael HaggertyJun 9, 2011
  73. Jakub NarebskiJun 9, 2011
  74. Michael HaggertyJun 9, 2011
  75. Jakub NarebskiJun 10, 2011
  76. Michael NahasJun 10, 2011
  77. Jakub NarebskiJun 10, 2011
  78. Jeff KingJun 9, 2011
  79. Michael NahasJun 9, 2011
  80. Jeff KingJun 9, 2011
  81. Jakub NarebskiJun 9, 2011
  82. Michael NahasJun 10, 2011
  83. Jeff KingJun 10, 2011
  84. Junio C HamanoJun 10, 2011
  85. Junio C HamanoJun 10, 2011
  86. Jakub NarebskiJun 10, 2011
  87. Michael HaggertyJun 12, 2011
  88. Junio C HamanoJun 12, 2011
  89. Michael NahasJun 12, 2011
  90. Junio C HamanoJun 12, 2011
  91. Michael NahasJun 13, 2011
  92. Jeff KingJun 13, 2011
  93. Jeff KingJun 9, 2011
  94. Paul EbermannJun 5, 2011
  95. Paul EbermannJun 5, 2011
  96. Michael NahasJun 7, 2011
  97. Junio C HamanoJun 7, 2011
  98. Michael NahasJun 7, 2011

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.