| Index: git_rebase_update.py
|
| diff --git a/git_rebase_update.py b/git_rebase_update.py
|
| index 992bb195dbd2a383d3c606e8e73dfb9d93bbcbc4..9d5755e9f0850c84b7373d40dc2803d4a2269bd4 100755
|
| --- a/git_rebase_update.py
|
| +++ b/git_rebase_update.py
|
| @@ -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)
|
| +
|
| + # 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))
|
|
|
| - deletions.add(branch)
|
| - print git.run('branch', '-d', branch)
|
| + # 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):
|
|
|