git-reparent - Recommit HEAD with a new set of parents.
git reparent [OPTIONS] ((-p <parent>)... | --no-parent)
Create a new commit object that has the same tree and commit message as HEAD
but with a different set of parents. If --no-reset
is given, the full
object id of this commit is printed and the program exits; otherwise, git
reset
is used to update HEAD and the current branch to this new commit.
This command can be used to manually shape the history of a repository.
Whereas git rebase
moves around diffs, git reparent
moves around
snapshots. See EXAMPLES for a reason why you might want to use this
command.
-h, --help | show the help |
-e, --edit | edit the commit message in an editor first |
-m, --message <message> | |
use the given message instead of that of HEAD | |
-p, --parent <commit> | |
new parent to use; may be given multiple times | |
--no-parent | create a parentless commit |
-q, --quiet | be quiet; only report errors |
--no-reset | print the new object id instead of updating HEAD |
Make executable and place somewhere in your $PATH.
Suppose we create some commit B and then accidentally pass the --amend
flag when creating new commit C, resulting in the following history:
B / ...---A---C (HEAD)
What we really wanted was one linear history, ...---A--B--C
. If we
were to use git rebase
or git cherry-pick
to reconstruct the history,
this would try to apply the diff of A..C onto B, which might fail.
Instead, what we really want to do is use the exact message and tree from C
but with parent B instead of A. To do this, we run
$ git reparent -p B
where the name B can be found by running git reflog
and looking for the
first "commit (amend)". The resulting history is now just what we wanted:
C / ...---A---B---C' (HEAD)
We can also update the parents of a commit other than the most recent. Suppose that we want to perform a rebase-like operation, moving master onto origin/master, but we want to completely ignore any changes made in the remote branch. That is, our history currently looks like this:
B---C (master, HEAD) / ...---A---D---E (origin/master)
and we want to make it look like this:
B---C (origin/master) / / ...---A---D---E---B'---C' (master, HEAD)
We can accomplish this by using git rebase --interactive
along with git
reparent
:
$ git rebase -i A
# select the "edit" command for commit B
# git rebase will dump us out at commit B
$ git reparent -p origin/master
$ git rebase --continue
Now the history will look as desired, and the trees, commit messages, and authors of B' and C' will be identical to those of B and C, respectively.
git-filter-branch(1) combined with either git grafts or git-replace(1) can be used to achieve the same effect
git-rebase(1) can be used to re-apply the diffs of the current branch to another
Mark Lodato <lodato@google.com>
Copyright 2013 Google Inc.
Distributed under the GNU General Public License, version 2.0.