Search code examples
gitgit-branchbranching-and-merging

Move the most recent commit(s) to a new branch with Git


How do I move my recent commits on master to a new branch, and reset master to before those commits were made? e.g. From this:

master A - B - C - D - E

To this:

newbranch     C - D - E
             /
master A - B 

Solution

  • WARNING: You need to store uncommitted edits to your stash before doing this, using git stash. Once complete, you can retrieve the stashed uncommitted edits with git stash pop. git reset hard command will remove all changes!

    Moving to an existing branch

    If you want to move your commits to an existing branch, it will look like this:

    git checkout existingbranch
    git merge branchToMoveCommitFrom
    git checkout branchToMoveCommitFrom
    git reset --hard HEAD~3 # Go back 3 commits. You *will* lose uncommitted work.
    git checkout existingbranch
    

    Moving to a new branch

    WARNING: This method works because you are creating a new branch with the first command: git branch newbranch. If you want to move commits to an existing branch you need to merge your changes into the existing branch before executing git reset --hard HEAD~3 (see Moving to an existing branch above). If you don't merge your changes first, they will be lost.

    Unless there are other circumstances involved, this can be easily done by branching and rolling back.

    # Note: Any changes not committed will be lost.
    git branch newbranch      # Create a new branch, saving the desired commits
    git checkout master       # checkout master, this is the place you want to go back
    git reset --hard HEAD~3   # Move master back by 3 commits (Make sure you know how many commits you need to go back)
    git checkout newbranch    # Go to the new branch that still has the desired commits
    

    But do make sure how many commits to go back. Alternatively, you can instead of HEAD~3, simply provide the hash of the commit (or the reference like origin/master) you want to "revert back to" on the master (/current) branch, e.g:

    git reset --hard a1b2c3d4
    

    Note: You will only be "losing" commits from the master branch, but don't worry, you'll have those commits in newbranch! An easy way to check that, after completing the 4 step sequence of commands above, is by looking at git log -n4 which will show the history of newbranch actually retained the 3 commits (and the reason is that newbranch was created at the time those changes were already commited on master!). They have only been removed from master, as git reset only affected the branch that was checked out at the time of its execution, i.e. master (see git reset description: Reset current HEAD to the specified state). git status however will not show any checkouts on the newbranch, which might be surprising at first but that is actually expected.

    Lastly, you may need to force push your latest changes to main repo:

    git push origin master --force
    

    WARNING: With Git version 2.0 and later, if you later git rebase the new branch upon the original (master) branch, you may need an explicit --no-fork-point option during the rebase to avoid losing the carried-over commits. Having branch.autosetuprebase always set makes this more likely. See John Mellor's answer for details.