D340: rebase: prefer choosing merge base with successor in destination
quark (Jun Wu)
phabricator at mercurial-scm.org
Mon Aug 14 10:24:59 EDT 2017
quark updated this revision to Diff 868.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D340?vs=830&id=868
REVISION DETAIL
https://phab.mercurial-scm.org/D340
AFFECTED FILES
hgext/rebase.py
tests/test-rebase-obsolete.t
CHANGE DETAILS
diff --git a/tests/test-rebase-obsolete.t b/tests/test-rebase-obsolete.t
--- a/tests/test-rebase-obsolete.t
+++ b/tests/test-rebase-obsolete.t
@@ -1069,10 +1069,8 @@
rebasing 2:b18e25de2cf5 "D" (D)
note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B"
rebasing 5:66f1a38021c9 "F" (F tip)
- warning: rebasing 5:66f1a38021c9 may inlcude unwanted changes from revision 3
+ note: rebase of 5:66f1a38021c9 created no changes to commit
$ hg log -G
- o 7:9ed45af61fa0 F
- |
o 6:8f47515dda15 D
|
| x 5:66f1a38021c9 F
@@ -1106,11 +1104,9 @@
note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B"
rebasing 3:7fb047a69f22 "E" (E)
rebasing 5:66f1a38021c9 "F" (F tip)
- warning: rebasing 5:66f1a38021c9 may inlcude unwanted changes from revision 2
+ note: rebase of 5:66f1a38021c9 created no changes to commit
$ hg log -G
- o 7:502540f44880 F
- |
o 6:533690786a86 E
|
| x 5:66f1a38021c9 F
@@ -1127,6 +1123,137 @@
$ cd ..
+Rebase merge where both parents have successors in destination
+
+ $ hg init p12-succ-in-dest
+ $ cd p12-succ-in-dest
+ $ hg debugdrawdag <<'EOS'
+ > E F
+ > /| /| # replace: A -> C
+ > A B C D # replace: B -> D
+ > | |
+ > X Y
+ > EOS
+ $ hg rebase -r A+B+E -d F
+ note: not rebasing 4:a3d17304151f "A" (A), already in destination as 0:96cc3511f894 "C"
+ note: not rebasing 5:b23a2cc00842 "B" (B), already in destination as 1:058c1e1fb10a "D"
+ rebasing 7:dac5d11c5a7d "E" (E tip)
+ warning: rebasing 7:dac5d11c5a7d may inlcude unwanted changes from revision 3, 5
+ $ hg manifest -r tip
+ B
+ C
+ D
+ Y
+ $ hg log -G -T '{rev}:{node|short} {desc|firstline} +{file_adds}\n'
+ o 8:3306ff4ff997 E +B Y
+ |
+ | x 7:dac5d11c5a7d E +B Y
+ | |\
+ o \ \ 6:e0c929a964ce F +C
+ |\ \ \
+ | | | x 5:b23a2cc00842 B +B
+ | | | |
+ | | x | 4:a3d17304151f A +A
+ | | | |
+ | | | o 3:59c792af609c Y +Y
+ | | |
+ | | o 2:ba2b7fa7166d X +X
+ | |
+ | o 1:058c1e1fb10a D +D
+ |
+ o 0:96cc3511f894 C +C
+
+ $ cd ..
+
+Rebase one parent with successor in destination, the other parent moves as "-d"
+requests. These two tests are to cover the case when the second merge base
+candidate gets selected, new parents get updated accordingly so new p1 matches
+the merge base.
+
+ $ hg init p1-succ-p2-move
+ $ cd p1-succ-p2-move
+ $ hg debugdrawdag <<'EOS'
+ > D
+ > /|
+ > A B Z # replace: A -> C
+ > | | | # D/D = D
+ > X Y C
+ > EOS
+ $ hg rebase -r A+B+D -d Z --config experimental.rebaseskipobsolete=0
+ rebasing 3:a3d17304151f "A" (A)
+ rebasing 4:b23a2cc00842 "B" (B)
+ rebasing 6:141c08ee43e3 "D" (D tip)
+ warning: rebasing 6:141c08ee43e3 may inlcude unwanted changes from revision 2
+
+ $ rm .hg/localtags
+ $ hg log -G
+ o 9:791364acf1f7 D
+ |\
+ | o 8:eb6ceb8cd2c1 B
+ | |
+ o | 7:fe98b87cd6e0 A
+ |/
+ o 5:50e41c1f3950 Z
+ |
+ | o 2:59c792af609c Y
+ |
+ | o 1:ba2b7fa7166d X
+ |
+ o 0:96cc3511f894 C
+
+ $ hg files -r tip
+ A
+ B
+ C
+ D
+ Y
+ Z
+
+ $ cd ..
+
+With p1 and p2 swapped from the above case
+
+ $ hg init p1-move-p2-succ
+ $ cd p1-move-p2-succ
+ $ hg debugdrawdag <<'EOS'
+ > D
+ > /|
+ > A B Z # replace: B -> C
+ > | | | # D/D = D
+ > X Y C
+ > EOS
+ $ hg rebase -r B+A+D -d Z --config experimental.rebaseskipobsolete=0
+ rebasing 3:a3d17304151f "A" (A)
+ rebasing 4:b23a2cc00842 "B" (B)
+ rebasing 6:141c08ee43e3 "D" (D tip)
+ warning: rebasing 6:141c08ee43e3 may inlcude unwanted changes from revision 1
+
+ $ rm .hg/localtags
+ $ hg log -G
+ o 9:433cf923621e D
+ |\
+ | o 8:eb6ceb8cd2c1 B
+ | |
+ o | 7:fe98b87cd6e0 A
+ |/
+ o 5:50e41c1f3950 Z
+ |
+ | o 2:59c792af609c Y
+ |
+ | o 1:ba2b7fa7166d X
+ |
+ o 0:96cc3511f894 C
+
+ $ hg files -r tip
+ A
+ B
+ C
+ D
+ X
+ Z
+
+ $ cd ..
+
Test that bookmark is moved and working dir is updated when all changesets have
equivalents in destination
$ hg init rbsrepo && cd rbsrepo
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -1096,6 +1096,30 @@
repo.ui.debug(" future parents are %d and %d\n" % tuple(newps))
+ # If there are multiple merge base candidates, try to remove one of them.
+ # Prefer keeping obsoleted node with successor in destination. Otherwise we
+ # might re-introduce unwanted obsoleted changes. For example,
+ #
+ # C # rebase -r A+B+C -d D
+ # /| # Suppose A has content "+A", B has "+B", D has "+D".
+ # A B D # replace: A is replaced by D
+ #
+ # B gets moved on top of D, A gets skipped, C gets moved on top of B':
+ #
+ # C' # When choosing merge base for C, A and B are candidates.
+ # | # If we choose B, the difference between C and B are "+A",
+ # C B' # and C' will have the content "+A", which is suboptimal
+ # /| | # because it re-introduces obsoleted content. If we choose
+ # A B D # A as merge base, it works as expected - C' may be empty.
+ if all(b != nullrev for b in bases):
+ assert len(bases) == 2
+ preferred = [any(isancestor(s, dest) for s in successorrevs(repo, r))
+ for r in bases]
+ if preferred == [False, True]:
+ bases.reverse()
+ if newps[1] != nullrev:
+ newps.reverse()
+
# "rebasenode" updates to new p1, use the corresponding merge base.
if bases[0] != nullrev:
base = bases[0]
To: quark, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list