mirror of
https://chromium.googlesource.com/chromium/tools/depot_tools.git
synced 2026-01-11 18:51:29 +00:00
Fix "git rebase-update" when multiple branch are stale.
Fix a bug that left branches tracking a dead branch if both their parent
and grand-parent were left with no changes after a "rebase-update" step.
Given the following initial state:
$ git map-branches -v
origin/master
a
b
c * [ ahead 1 ]
without this patch, a "git rebase-update" on this tree state would
leave the branch "c" as tracking a non-existing branch "a":
$ git recursive-rebase
a up-to-date
b up-to-date
c up-to-date
Reparented c to track a (was tracking b)
Deleted branch b (was 448d1da).
Deleted branch a (was 448d1da).
$ git map-branches -v
{a:GONE}
c *
with the patch, we record that the branch "c" is tracking must be
updated twice and we end up in a state were "c" is correctly tracking
"origin/master":
$ git recursive-rebase
a up-to-date
b up-to-date
c up-to-date
Reparented c to track origin/master (was tracking b)
Deleted branch b (was 448d1da).
Deleted branch a (was 448d1da).
$ git map-branches -v
origin/master
c * [ ahead 1 ]
BUG=456806
Review URL: https://codereview.chromium.org/1482753002
git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@297792 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@@ -87,32 +87,54 @@ def remove_empty_branches(branch_tree):
|
||||
tag_set = git.tags()
|
||||
ensure_root_checkout = git.once(lambda: git.run('checkout', git.root()))
|
||||
|
||||
deletions = set()
|
||||
deletions = {}
|
||||
reparents = {}
|
||||
downstreams = collections.defaultdict(list)
|
||||
for branch, parent in git.topo_iter(branch_tree, top_down=False):
|
||||
downstreams[parent].append(branch)
|
||||
|
||||
# If branch and parent have the same state, then branch has to be marked
|
||||
# for deletion and its children and grand-children reparented to parent.
|
||||
if git.hash_one(branch) == git.hash_one(parent):
|
||||
ensure_root_checkout()
|
||||
|
||||
logging.debug('branch %s merged to %s', branch, parent)
|
||||
|
||||
# Mark branch for deletion while remembering the ordering, then add all
|
||||
# its children as grand-children of its parent and record reparenting
|
||||
# information if necessary.
|
||||
deletions[branch] = len(deletions)
|
||||
|
||||
for down in downstreams[branch]:
|
||||
if down in deletions:
|
||||
continue
|
||||
|
||||
if parent in tag_set:
|
||||
git.set_branch_config(down, 'remote', '.')
|
||||
git.set_branch_config(down, 'merge', 'refs/tags/%s' % parent)
|
||||
print ('Reparented %s to track %s [tag] (was tracking %s)'
|
||||
% (down, parent, branch))
|
||||
# Record the new and old parent for down, or update such a record
|
||||
# if it already exists. Keep track of the ordering so that reparenting
|
||||
# happen in topological order.
|
||||
downstreams[parent].append(down)
|
||||
if down not in reparents:
|
||||
reparents[down] = (len(reparents), parent, branch)
|
||||
else:
|
||||
git.run('branch', '--set-upstream-to', parent, down)
|
||||
print ('Reparented %s to track %s (was tracking %s)'
|
||||
% (down, parent, branch))
|
||||
order, _, old_parent = reparents[down]
|
||||
reparents[down] = (order, parent, old_parent)
|
||||
|
||||
deletions.add(branch)
|
||||
print git.run('branch', '-d', branch)
|
||||
# Apply all reparenting recorded, in order.
|
||||
for branch, value in sorted(reparents.iteritems(), key=lambda x:x[1][0]):
|
||||
_, parent, old_parent = value
|
||||
if parent in tag_set:
|
||||
git.set_branch_config(branch, 'remote', '.')
|
||||
git.set_branch_config(branch, 'merge', 'refs/tags/%s' % parent)
|
||||
print ('Reparented %s to track %s [tag] (was tracking %s)'
|
||||
% (branch, parent, old_parent))
|
||||
else:
|
||||
git.run('branch', '--set-upstream-to', parent, branch)
|
||||
print ('Reparented %s to track %s (was tracking %s)'
|
||||
% (branch, parent, old_parent))
|
||||
|
||||
# Apply all deletions recorded, in order.
|
||||
for branch, _ in sorted(deletions.iteritems(), key=lambda x: x[1]):
|
||||
print git.run('branch', '-d', branch)
|
||||
|
||||
|
||||
def rebase_branch(branch, parent, start_hash):
|
||||
|
||||
Reference in New Issue
Block a user