The common mistake I make in git is
- not check on which branch I am
- commit changes to a wrong branch (on branch B, th开发者_如何转开发inking I'm on A, commiting a change for feature A)
How do I get back, and commit the edits to the proper branch?
rebase --onto
can help here, especially if you have a range of commits to move back.
Do not forget a git stash
to save any current uncommitted changes which are relevant to "wrongBranch
" (the one where commits were appropriately applied), in order to pop them back at the end of the process.
Basically, you need to apply a commit or range of commits to another branch (called here "rightBranch
"):
# Checkout the right branch where the commit should have been applied
git checkout rightBranch
# Checkout a new temporary branch at the current location
git checkout -b tmp
# Move the rightBranch branch to the head of patchset which should have been on rightBranch
git branch -f rightBranch last_SHA-1_of_commits_for_rightBranch
# Rebase the patchset onto tmp, the old location of rightBranch
git rebase --onto tmp first_SHA-1_of_commits_for_rightBranch~1 rightBranch
(first_SHA-1_of_commits_for_rightBranch~1
is the parent commit of first_SHA-1_of_commits_for_rightBranch
, that is the commit on top of which all the commits for rightBranch have been incorrectly applied)
rightBranch
will be again at the top of:
- all the old commits of right branch (pointed by the
tmp
branch) - plus all the relevant commits range from
wrongBranch
, which have just been replayed on top oftmp
(tmp
being the previousrightBranch HEAD
).
Then you can reset wrongBranch
to some previous commits.
git checkout wrongBranch
git reset --hard some_older_commit
# if needed, re-apply what you were working on vefore this all proccess
git stash pop
Caveat:
- cherry-picking or rebase --onto have consequences (see this question)
- if
wrongBranch
has already been published (pushed to a public repo), that can be awkward for the people pulling for that repo (having to rebase all their changes on top of that "new" branch)
Simple answer?
git checkout branch_with_wrong_tip
git reset HEAD~1 (or whatever number of commits you want to go back)
git checkout correct_branch
git commit ...etc
Note the important part, which is the soft reset (retaining changes) as opposed to any hard reset, which might let you lose the place of changes.
This will also turn all those commits that you reset back into changes that you'd then have to recommit individually or as a group. E.g. if you git reset HEAD~10, you're going to have to make commits to all those files that were committed in the 10 commits, or else lump them into a totally new commit. That's just if you use this approach, of course.
Checkout the wrong branch where the commit is
git checkout wrong_branch
In the wrong branch, reset to the previous commit:
git reset --hard HEAD^
NOTE: the ^ operator indicating the previous commit, to remove multiple commits use ~N where N is the number of commits
Checkout to the branch where the commit should be
git checkout right_branch
Re-apply the commit using cherry-pick
git cherry-pick wrong_branch@{1}
NOTE: wrong_branch@{1} is the last commit of wrong_branch before the git reset command was executed, for example, HEAD@{2} could be used too in this case
To move multiple commits you could use multiple calls to git cherry-pick or only one execution of git rebase:
git rebase --onto right_branch wrong_branch@{1}~N wrong_branch@{1}
(and the corresponding parameter to reset will be HEAD~N in this case)
精彩评论