mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
Make hg rebase --restack smarter
Differential Revision: https://phabricator.intern.facebook.com/D4000348
This commit is contained in:
parent
7f1c4eb449
commit
37cf7bd354
@ -29,10 +29,11 @@ from mercurial import (
|
||||
phases,
|
||||
repair,
|
||||
)
|
||||
from mercurial.node import hex
|
||||
from mercurial.node import hex, nullrev
|
||||
from mercurial import lock as lockmod
|
||||
from mercurial.i18n import _
|
||||
from itertools import chain
|
||||
from collections import defaultdict, deque
|
||||
from contextlib import nested
|
||||
|
||||
cmdtable = {}
|
||||
@ -485,15 +486,14 @@ def _nextrebase(orig, ui, repo, **opts):
|
||||
# from rebasemod.rebase(), so just assume that it's the current
|
||||
# changeset's only child. (This should always be the case.)
|
||||
rebasedchild = current.children()[0]
|
||||
ancestors = [r.node() for r in repo.set('%d %% .', child.rev())]
|
||||
ancestors = repo.set('%d %% .', child.rev())
|
||||
|
||||
# Mark the old child changeset as obsolete, and remove the
|
||||
# the inhibition markers from it and its ancestors. This
|
||||
# effectively "strips" all of the obsoleted changesets in the
|
||||
# stack below the child.
|
||||
_deinhibit(repo, ancestors)
|
||||
obsolete.createmarkers(repo, [(child, [rebasedchild])])
|
||||
if inhibitmod:
|
||||
inhibitmod._deinhibitmarkers(repo, ancestors)
|
||||
|
||||
# Remove any preamend bookmarks on precursors, as these would
|
||||
# create unnecessary inhibition markers.
|
||||
@ -504,9 +504,9 @@ def _nextrebase(orig, ui, repo, **opts):
|
||||
|
||||
def restack(orig, ui, repo, **opts):
|
||||
"""Wrapper around `hg rebase` adding the `--restack` option, which rebases
|
||||
all "unstable" descendants of an obsolete changeset onto the latest
|
||||
version of that changeset. This is similar to (and intended as a
|
||||
replacement for) the `hg evolve --all` command.
|
||||
all "unstable" descendants of an obsolete changeset onto the latest
|
||||
version of that changeset. This is similar to (and intended as a
|
||||
replacement for) the `hg evolve --all` command.
|
||||
"""
|
||||
if not opts['restack']:
|
||||
return orig(ui, repo, **opts)
|
||||
@ -533,28 +533,198 @@ def restack(orig, ui, repo, **opts):
|
||||
cmdutil.checkunfinished(repo)
|
||||
cmdutil.bailifchanged(repo)
|
||||
|
||||
base = repo['.']
|
||||
precursors = list(repo.set('allprecursors(%d)', base.rev()))
|
||||
descendants = chain.from_iterable(p.descendants() for p in precursors)
|
||||
# Identify a base changeset from which to begin stabilizing.
|
||||
base = _findrestackbase(repo)
|
||||
targets = _findrestacktargets(repo, base)
|
||||
|
||||
# Overwrite source and destination, leave all other options.
|
||||
opts['rev'] = [d.rev() for d in descendants]
|
||||
opts['dest'] = base.rev()
|
||||
|
||||
ret = None
|
||||
with repo.transaction('restack') as tr:
|
||||
try:
|
||||
ret = orig(ui, repo, **opts)
|
||||
except error.InterventionRequired:
|
||||
tr.close()
|
||||
raise
|
||||
_clearpreamend(repo, precursors)
|
||||
if inhibitmod:
|
||||
inhibitmod._deinhibitmarkers(
|
||||
repo,
|
||||
(p.node() for p in precursors)
|
||||
)
|
||||
return ret
|
||||
# Attempt to stabilize all changesets that are or will be (after
|
||||
# rebasing) descendants of base.
|
||||
for rev in targets:
|
||||
try:
|
||||
_restackonce(ui, repo, rev, opts)
|
||||
except error.InterventionRequired:
|
||||
tr.close()
|
||||
raise
|
||||
|
||||
# If we're currently on one of the precursors of the base, update
|
||||
# to the latest successor since the old changeset is no longer
|
||||
# needed. Note that if we're on a descendant of the base or its
|
||||
# precurosrs, the rebase command will ensure that we end up on a
|
||||
# non-obsolete changeset, so it is only necessary to explicitly
|
||||
# update if we're on a precursor of the base.
|
||||
if not repo.revs('. - allprecursors(%d)', base):
|
||||
commands.update(ui, repo, rev=base)
|
||||
|
||||
def _restackonce(ui, repo, rev, rebaseopts=None):
|
||||
"""Rebase all descendants of precursors of rev onto rev, thereby
|
||||
stabilzing any non-obsolete descendants of those precursors.
|
||||
"""
|
||||
# Get visible descendants of precusors of rev.
|
||||
allprecursors = repo.revs('allprecursors(%d)', rev)
|
||||
descendants = repo.revs('descendants(%ld) - %ld', allprecursors,
|
||||
allprecursors)
|
||||
|
||||
# Nothing to do if there are no descendants.
|
||||
if not descendants:
|
||||
return
|
||||
|
||||
# Overwrite source and destination, leave all other options.
|
||||
if rebaseopts is None:
|
||||
rebaseopts = {}
|
||||
rebaseopts['rev'] = descendants
|
||||
rebaseopts['dest'] = rev
|
||||
|
||||
rebasemod.rebase(ui, repo, **rebaseopts)
|
||||
|
||||
# Remove any preamend bookmarks and any inhibition markers
|
||||
# on precursors so that they will be correctly labelled as
|
||||
# obsolete. The rebase command will obsolete the descendants,
|
||||
# so we only need to do this for the precursors.
|
||||
contexts = [repo[r] for r in allprecursors]
|
||||
_clearpreamend(repo, contexts)
|
||||
_deinhibit(repo, contexts)
|
||||
|
||||
|
||||
def _findrestackbase(repo):
|
||||
"""Search backwards through history to find a changeset in the current
|
||||
stack that may have unstable descendants on its precursors, or
|
||||
may itself need to be stabilized.
|
||||
"""
|
||||
# Move down current stack until we find a changeset with visible
|
||||
# precursors or successors, indicating that we may need to stabilize
|
||||
# some descendants of this changeset or its precursors.
|
||||
stack = repo.revs('. %% public()')
|
||||
stack.reverse()
|
||||
for rev in stack:
|
||||
# Is this the latest version of this changeset? If not, we need
|
||||
# to rebase any unstable descendants onto the latest version.
|
||||
latest = _latest(repo, rev)
|
||||
if rev != latest:
|
||||
return latest
|
||||
|
||||
# If we're already on the latest version, check if there are any
|
||||
# visible precusors. If so, we need to rebase their descendants.
|
||||
if repo.revs('allprecursors(%d)', rev):
|
||||
return rev
|
||||
|
||||
# If we don't encounter any changesets with precursors or successors
|
||||
# on the way down, assume the user just wants to recusively fix
|
||||
# the stack upwards from the current changeset.
|
||||
return repo['.'].rev()
|
||||
|
||||
def _findrestacktargets(repo, base):
|
||||
"""Starting from the given base revision, do a BFS forwards through
|
||||
history, looking for changesets with unstable descendants on their
|
||||
precursors. Returns a list of any such changesets, in a top-down
|
||||
ordering that will allow all of the descendants of their precursors
|
||||
to be correctly rebased.
|
||||
"""
|
||||
childrenof = _getchildrelationships(repo, base)
|
||||
|
||||
# Perform BFS starting from base.
|
||||
queue = deque([base])
|
||||
targets = []
|
||||
processed = set()
|
||||
while queue:
|
||||
rev = queue.popleft()
|
||||
|
||||
# Merges may result in the same revision being added to the queue
|
||||
# multiple times. Filter those cases out.
|
||||
if rev in processed:
|
||||
continue
|
||||
|
||||
processed.add(rev)
|
||||
queue.extend(childrenof[rev])
|
||||
|
||||
# Look for visible precursors (which are probably visible because
|
||||
# they have unstable descendants) and successors (for which the latest
|
||||
# non-obsolete version should be visible).
|
||||
precursors = repo.revs('allprecursors(%d)', rev)
|
||||
successors = repo.revs('allsuccessors(%d)', rev)
|
||||
|
||||
# If this changeset has precursors but no successor, then
|
||||
# if its precursors have children those children need to be
|
||||
# rebased onto the changeset.
|
||||
if precursors and not successors:
|
||||
children = []
|
||||
for p in precursors:
|
||||
children.extend(childrenof[p])
|
||||
if children:
|
||||
queue.extend(children)
|
||||
targets.append(rev)
|
||||
|
||||
# We need to perform the rebases in reverse-BFS order so that
|
||||
# obsolescence information at lower levels is not modified by rebases
|
||||
# at higher levels.
|
||||
return reversed(targets)
|
||||
|
||||
def _getchildrelationships(repo, base):
|
||||
"""Build a defaultdict of child relationships between all descendants of
|
||||
base. This information will prevent us from having to repeatedly
|
||||
perform children that reconstruct these relationships each time.
|
||||
"""
|
||||
cl = repo.changelog
|
||||
children = defaultdict(list)
|
||||
for rev in repo.revs('%d:: + allprecursors(%d)::', base, base):
|
||||
for parent in cl.parentrevs(rev):
|
||||
if parent != nullrev:
|
||||
children[parent].append(rev)
|
||||
return children
|
||||
|
||||
def _latest(repo, rev):
|
||||
"""Find the "latest version" of the given revision -- either the
|
||||
latest visible successor, or the revision itself if it has no
|
||||
visible successors. Throws an exception if divergence is
|
||||
detected.
|
||||
"""
|
||||
unfiltered = repo.unfiltered()
|
||||
|
||||
def leadstovisible(rev):
|
||||
"""Return true if the given revision is visble, or if one
|
||||
of the revisions in its chain of successors is visible.
|
||||
"""
|
||||
try:
|
||||
return repo.revs('allsuccessors(%d) + %d', rev, rev)
|
||||
except error.FilteredRepoLookupError:
|
||||
return False
|
||||
|
||||
def getsuccessors(rev):
|
||||
"""Return all successors of the given revision that leads
|
||||
to a visible successor.
|
||||
"""
|
||||
return [
|
||||
r for r in unfiltered.revs('successors(%d)', rev)
|
||||
if leadstovisible(r)
|
||||
]
|
||||
|
||||
# Right now this loop runs in O(n^2) due to the allsuccessors
|
||||
# lookup inside getsuccessors(). This check is neccesary to deal
|
||||
# with unamended changesets (which create situations where
|
||||
# the latest successor is acutally obsolete, and we want a
|
||||
# precursor instead. This logic could probably be made more
|
||||
# sophisticated for better performance.
|
||||
successors = getsuccessors(rev)
|
||||
while successors:
|
||||
if len(successors) > 1:
|
||||
raise error.Abort(_("changeset %s has multiple newer versions, "
|
||||
"cannot automatically determine latest verion")
|
||||
% unfiltered[rev].hex())
|
||||
rev = successors[0]
|
||||
successors = getsuccessors(rev)
|
||||
return rev
|
||||
|
||||
def _clearpreamend(repo, contexts):
|
||||
"""Remove any preamend bookmarks on the given change contexts."""
|
||||
for ctx in contexts:
|
||||
for bookmark in repo.nodebookmarks(ctx.node()):
|
||||
if bookmark.endswith('.preamend'):
|
||||
repo._bookmarks.pop(bookmark, None)
|
||||
|
||||
def _deinhibit(repo, contexts):
|
||||
"""Remove any inhibit markers on the given change contexts."""
|
||||
if inhibitmod:
|
||||
inhibitmod._deinhibitmarkers(repo, (ctx.node() for ctx in contexts))
|
||||
|
||||
def _preamendname(repo, node):
|
||||
suffix = '.preamend'
|
||||
@ -574,13 +744,6 @@ def _usereducation(ui):
|
||||
if education:
|
||||
ui.warn(education + "\n")
|
||||
|
||||
def _clearpreamend(repo, contexts):
|
||||
"""Remove any preamend bookmarks on the given change contexts."""
|
||||
for ctx in contexts:
|
||||
for bookmark in repo.nodebookmarks(ctx.node()):
|
||||
if bookmark.endswith('.preamend'):
|
||||
repo._bookmarks.pop(bookmark, None)
|
||||
|
||||
### bookmarks api compatibility layer ###
|
||||
def bmactivate(repo, mark):
|
||||
try:
|
||||
|
@ -121,7 +121,6 @@ Test multiple amends of same commit.
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 2:4538525df7e2 "add c"
|
||||
$ showgraph
|
||||
@ -191,3 +190,490 @@ Test conflict during rebasing.
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test finding a stable base commit from within the old stack.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ mkcommit d
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 3
|
||||
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 5 add b
|
||||
|
|
||||
| @ 3 add d
|
||||
| |
|
||||
| o 2 add c
|
||||
| |
|
||||
| o 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 2:4538525df7e2 "add c"
|
||||
rebasing 3:47d2a3944de8 "add d"
|
||||
$ showgraph
|
||||
@ 7 add d
|
||||
|
|
||||
o 6 add c
|
||||
|
|
||||
o 5 add b
|
||||
|
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test finding a stable base commit from a new child of the amended commit.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ mkcommit d
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ mkcommit e
|
||||
$ showgraph
|
||||
@ 6 add e
|
||||
|
|
||||
o 5 add b
|
||||
|
|
||||
| o 3 add d
|
||||
| |
|
||||
| o 2 add c
|
||||
| |
|
||||
| o 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 2:4538525df7e2 "add c"
|
||||
rebasing 3:47d2a3944de8 "add d"
|
||||
$ showgraph
|
||||
o 8 add d
|
||||
|
|
||||
o 7 add c
|
||||
|
|
||||
| @ 6 add e
|
||||
|/
|
||||
o 5 add b
|
||||
|
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test finding a stable base commit when there are multiple amends and
|
||||
a commit on top of one of the obsolete intermediate commits.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ mkcommit d
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ mkcommit e
|
||||
$ hg prev
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
[5] add b
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 6
|
||||
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 8 add b
|
||||
|
|
||||
| @ 6 add e
|
||||
| |
|
||||
| o 5 add b
|
||||
|/
|
||||
| o 3 add d
|
||||
| |
|
||||
| o 2 add c
|
||||
| |
|
||||
| o 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 2:4538525df7e2 "add c"
|
||||
rebasing 3:47d2a3944de8 "add d"
|
||||
rebasing 6:c1992d8998fa "add e"
|
||||
$ showgraph
|
||||
@ 11 add e
|
||||
|
|
||||
| o 10 add d
|
||||
| |
|
||||
| o 9 add c
|
||||
|/
|
||||
o 8 add b
|
||||
|
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test that we only use the closest stable base commit.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ mkcommit d
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 2
|
||||
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ echo c >> c
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 3
|
||||
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 7 add c
|
||||
|
|
||||
| o 5 add b
|
||||
| |
|
||||
| | @ 3 add d
|
||||
| | |
|
||||
+---o 2 add c
|
||||
| |
|
||||
o | 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 3:47d2a3944de8 "add d"
|
||||
$ showgraph
|
||||
@ 8 add d
|
||||
|
|
||||
o 7 add c
|
||||
|
|
||||
| o 5 add b
|
||||
| |
|
||||
o | 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test what happens if there is no base commit found. The command should
|
||||
fix up everything above the current commit, leaving other commits
|
||||
below the current commit alone.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ mkcommit d
|
||||
$ mkcommit e
|
||||
$ hg up 3
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
$ echo d >> d
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 0
|
||||
0 files updated, 0 files merged, 3 files removed, 0 files unresolved
|
||||
$ mkcommit f
|
||||
created new head
|
||||
$ hg up 1
|
||||
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 7 add f
|
||||
|
|
||||
| o 6 add d
|
||||
| |
|
||||
| | o 4 add e
|
||||
| | |
|
||||
| | o 3 add d
|
||||
| |/
|
||||
| o 2 add c
|
||||
| |
|
||||
| @ 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 4:9d206ffc875e "add e"
|
||||
$ showgraph
|
||||
o 8 add e
|
||||
|
|
||||
| o 7 add f
|
||||
| |
|
||||
o | 6 add d
|
||||
| |
|
||||
o | 2 add c
|
||||
| |
|
||||
@ | 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test having an unamended commit.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ hg prev
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
[1] add b
|
||||
$ echo b >> b
|
||||
$ hg amend -m "Amended"
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ echo b >> b
|
||||
$ hg amend -m "Unamended"
|
||||
$ hg unamend
|
||||
$ hg up -C 1
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 4 Amended
|
||||
|
|
||||
| o 2 add c
|
||||
| |
|
||||
| @ 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 2:4538525df7e2 "add c"
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 7 add c
|
||||
|
|
||||
@ 4 Amended
|
||||
|
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test situation with divergence.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ hg prev
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
[1] add b
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 1
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ echo c >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 1
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 6 add b
|
||||
|
|
||||
| o 4 add b
|
||||
|/
|
||||
| o 2 add c
|
||||
| |
|
||||
| @ 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
abort: changeset 7c3bad9141dcb46ff89abf5f61856facd56e476c has multiple newer versions, cannot automatically determine latest verion
|
||||
[255]
|
||||
|
||||
Test situation with divergence due to an unamend. This should actually succeed
|
||||
since the successor is obsolete.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ hg prev
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
[1] add b
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 1
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ echo c >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg unamend
|
||||
$ hg up -C 1
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 4 add b
|
||||
|
|
||||
| o 2 add c
|
||||
| |
|
||||
| @ 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 2:4538525df7e2 "add c"
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 7 add c
|
||||
|
|
||||
@ 4 add b
|
||||
|
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test recursive restacking -- basic case.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ mkcommit d
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 2
|
||||
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ echo c >> c
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 7 add c
|
||||
|
|
||||
| o 5 add b
|
||||
| |
|
||||
| | o 3 add d
|
||||
| | |
|
||||
+---o 2 add c
|
||||
| |
|
||||
@ | 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 3:47d2a3944de8 "add d"
|
||||
rebasing 7:a43fcd08f41f "add c" (tip)
|
||||
rebasing 8:49b119a57122 "add d"
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 10 add d
|
||||
|
|
||||
o 9 add c
|
||||
|
|
||||
@ 5 add b
|
||||
|
|
||||
o 0 add a
|
||||
|
||||
|
||||
Test recursive restacking -- more complex case. This test is designed to
|
||||
to check for a bug encountered if rebasing is performed naively from the
|
||||
bottom-up wherein obsolescence information for commits further up the
|
||||
stack is lost upon rebasing lower levels.
|
||||
$ reset
|
||||
$ mkcommit a
|
||||
$ mkcommit b
|
||||
$ mkcommit c
|
||||
$ mkcommit d
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
|
||||
$ echo b >> b
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ mkcommit e
|
||||
$ mkcommit f
|
||||
$ hg prev
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
[6] add e
|
||||
$ echo e >> e
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 2
|
||||
2 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
$ echo c >> c
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ mkcommit g
|
||||
$ mkcommit h
|
||||
$ hg prev
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
[12] add g
|
||||
$ echo g >> g
|
||||
$ hg amend
|
||||
warning: the changeset's children were left behind
|
||||
(use 'hg amend --fixup' to rebase them)
|
||||
$ hg up 1
|
||||
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 15 add g
|
||||
|
|
||||
| o 13 add h
|
||||
| |
|
||||
| o 12 add g
|
||||
|/
|
||||
o 11 add c
|
||||
|
|
||||
| o 9 add e
|
||||
| |
|
||||
| | o 7 add f
|
||||
| | |
|
||||
| | o 6 add e
|
||||
| |/
|
||||
| o 5 add b
|
||||
| |
|
||||
| | o 3 add d
|
||||
| | |
|
||||
+---o 2 add c
|
||||
| |
|
||||
@ | 1 add b
|
||||
|/
|
||||
o 0 add a
|
||||
|
||||
$ hg rebase --restack
|
||||
rebasing 13:9f2a7cefd4b4 "add h"
|
||||
rebasing 3:47d2a3944de8 "add d"
|
||||
rebasing 7:2a79e3a98cd6 "add f"
|
||||
rebasing 11:a43fcd08f41f "add c"
|
||||
rebasing 15:604f34a1983d "add g" (tip)
|
||||
rebasing 16:e1df23499b99 "add h"
|
||||
rebasing 17:49b119a57122 "add d"
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ showgraph
|
||||
o 22 add d
|
||||
|
|
||||
| o 21 add h
|
||||
| |
|
||||
| o 20 add g
|
||||
|/
|
||||
o 19 add c
|
||||
|
|
||||
| o 18 add f
|
||||
| |
|
||||
| o 9 add e
|
||||
|/
|
||||
@ 5 add b
|
||||
|
|
||||
o 0 add a
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user