-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a parameter --commit-to-reparent for the reparent command so #130
base: master
Are you sure you want to change the base?
Conversation
that a list of commits starting from a specified commit to HEAD can be reparented in a cascading manner.
reparent operation should use individual commit's parent to reconstruct the parents.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch! Sorry it took so long for me to review it. I left a bunch of comments on it.
I will write up a modified version of your patch that works correctly for more complicated commit topologies. I'm curious if it works for you.
@@ -3717,6 +3749,18 @@ def main(args): | |||
help='the tip of the branch to be merged into HEAD', | |||
) | |||
|
|||
def add_commit_to_reparent_argument(subparser): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need for this to be in a function, since it is only called once. (add_*_option()
functions are used when the same option applies to multiple commands.)
@@ -3717,6 +3749,18 @@ def main(args): | |||
help='the tip of the branch to be merged into HEAD', | |||
) | |||
|
|||
def add_commit_to_reparent_argument(subparser): | |||
subparser.add_argument( | |||
'--commit-to-reparent', dest='commit_to_reparent', action='store', default=None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I think it would be ok to name this option
--commit
. dest
is redundant because that's the default.action
is redundant because'store'
is the default action.default=None
is redundant because that is the default. However, don't you actually wantdefault='HEAD'
here? That would remove the need forcmd_reparent
to check this argument and set it toHEAD
if it was missing.
'reparent operation creates a new commit object like the original commit, but with the specified parents. ' | ||
'reparent command first executes the reparent operation on the commit specified by the --commit-to-reparent argument to generate a new commit object, ' | ||
'then it uses this object to replace the first parent of its child commit on the path towards the HEAD commit.\n' | ||
'the command repeats this process till the HEAD commit so that a list of new commit objects are created.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please limit lines to 79 characters.
help=( | ||
'[PARENT...] \n' | ||
'parents is a list of SHA1.\n' | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline characters don't have an effect in help strings. And instead of starting the help string with [PARENT...]
, you can set metavar='PARENT'
.
@@ -3629,9 +3629,22 @@ def cmd_diagram(parser, options): | |||
|
|||
|
|||
def cmd_reparent(parser, options): | |||
if len(options.parents) == 0: | |||
parser.error('Parent is not specified, please specify at least one parent.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you add this new restriction? It is perfectly sensible to set a commit to have zero parents; in that case, the commit becomes an orphan commit (i.e., like the first commit made in a fresh repository).
@@ -3640,8 +3653,27 @@ def cmd_reparent(parser, options): | |||
except ValueError as e: | |||
sys.exit(e.message) | |||
|
|||
sys.stdout.write('%s\n' % (git.reparent(commit_sha1, parent_sha1s),)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not OK to remove this output or complicate it. The reparent
command is pretty useless if you don't do anything with its output (because it doesn't change any references itself). And likely people want to use the output directly; e.g.,
git update-ref refs/heads/mynewbranch $(git imerge reparent $PARENT)
This works with the old code because the only thing that it outputs to stdout is the final SHA-1. But it won't work with your changes.
@@ -3629,9 +3629,22 @@ def cmd_diagram(parser, options): | |||
|
|||
|
|||
def cmd_reparent(parser, options): | |||
if len(options.parents) == 0: | |||
parser.error('Parent is not specified, please specify at least one parent.') | |||
sys.stdout.write('Reparenting from HEAD to %s...\n' % options.commit_to_reparent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not appropriate to emit progress messages to stdout. They should go to stderr so that the stdout can be piped to another program.
def iterative_reparent(head, commit_to_reparent, parents, git): | ||
commit_list = [head]; | ||
current_commit = head; | ||
while current_commit != commit_to_reparent: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This loop will totally fail (with an IndexError
, I believe) if commit_to_reparent
is not a first-parent ancestor of head
. I understand that this will never be the case the way you want to use the program, but other people might want to use it other ways, and it shouldn't crash for them.
It's not very much harder to rewrite this so that it works for any ancestor of head (not just first-parent ancestors). I'll try to implement that.
current_parents = parents | ||
else: | ||
current_parents = git.get_commit_parents(commit_list[i]) | ||
current_parents = [new_commit] + current_parents[1:len(current_parents)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to do something screwy if there is more than one ancestry path between commit_to_reparent
and head
. For example, suppose that there was a merge in between:
o---A---C---D---E---F---H
/ \ /
o---B X---Y
and you run git imerge reparent --commit-to-reparent C A
. This algorithm will only rewrite commits C
, D
, E
, F
, and H
, but won't rewrite X
or Y
. The result will not be the hoped-for
o---A---C'--D'--E'--F'--H'
\ /
X'--Y'
but I think will look like this instead:
C'--D'--E'------F'--H'
/ /
o---A---C---D /
/ \ /
o---B X---Y
I understand that you are not interested in this case, but it's not that much harder to handle it correctly.
Add an option `git imerge reparent --commit=COMMIT`, which allows the parents of an arbitrary commit to be changed. Moreover, the descendants of COMMIT are also rewritten all the way to HEAD. This feature was suggested by Ke Ma <[email protected]>, and the implementation is partly derived from PR #130 submitted by Ke Ma.
Add an option `git imerge reparent --commit=COMMIT`, which allows the parents of an arbitrary commit to be changed. Moreover, the descendants of COMMIT are also rewritten all the way to HEAD. This feature was suggested by Ke Ma <[email protected]>, and the implementation is partly derived from PR #130 submitted by Ke Ma.
that a list of commits starting from a specified commit to HEAD can be reparented in a cascading manner.
@mhagger