问题
is it possible to rebase a branch with all it's subbranches in git?
i often use branches as quick/mutable tags to mark certain commits.
* master
*
* featureA-finished
*
* origin/master
now i want to rebase -i
master
onto origin/master
, to change/reword the commit featureA-finished^
after git rebase -i --onto origin/master origin/master master
, i basically want the history to be:
* master
*
* featureA-finished
* (changed/reworded)
* origin/master
but what i get is:
* master
*
* (same changeset as featureA-finished)
* (changed/reworded)
| * featureA-finished
|.* (original commit i wanted to edit)
* origin/master
is there a way around it, or am i stuck with recreating the branches on the new rebased commits?
回答1:
According to git's Object Model if you only change the meta-data of a commit (i.e. commit message) but not the underlying data ("tree(s)") contained within it then it's Tree hash will remain unchanged.
Aside from editing a commit message, you are also performing a rebase, which will change the Tree hashes of each commit in your history, because any changes pulled from origin/master
will affect the files in your re-written history: which means some of the files (blobs) that your commit points to have changed.
So there is no bullet-proof way to do what you want.
That said, editing a commit with rebase -i
does not usually alter the commit's timestamp and author, so you could use this to uniquely identify your commits before and after a rebase operation.
You would have to write a script which records all the branch start-points against these "timestamp:author" identifier before doing a rebase, and then find the rewritten commits with the same "timestamp:author" ID and rebase the branch on it.
Sadly, I don't have time to try writing this script myself now, so I can only wish you the best of luck!
Edit: You can obtain the author email address and timestamp using:
$ git log --graph --all --pretty=format:"%h %ae:%ci"
* 53ca31a robert.meerman@gmail.com:2010-06-16 13:50:12 +0100
* 03dda75 robert.meerman@gmail.com:2010-06-16 13:50:11 +0100
| * a8bb03a robert.meerman@gmail.com:2010-06-16 13:49:46 +0100
| * b93e59d robert.meerman@gmail.com:2010-06-16 13:49:44 +0100
|/
* d4214a2 robert.meerman@gmail.com:2010-06-16 13:49:41 +0100
And you can obtain a list of branches for each of these based on their commit hash:
$ git branch --contains 03dda75
* testbranch
Watch out for multiple branches per commit, the common ancestor d4214a2
belongs to both branches!
回答2:
I am not sure how exactly you got there, but:
git branch -f (same changeset as featureA-finished)
should be enough to reset your featureA-finished
branch with the right history.
回答3:
looks like this feature is slowly getting into git. rebase
will gain the option --rebase-refs
which will do exactly what my original answer asked. for the proposed patch series see the thread rebase: command "ref" and options --rewrite-{refs,heads,tags} on gmane.
回答4:
What I'd advise is to rebase featureA-finished
onto origin/master
first. Do the rewording step then. After that, rebase master
onto featureA-finished
. This will net you the end result you are wanting.
Note that you'll need to use -i
on both rebases, and may have to delete all the commits from the original featureA-finshed
down in the second rebase. If you wanted, you could write a script that would eliminate this by saving off the intermediate branch and using that as the base for a rebase --onto
the new version. It could even handle a sequence of such 'subbranches' if you wrote it right. If you need help I can attempt to bang one out.
来源:https://stackoverflow.com/questions/2730866/git-rebase-branch-with-all-subbranches