D11039: amend: make `hg amend -r` rebase descendants of target onto amended target
martinvonz (Martin von Zweigbergk)
phabricator at mercurial-scm.org
Fri Jul 9 20:28:52 UTC 2021
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D11039
AFFECTED FILES
hgext/amend.py
tests/test-amend-rev.t
CHANGE DETAILS
diff --git a/tests/test-amend-rev.t b/tests/test-amend-rev.t
--- a/tests/test-amend-rev.t
+++ b/tests/test-amend-rev.t
@@ -48,14 +48,12 @@
Can amend into grandparent
$ hg amend -r 'desc("modify a")'
- 1 new orphan changesets
+ rebasing 2:42e29cb5ca48 "add b"
$ hg log -G -T '{rev} {desc}'
+ o 6 add b (known-bad-output !)
+ |
@ 5 modify a (known-bad-output !)
- | (known-bad-output !)
- | * 2 add b (known-bad-output !)
- | | (known-bad-output !)
- | x 1 modify a (known-bad-output !)
- |/ (known-bad-output !)
+ |
o 0 add a
Target commit has new content
@@ -86,6 +84,13 @@
warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
unresolved conflicts (see 'hg resolve', then 'hg amend --continue')
[240]
+ $ hg log -G -T '{rev} {desc}'
+ % 2 temporary commit for "amend --rev"
+ |
+ o 1 modify a
+ |
+ @ 0 add a
+
$ hg st -v
M a
? a.orig
@@ -133,17 +138,165 @@
$ hg resolve -m
(no more unresolved files)
continue: hg amend --continue
+ $ hg log -G -T '{rev} {desc}'
+ o 2 temporary commit for "amend --rev"
+ |
+ o 1 modify a
+ |
+ @ 0 add a
+
$ hg continue
+ rebasing 1:41c4ea50d4cf "modify a"
+ merging a
+ warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1 new orphan changesets
+ unresolved conflicts (see 'hg resolve', then 'hg amend --continue')
+ [240]
$ hg log -G -T '{rev} {desc}'
@ 4 add a
- * 1 modify a (known-bad-output !)
- | (known-bad-output !)
+ % 1 modify a
+ |
x 0 add a
+ $ echo resolved again > a
+ $ hg resolve -m
+ (no more unresolved files)
+ continue: hg amend --continue
+ $ hg continue
+ rebasing 1:41c4ea50d4cf "modify a"
+ $ hg log -G -T '{rev} {desc}'
+ o 5 modify a (known-bad-output !)
+ |
+ @ 4 add a (known-bad-output !)
+
Target commit has new content
$ hg cat -r 'desc("add a")' a
resolved
The working copy is clean and there is no unfinished operation
$ hg st -v
+ ? a.orig
+
+
+Can abort or continue after conflict while rebasing descendant commit
+--------------------------------------------------------------------------------
+
+Common setup for abort and continue
+ $ cd "$TESTTMP"
+ $ hg init conflict-rebasing-descendant-commit
+ $ cd conflict-rebasing-descendant-commit
+ $ echo a > a
+ $ hg ci -Aqm 'add a'
+ $ echo a2 > a
+ $ hg ci -m 'modify a'
+ $ echo a > a
+ $ hg ci -m 'revert a'
+ $ echo a3 > a
+ $ hg log -G -T '{rev} {desc}'
+ @ 2 revert a
+ |
+ o 1 modify a
+ |
+ o 0 add a
+
+ $ hg amend -r 'desc("add a")'
+ rebasing 1:41c4ea50d4cf "modify a"
+ merging a
+ warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
+ 2 new orphan changesets
+ unresolved conflicts (see 'hg resolve', then 'hg amend --continue')
+ [240]
+ $ hg log -G -T '{rev} {desc}'
+ @ 5 add a
+
+ * 2 revert a
+ |
+ % 1 modify a
+ |
+ x 0 add a
+
+ $ hg st -v
+ M a
+ ? a.orig
+ # The repository is in an unfinished *amend* state.
+
+ # Unresolved merge conflicts:
+ #
+ # a
+ #
+ # To mark files as resolved: hg resolve --mark FILE
+
+ # To continue: hg amend --continue
+ # To abort: hg amend --abort
+
+
+Make a copy of the repo and working copy to test continuing
+ $ cp -R . ../conflict-rebasing-descendant-commit-continue
+
+Can abort
+ $ hg abort
+ rebase aborted
+ saved backup bundle to $TESTTMP/conflict-rebasing-descendant-commit/.hg/strip-backup/f242bdc041a8-4658c323-backup.hg
+The log output looks like it did before we started
+ $ hg log -G -T '{rev} {desc}'
+ @ 2 revert a
+ |
+ o 1 modify a
+ |
+ o 0 add a
+
+The working copy has the change it had before we started
+ $ hg diff
+ diff -r 43217edd8bde a
+ --- a/a Thu Jan 01 00:00:00 1970 +0000
+ +++ b/a Thu Jan 01 00:00:00 1970 +0000
+ @@ -1,1 +1,1 @@
+ -a
+ +a3
+There is no unfinished operation
+ $ hg st -v
+ M a
+ ? a.orig
+
+Can continue
+ $ cd ../conflict-rebasing-descendant-commit-continue
+ $ echo resolved > a
+ $ hg resolve -m
+ (no more unresolved files)
+ continue: hg amend --continue
+ $ hg log -G -T '{rev} {desc}'
+ @ 5 add a
+
+ * 2 revert a
+ |
+ * 1 modify a
+ |
+ x 0 add a
+
+ $ hg continue
+ rebasing 1:41c4ea50d4cf "modify a"
+ rebasing 2:43217edd8bde "revert a"
+ merging a
+ warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
+ unresolved conflicts (see 'hg resolve', then 'hg amend --continue')
+ [240]
+ $ echo resolved again > a
+ $ hg resolve -m
+ (no more unresolved files)
+ continue: hg amend --continue
+ $ hg continue
+ already rebased 1:41c4ea50d4cf "modify a" as 79b758e3d369
+ rebasing 2:43217edd8bde "revert a"
+ $ hg log -G -T '{rev} {desc}'
+ o 7 revert a (known-bad-output !)
+ |
+ o 6 modify a
+ |
+ @ 5 add a (known-bad-output !)
+
+Target commit has new content
+ $ hg cat -r 'desc("add a")' a
+ a3
+The working copy is clean and there is no unfinished operation
+ $ hg st -v
+ ? a.orig
diff --git a/hgext/amend.py b/hgext/amend.py
--- a/hgext/amend.py
+++ b/hgext/amend.py
@@ -208,11 +208,17 @@
unfi = repo.unfiltered()
target_ctx = unfi[state[b'target_node']]
temp_ctx = unfi[state[b'temp_node']]
+ wc_pctx = temp_ctx.p1()
rebased_temp_ctx = _rebase_temp_node(
ui, repo, state, rebase, temp_ctx, target_ctx
)
- _fold_temp_node(ui, repo, state, rebase, rebased_temp_ctx, target_ctx)
+ amended_ctx = _fold_temp_node(
+ ui, repo, state, rebase, rebased_temp_ctx, target_ctx
+ )
+ _rebase_descendants(
+ ui, repo, state, rebase, amended_ctx, target_ctx, wc_pctx
+ )
def _rebase_temp_node(ui, repo, state, rebase, temp_ctx, target_ctx):
@@ -275,6 +281,36 @@
return amended_ctx
+def _rebase_descendants(
+ ui, repo, state, rebase, amended_ctx, target_ctx, wc_pctx
+):
+ if b'rebased_descendant_nodes' in state:
+ return
+ elif statemod.ischildunfinished(repo, b'amend', b'rebase'):
+ with statemod.delegating(repo, b'amend', b'rebase'):
+ ret = statemod.continuechild(ui, repo, b'amend', b'rebase')
+ else:
+ with statemod.delegating(repo, b'amend', b'rebase'):
+ ret = rebase.rebase(
+ ui,
+ repo,
+ rev=[
+ revsetlang.formatspec(
+ b'only(%d, %d)', wc_pctx.rev(), target_ctx.rev()
+ )
+ ],
+ dest=revsetlang.formatspec(b'%d', amended_ctx.rev()),
+ )
+
+ if ret:
+ raise error.Abort(_(b'failed to rebase descendants of target'))
+
+ rebased_descendants = repo.set(b'only(tip, %d)', amended_ctx.rev())
+ state[b'rebased_descendant_nodes'] = [
+ ctx.node() for ctx in rebased_descendants
+ ]
+
+
def _abort_amend_rev(ui, repo):
with repo.wlock(), repo.lock(), repo.transaction(b'amend'):
state_store = statemod.cmdstate(repo, b'amend-state')
@@ -299,6 +335,9 @@
rebased_temp_node = state.get(b'rebased_temp_node')
to_strip.append(rebased_temp_node)
to_strip.append(state.get(b'amended_node'))
+ rebased_descendant_nodes = state.get(b'rebased_descendant_nodes')
+ if rebased_descendant_nodes:
+ to_strip.extend(rebased_descendant_nodes)
to_strip = [node for node in to_strip if node and node in unfi]
if to_strip:
repair.delayedstrip(ui, unfi, to_strip)
To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
More information about the Mercurial-devel
mailing list