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

Re: [RFC] Rebasing merges: a jorney to the ultimate solution (Road Clear)

From
IDIgor Djordjevic <igor.d.djordjevic@gmail.com>
Date
Mar 2, 2018, 01:16 UTC
Message-ID
<f1a960dc-cc5c-e7b0-10b6-39e5516655b3@gmail.com>
In-Reply-To
<87a7vss6ax.fsf@javad.com>
Hi Sergey,
On 01/03/2018 06:39, Sergey Organov wrote:
Show 19 quoted lines
> 
> > > (3) ---X1---o---o---o---o---o---X2
> > >        |\                       |\
> > >        | A1---A2---A3---U1      | A1'--A2'--A3'--U1'
> > >        |             \          |
> > >        |              M         |
> > >        |             /          |
> > >        \-B1---B2---B3---U2      \-B1'--B2'--B3'--U2'
> > >
> > 
> > Meh, I hope I`m rushing it now, but for example, if we had decided to 
> > drop commit A2 during an interactive rebase (so losing A2' from 
> > diagram above), wouldn`t U2' still introduce those changes back, once 
> > U1' and U2' are merged, being incorrect/unwanted behavior...? :/
> > 
> > [...]
> 
> Yeah, I now see it myself. I'm sorry for being lazy and not inspecting
> this more carefully in the first place.

No problem, that`s why we`re discussing it, and I`m glad we`re aligned now, so we can move forward :)

Show 10 quoted lines
> > So while your original proposal currently seems like it could be 
> > working nicely for non-interactive rebase (and might be some simpler 
> > interactive ones), now hitting/acknowledging its first real use 
> > limit, my additional quick attempt[1] just tries to aid pretty 
> > interesting case of complicated interactive rebase, too, where we 
> > might be able to do better as well, still using you original proposal 
> > as a base idea :)
> 
> Yes, thank you for pushing me back to reality! :-) The work and thoughts
> you are putting into solving the puzzle are greatly appreciated!
You`re welcome, and I am enjoying it :)
Show 9 quoted lines
> Thinking about it overnight, I now suspect that original proposal had a
> mistake in the final merge step. I think that what you did is a way to
> fix it, and I want to try to figure what exactly was wrong in the
> original proposal and to find simpler way of doing it right.
> 
> The likely solution is to use original UM as a merge-base for final
> 3-way merge of U1' and U2', but I'm not sure yet. Sounds pretty natural
> though, as that's exactly UM from which both U1' and U2' have diverged
> due to rebasing and other history editing.
Yes, this might be it...! ;)

To prove myself it works, I`ve assembled a pretty crazy `-s ours` merge interactive rebase scenario, and it seems this passes the test, ticking all the check boxes (I could think of) :P

Let`s see our starting situation:
 (0) ---X8--B2'--X9 (master)
        |\
        | A1---A2---A3 (A)
        |             \
        |              M (topic)
        |             /
        \-B1---B2---B3 (B)

Here, merge commit M is done with `-s ours` (obsoleting branch "B"), plus amended to make it an "evil merge", where a commit B2 from obsoleted branch "B" is cherry picked to "master".

Now, we want to rebase "topic" (M) onto updated "master" (X9), but to make things more interesting, we`ll do it interactively, with some amendments, drops, additions and even more cherry-picks!

This is what the final result looks like:
 (1) ---X8--B2'--X9 (master)
                 |\
                 | A12--A2'---B3' (A)
                 |             \
                 |              M' (topic)
                 |             /
                 \-B1'--B3'---B4  (B)

During interactive rebase, on branch "A", we amended A1 into A12, dropped A3 and cherry-picked B3. On branch "B", B4 is added, B2' being omitted automatically as already present in "master".

So... In comparison to original merge commit M, rebased merge commit M' is expected to:

 - Add X9, from updated "master"
 - Have A1 changed to A12, due to A12 commit amendment
 - Keep A2, rebased as A2'
 - Remove A3, due to dropped A3 commit
 - Keep amendment from original (evil) merge commit M
 - Miss B1' like M does B, due to original `-s ours` merge strategy
 - Add B2, cherry-picked as B2' into "master"
 - Add B3, cherry-picked as B3' into "A"
 - Add B4, added to "B"
 - Most important, provide safety mechanism to "fail loud", being 
   aware of non-trivial things going on, allowing to stop for user 
   inspection/decision

There, I hope I didn`t miss any expectation. And, it _seems_ to work exactly as expected :D

Not to leave this to imagination only, and hopefully helping others to get to speed and possibly discuss this, pointing to still possible flaws, I`m adding a demo script[1], showing how this exact example works.

