diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -447,9 +447,44 @@ def rebasenode(repo, rev, p1, state, col repo.ui.debug(" already in target\n") repo.dirstate.write() repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev])) - base = None - if repo[rev].rev() != repo[min(state)].rev(): + if repo[rev].rev() == repo[min(state)].rev(): + # Case (1) initial changeset of a non-detaching rebase. + # Let the merge mechanism find the base itself. + base = None + elif not repo[rev].p2(): + # Case (2) detaching the node with a single parent, use this parent base = repo[rev].p1().node() + else: + # In case of merge, we need to pick the right parent as merge base. + # + # Imagine we have: + # - M: currently rebase revision in this step + # - A: one parent of M + # - B: second parent of M + # - D: destination of this merge step (p1 var) + # + # If we are rebasing on D, D is the successors of A or B. The right + # merge base is the one D succeed to. We pretend it is B for the rest + # of this comment + # + # If we pick B as the base, the merge involves: + # - changes from B to M (actual changeset payload) + # - changes from B to D (induced by rebase) as D is a rebased + # version of B) + # Which exactly represent the rebase operation. + # + # If we pick the A as the base, the merge involves + # - changes from A to M (actual changeset payload) + # - changes from A to D (with include changes between unrelated A and B + # plus changes induced by rebase) + # Which does not represent anything sensible and creates a lot of + # conflicts. + for p in repo[rev].parents(): + if state.get(p.rev()) == repo[p1].rev(): + base = p.node() + break + if base is not None: + repo.ui.debug(" detach base %d:%s\n" % (repo[base].rev(), repo[base])) # When collapsing in-place, the parent is the common ancestor, we # have to allow merging with it. return merge.update(repo, rev, True, True, False, base, collapse) diff --git a/tests/bundles/issue4041.hg b/tests/bundles/issue4041.hg new file mode 100644 index 0000000000000000000000000000000000000000..6a31748ad67fa7fd4b12387b32e13e68b08f8d65 GIT binary patch literal 2216 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] + rebasing: 9:e31216eec445 5/6 changesets (83.33%) + future parents are 2 and -1 + rebase status stored + update to 2:4bc80088dc6b + resolving manifests + branchmerge: False, force: True, partial: False + ancestor: d79e2059b5c0+, local: d79e2059b5c0+, remote: 4bc80088dc6b + f2.txt: other deleted -> r + f1.txt: remote created -> g + removing f2.txt + updating: f2.txt 1/2 files (50.00%) + getting f1.txt + updating: f1.txt 2/2 files (100.00%) + merge against 9:e31216eec445 + detach base 8:8e4e2c1a07ae + searching for copies back to rev 3 + resolving manifests + branchmerge: True, force: True, partial: False + ancestor: 8e4e2c1a07ae, local: 4bc80088dc6b+, remote: e31216eec445 + f1.txt: remote is newer -> g + getting f1.txt + updating: f1.txt 1/1 files (100.00%) + f1.txt + rebasing: 10:2f2496ddf49d 6/6 changesets (100.00%) + future parents are 11 and 7 + rebase status stored + already in target + merge against 10:2f2496ddf49d + detach base 9:e31216eec445 + searching for copies back to rev 3 + resolving manifests + branchmerge: True, force: True, partial: False + ancestor: e31216eec445, local: 19c888675e13+, remote: 2f2496ddf49d + f1.txt: remote is newer -> g + getting f1.txt + updating: f1.txt 1/1 files (100.00%) + f1.txt + rebase merging completed + update back to initial working directory parent + resolving manifests + branchmerge: False, force: False, partial: False + ancestor: 2a7f09cac94c, local: 2a7f09cac94c+, remote: d79e2059b5c0 + f1.txt: other deleted -> r + f2.txt: remote created -> g + removing f1.txt + updating: f1.txt 1/2 files (50.00%) + getting f2.txt + updating: f2.txt 2/2 files (100.00%) + 3 changesets found + list of changesets: + 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c + e31216eec445e44352c5f01588856059466a24c9 + 2f2496ddf49d69b5ef23ad8cf9fb2e0e4faf0ac2 + bundling: 1/3 changesets (33.33%) + bundling: 2/3 changesets (66.67%) + bundling: 3/3 changesets (100.00%) + bundling: 1/3 manifests (33.33%) + bundling: 2/3 manifests (66.67%) + bundling: 3/3 manifests (100.00%) + bundling: f1.txt 1/1 files (100.00%) + saved backup bundle to $TESTTMP/issue4041/.hg/strip-backup/e31216eec445-backup.hg (glob) + 3 changesets found + list of changesets: + 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c + 19c888675e133ab5dff84516926a65672eaf04d9 + 2a7f09cac94c7f4b73ebd5cd1a62d3b2e8e336bf + bundling: 1/3 changesets (33.33%) + bundling: 2/3 changesets (66.67%) + bundling: 3/3 changesets (100.00%) + bundling: 1/3 manifests (33.33%) + bundling: 2/3 manifests (66.67%) + bundling: 3/3 manifests (100.00%) + bundling: f1.txt 1/1 files (100.00%) + adding branch + adding changesets + changesets: 1 chunks + add changeset 4c9fbe56a16f + changesets: 2 chunks + add changeset 19c888675e13 + changesets: 3 chunks + add changeset 2a7f09cac94c + adding manifests + manifests: 1/2 chunks (50.00%) + manifests: 2/2 chunks (100.00%) + manifests: 3/2 chunks (150.00%) + adding file changes + adding f1.txt revisions + files: 1/1 chunks (100.00%) + added 2 changesets with 2 changes to 1 files + removing unknown node e31216eec445 from 1-phase boundary + invalid branchheads cache (served): tip differs + rebase completed + updating the branch cache