Skip to content

Commit 9303372

Browse files
authored
Merge pull request #132 from mhagger/reparent-specific-commit
reparent: add a `--commit` option
2 parents 269969e + c7b96a3 commit 9303372

File tree

1 file changed

+63
-5
lines changed

1 file changed

+63
-5
lines changed

git-imerge

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3628,19 +3628,63 @@ def cmd_diagram(parser, options):
36283628
)
36293629

36303630

3631+
def reparent_recursively(git, start_commit, parents, end_commit):
3632+
"""Change the parents of start_commit and its descendants.
3633+
3634+
Change start_commit to have the specified parents, and reparent
3635+
all commits on the ancestry path between start_commit and
3636+
end_commit accordingly. Return the replacement end_commit.
3637+
start_commit, parents, and end_commit must all be resolved OIDs.
3638+
3639+
"""
3640+
3641+
# A map {old_oid : new_oid} keeping track of which replacements
3642+
# have to be made:
3643+
replacements = {}
3644+
3645+
# Reparent start_commit:
3646+
replacements[start_commit] = git.reparent(start_commit, parents)
3647+
3648+
for (commit, parents) in git.rev_list_with_parents(
3649+
'--ancestry-path', '--topo-order', '--reverse',
3650+
'%s..%s' % (start_commit, end_commit)
3651+
):
3652+
parents = [replacements.get(p, p) for p in parents]
3653+
replacements[commit] = git.reparent(commit, parents)
3654+
3655+
try:
3656+
return replacements[end_commit]
3657+
except KeyError:
3658+
raise ValueError(
3659+
"%s is not an ancestor of %s" % (start_commit, end_commit),
3660+
)
3661+
3662+
36313663
def cmd_reparent(parser, options):
36323664
git = GitRepository()
36333665
try:
3634-
commit_sha1 = git.get_commit_sha1('HEAD')
3666+
commit = git.get_commit_sha1(options.commit)
3667+
except ValueError:
3668+
sys.exit('%s is not a valid commit', options.commit)
3669+
3670+
try:
3671+
head = git.get_commit_sha1('HEAD')
36353672
except ValueError:
36363673
sys.exit('HEAD is not a valid commit')
36373674

36383675
try:
3639-
parent_sha1s = [git.get_commit_sha1(p) for p in options.parents]
3676+
parents = [git.get_commit_sha1(p) for p in options.parents]
3677+
except ValueError as e:
3678+
sys.exit(e.message)
3679+
3680+
sys.stderr.write('Reparenting %s..HEAD\n' % (options.commit,))
3681+
3682+
try:
3683+
new_head = reparent_recursively(git, commit, parents, head)
36403684
except ValueError as e:
36413685
sys.exit(e.message)
36423686

3643-
sys.stdout.write('%s\n' % (git.reparent(commit_sha1, parent_sha1s),))
3687+
sys.stdout.write('%s\n' % (new_head,))
36443688

36453689

36463690
def main(args):
@@ -3927,10 +3971,24 @@ def main(args):
39273971

39283972
subparser = subparsers.add_parser(
39293973
'reparent',
3930-
help='change the parents of the HEAD commit',
3974+
help=(
3975+
'change the parents of the specified commit and propagate the '
3976+
'change to HEAD'
3977+
),
39313978
)
39323979
subparser.add_argument(
3933-
'parents', nargs='*', help='[PARENT...]',
3980+
'--commit', metavar='COMMIT', default='HEAD',
3981+
help=(
3982+
'target commit to reparent. Create a new commit identical to '
3983+
'this one, but having the specified parents. Then create '
3984+
'new versions of all descendants of this commit all the way to '
3985+
'HEAD, incorporating the modified commit. Output the SHA-1 of '
3986+
'the replacement HEAD commit.'
3987+
),
3988+
)
3989+
subparser.add_argument(
3990+
'parents', nargs='*', metavar='PARENT',
3991+
help='a list of commits',
39343992
)
39353993

39363994
options = parser.parse_args(args)

0 commit comments

Comments
 (0)