Note that script _is_ coined to avoid rebase conflicts, as they`re not currently important for the point to be made here.

In real life, except for usual possibility for conflicts during commit rebasing, we might experience _three_ possible conflict situations once "rebased" merge itself is to be created - two when rebasing each of temporary merge helper commits, and one on the "rebased" merge itself. This is something where we might think about user experience, not introducing (too much) confusion...

Regards, Buga

[1] Demonstration script: -- >8 -- #!/bin/sh

# rm -rf ./.git # rm -f ./test.txt

git init

touch ./test.txt git add -- test.txt

# prepare repository
for i in {1..8}
do
	echo X$i >>test.txt
	git commit -am "X$i"
done

# prepare branch A git checkout -b A sed -i '2iA1' test.txt git commit -am "A1" sed -i '4iA2' test.txt git commit -am "A2" sed -i '6iA3' test.txt git commit -am "A3"

# prepare branch B git checkout -b B master sed -i '5iB1' test.txt git commit -am "B1" sed -i '7iB2' test.txt git commit -am "B2" sed -i '9iB3' test.txt git commit -am "B3"

git checkout -b topic A git merge -s ours --no-commit B # merge A and B with `-s ours` sed -i '8iM' test.txt # amend merge commit ("evil merge") git commit -am "M" git tag original-merge

# master moves on... git checkout master git cherry-pick B^ # cherry-pick B2 into master sed -i "1iX9" test.txt # add X9 git commit -am "X9"

# (0) ---X8--B2'--X9 (master) # |\ # | A1---A2---A3 (A) # | \ # | M (topic) # | / # \-B1---B2---B3 (B)

# simple/naive demonstration of proposed merge rebasing logic # using described new approach, preserving merge commit manual # amendments, testing `-s ours` merge with cherry-picking from # obsoleted part, but still respecting interactively rebased # added/modified/dropped/cherry-picked commits :)

git checkout A git cherry-pick -m1 original-merge # prepare temporary helper commit U1 git tag U1 git reset --hard HEAD^^ # drop U1 and A3 from A sed -i '/A1/c\A12' test.txt # amend A1 to A12 git commit -a --amend --no-edit git rebase master # rebase A onto master git cherry-pick B # cherry-pick B3 into A git cherry-pick U1 # "rebase" temporary helper commit U1 git tag U1-prime

git checkout B git cherry-pick -m2 original-merge # prepare temporary helper commit U2 git tag U2 git reset --hard HEAD^ # drop U2 from B git rebase master # rebase B onto master sed -i '12iB4' test.txt # add B4 git commit -am "B4" git cherry-pick U2 # "rebase" temporary helper commit U2 git tag U2-prime

git branch -f topic A git checkout topic # merge rebased temporary commits U1' and U2', # using original merge commit as a merge base, # producing "rebased" merge commit M' git read-tree -m --aggressive original-merge A B git merge-index -o git-merge-one-file -a

# recognize complex stuff going on during rebasing merge commit,
# allowing user to inspect result, edit, and continue or abort
git diff --quiet U1-prime U2-prime
if test $? -ne 0
then
	# PLACEHOLDER
	# chance to inspect result, like:
	git diff original-merge
	# edit if needed, continue or abort
fi

# drop rebased temporary commits U1' and U2' git branch -f A A^ git branch -f B B^

# record branches A and B as parents of "rebased" merge commit M', # updating topic branch git update-ref refs/heads/topic "$(git show -s --format=%B original-merge | git commit-tree "$(git write-tree)" -p "$(git rev-parse A)" -p "$(git rev-parse B)")" git tag angel-merge

# (1) ---X8--B2'--X9 (master) # |\ # | A12--A2'---B3' (A) # | \ # | M' (topic) # | / # \-B1'--B3'---B4 (B)

# show resulting graph # echo # git log --all --decorate --oneline --graph

# in comparison to original merge commit M, rebased merge commit # M' is expected to: # # - Add X9, from updated "master" # - Have A1 changed to A12, due to A12 commit amendment # - Keep A2, rebased as A2' # - Remove A3, due to dropped A3 commit # - Keep amendment from original (evil) merge commit M # - Miss B1' like M does B, due to original `-s ours` merge strategy # - Add B2, cherry-picked as B2' into "master" # - Add B3, cherry-picked as B3' into "A" # - Add B4, added to "B" # # echo # echo 'diff original-merge angel-merge:' # git diff original-merge angel-merge

Previous: Sergey OrganovNext: Sergey Organov
Message 34 of 173 in “[RFC] Rebasing merges: a jorney to the ultimate solution (Road Clear)”
  1. Sergey OrganovFeb 16, 2018
  2. Jacob KellerFeb 18, 2018
  3. Sergey OrganovFeb 19, 2018
  4. Igor DjordjevicFeb 19, 2018
  5. Sergey OrganovFeb 20, 2018
  6. Johannes SchindelinFeb 27, 2018
  7. Sergey OrganovFeb 27, 2018
  8. Jacob KellerFeb 27, 2018
  9. Johannes SchindelinFeb 27, 2018
  10. Igor DjordjevicFeb 27, 2018
  11. Igor DjordjevicFeb 27, 2018
  12. Johannes SchindelinFeb 27, 2018
  13. Igor DjordjevicFeb 28, 2018
  14. Igor DjordjevicFeb 28, 2018
  15. Sergey OrganovFeb 28, 2018
  16. Igor DjordjevicFeb 28, 2018
  17. Sergey OrganovFeb 28, 2018
  18. Igor DjordjevicFeb 28, 2018
  19. Igor DjordjevicFeb 27, 2018
  20. Junio C HamanoFeb 28, 2018
  21. Igor DjordjevicFeb 28, 2018
  22. Sergey OrganovFeb 28, 2018
  23. Jacob KellerFeb 28, 2018
  24. Igor DjordjevicFeb 28, 2018
  25. Igor DjordjevicFeb 28, 2018
  26. Sergey OrganovFeb 28, 2018
  27. Igor DjordjevicFeb 28, 2018
  28. Sergey OrganovMar 1, 2018
  29. Sergey OrganovFeb 28, 2018
  30. Igor DjordjevicFeb 28, 2018
  31. Igor DjordjevicFeb 28, 2018
  32. Sergey OrganovMar 1, 2018
  33. Sergey OrganovMar 1, 2018
  34. Igor DjordjevicMar 2, 2018
  35. Sergey OrganovMar 2, 2018
  36. Igor DjordjevicMar 2, 2018
  37. Phillip WoodMar 2, 2018
  38. Phillip WoodMar 2, 2018
  39. Jacob KellerMar 2, 2018
  40. Igor DjordjevicMar 2, 2018
  41. Phillip WoodMar 6, 2018
  42. Johannes SchindelinMar 6, 2018
  43. Igor DjordjevicMar 6, 2018
  44. Johannes SchindelinMar 7, 2018
  45. Phillip WoodMar 8, 2018
  46. Phillip WoodMar 8, 2018
  47. Igor DjordjevicMar 8, 2018
  48. Johannes SchindelinMar 11, 2018
  49. Igor DjordjevicMar 11, 2018
  50. Johannes SchindelinMar 12, 2018
  51. Sergey OrganovMar 12, 2018
  52. Igor DjordjevicMar 13, 2018
  53. Johannes SchindelinMar 26, 2018
  54. Sergey OrganovMar 27, 2018
  55. Johannes SchindelinMar 27, 2018
  56. Sergey OrganovApr 2, 2018
  57. Igor DjordjevicMar 12, 2018
  58. Sergey OrganovMar 13, 2018
  59. Igor DjordjevicMar 8, 2018
  60. Johannes SchindelinMar 11, 2018
  61. Igor DjordjevicMar 11, 2018
  62. Johannes SchindelinMar 12, 2018
  63. Igor DjordjevicMar 13, 2018
  64. Johannes SchindelinMar 26, 2018
  65. Sergey OrganovMar 27, 2018
  66. Johannes SchindelinMar 27, 2018
  67. Sergey OrganovMar 28, 2018
  68. Johannes SchindelinMar 30, 2018
  69. Sergey OrganovMar 30, 2018
  70. Sergey OrganovMar 28, 2018
  71. Jacob KellerMar 8, 2018
  72. Johannes SchindelinMar 11, 2018
  73. Igor DjordjevicMar 11, 2018
  74. Igor DjordjevicMar 8, 2018
  75. Igor DjordjevicMar 8, 2018
  76. Johannes SchindelinMar 11, 2018
  77. Sergey OrganovMar 14, 2018
  78. Igor DjordjevicMar 14, 2018
  79. Sergey OrganovMar 15, 2018
  80. Igor DjordjevicMar 15, 2018
  81. Igor DjordjevicMar 17, 2018
  82. Sergey OrganovMar 19, 2018
  83. Igor DjordjevicMar 19, 2018
  84. Sergey OrganovMar 20, 2018
  85. Johannes SchindelinMar 26, 2018
  86. Junio C HamanoMar 6, 2018
  87. Johannes SchindelinMar 7, 2018
  88. Junio C HamanoMar 7, 2018
  89. Johannes SchindelinMar 8, 2018
  90. Junio C HamanoMar 8, 2018
  91. Johannes SchindelinMar 9, 2018
  92. Jacob KellerMar 2, 2018
  93. Igor DjordjevicMar 2, 2018
  94. Igor DjordjevicMar 3, 2018
  95. Sergey OrganovMar 5, 2018
  96. Phillip WoodMar 2, 2018
  97. Igor DjordjevicMar 3, 2018
  98. Sergey OrganovMar 5, 2018
  99. Phillip WoodMar 6, 2018
  100. Junio C HamanoMar 6, 2018
  101. Johannes SchindelinMar 8, 2018
  102. Junio C HamanoMar 8, 2018
  103. Johannes SchindelinMar 11, 2018
  104. Junio C HamanoMar 13, 2018
  105. Johannes SchindelinMar 26, 2018
  106. Johannes SchindelinMar 5, 2018
  107. Igor DjordjevicMar 6, 2018
  108. Johannes SchindelinMar 7, 2018
  109. Phillip WoodMar 6, 2018
  110. Sergey OrganovMar 6, 2018
  111. Igor DjordjevicMar 8, 2018
  112. Johannes SchindelinMar 6, 2018
  113. Sergey OrganovMar 7, 2018
  114. Johannes SchindelinMar 7, 2018
  115. Sergey OrganovMar 7, 2018
  116. Johannes SchindelinMar 8, 2018
  117. Sergey OrganovMar 12, 2018
  118. Johannes SchindelinMar 26, 2018
  119. Sergey OrganovMar 27, 2018
  120. Johannes SchindelinMar 27, 2018
  121. Sergey OrganovMar 28, 2018
  122. Phillip WoodMar 8, 2018
  123. Johannes SchindelinMar 5, 2018
  124. Sergey OrganovMar 13, 2018
  125. Igor DjordjevicMar 14, 2018
  126. Sergey OrganovMar 14, 2018
  127. Igor DjordjevicMar 15, 2018
  128. Sergey OrganovMar 15, 2018
  129. Igor DjordjevicMar 15, 2018
  130. Sergey OrganovMar 16, 2018
  131. Igor DjordjevicMar 17, 2018
  132. Sergey OrganovMar 19, 2018
  133. Johannes SchindelinMar 26, 2018
  134. Jacob KellerFeb 28, 2018
  135. Sergey OrganovFeb 27, 2018
  136. Junio C HamanoFeb 27, 2018
  137. Jacob KellerFeb 28, 2018
  138. Sergey OrganovFeb 28, 2018
  139. Sergey OrganovFeb 28, 2018
  140. [RFC v2] Rebasing merges: a jorney to the ultimate solution (Road Clear)Sergey Organov, Mar 6, 2018
  141. Johannes SchindelinMar 7, 2018
  142. Sergey OrganovMar 7, 2018
  143. Johannes SchindelinMar 7, 2018
  144. Sergey OrganovMar 7, 2018
  145. Johannes SchindelinMar 8, 2018
  146. Sergey OrganovMar 12, 2018
  147. Johannes SchindelinMar 26, 2018
  148. Igor DjordjevicMar 8, 2018
  149. Igor DjordjevicMar 8, 2018
  150. Igor DjordjevicMar 8, 2018
  151. Igor DjordjevicMar 8, 2018
  152. Johannes SchindelinMar 11, 2018
  153. Igor DjordjevicMar 11, 2018
  154. Johannes SchindelinMar 12, 2018
  155. Sergey OrganovMar 12, 2018
  156. Johannes SchindelinMar 26, 2018
  157. Sergey OrganovMar 27, 2018
  158. Igor DjordjevicMar 13, 2018
  159. Johannes SchindelinMar 26, 2018
  160. Sergey OrganovMar 12, 2018
  161. Johannes SchindelinMar 11, 2018
  162. Igor DjordjevicMar 11, 2018
  163. Sergey OrganovMar 12, 2018
  164. Johannes SchindelinMar 26, 2018
  165. Sergey OrganovMar 27, 2018
  166. Igor DjordjevicMar 12, 2018
  167. Sergey OrganovMar 28, 2018
  168. Sergey OrganovMar 28, 2018
  169. Sergey OrganovMar 29, 2018
  170. Johannes SchindelinMar 30, 2018
  171. Sergey OrganovMar 30, 2018
  172. Johannes SchindelinMar 30, 2018
  173. Sergey OrganovMar 30, 2018

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.