How to undo a commit and commit the changes into the other branch in Git?

后端 未结 3 563
醉话见心
醉话见心 2021-01-01 04:41

The common mistake I make in git is

  1. not check on which branch I am
  2. commit changes to a wrong branch (on branch B, thinking I\'m on A, commiting a chan
相关标签:
3条回答
  • 2021-01-01 05:08

    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)

    0 讨论(0)
  • 2021-01-01 05:09

    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.

    0 讨论(0)
  • 2021-01-01 05:16

    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 of tmp (tmp being the previous rightBranch 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)
    0 讨论(0)
提交回复
热议问题