Categories
branching-and-merging git git-branch

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

6031

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 

6

  • 150

    Note: I asked the opposite question here

    – Benjol

    Dec 16, 2010 at 8:56

  • 4

    eddmann.com/posts/… this one works

    Apr 25, 2017 at 6:35

  • 18

    Were the comments here purged? I ask because during my bimonthly visit to this question, I always scroll by that comment.

    Mar 19, 2018 at 14:02


  • 1

    Side-comment: The question is about a very simple case. Reading the answers and all the “don’t do this because…” and “a better solution is…” and “warning with version n+…” just after the answers (possibly when it’s too late), it seems to me even very simple operations have no straight solutions in git. A graphical version manager where you would just add a tag for the new branch without dealing with what seems to me obscure and archaic syntax would be such a relief. My kingdom and my gold badges to the first one who “forks” git and starts a new approach 😉 it’s urgent.

    – mins

    Jun 15, 2020 at 10:57

  • 1

    Be sure to read through the first ten answers (or so), as the best are not the most upvoted.

    – chb

    Jun 24, 2021 at 23:17


7786

+50

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 master
git checkout master
git reset --hard HEAD~3 # Go back 3 commits. You *will* lose uncommitted work.
git checkout existingbranch

You can 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

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

*1 You will only be “losing” commits from the master branch, but don’t worry, you’ll have those commits in newbranch!

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.

38

  • 275

    And in particular, don’t try to go back further than the point where you last pushed commits to another repository from which somebody else might have pulled.

    Oct 27, 2009 at 3:23

  • 122

    Wondering if you can explain WHY this works. To me you’re creating a new branch, removing 3 commits from the old branch you are still on, and then checking out the branch you made. So how do the commits you removed magically show up in the new branch?

    Aug 3, 2010 at 18:28

  • 153

    @Jonathan Dumaine: Because I created the new branch before removing the commits from the old branch. They’re still there in the new branch.

    – sykora

    Aug 4, 2010 at 8:28

  • 96

    branches in git are just markers which point to commits in history, there is nothing being cloned, created or deleted (except the markers)

    – knittl

    Aug 16, 2010 at 11:32

  • 247

    Also note: Don’t do this with uncommitted changes in your working copy! This just bit me! 🙁

    Oct 25, 2011 at 3:59

1200

For those wondering why it works (as I was at first):

You want to go back to C, and move D and E to the new branch. Here’s what it looks like at first:

A-B-C-D-E (HEAD)
        ↑
      master

After git branch newBranch:

    newBranch
        ↓
A-B-C-D-E (HEAD)
        ↑
      master

After git reset --hard HEAD~2:

    newBranch
        ↓
A-B-C-D-E (HEAD)
    ↑
  master

Since a branch is just a pointer, master pointed to the last commit. When you made newBranch, you simply made a new pointer to the last commit. Then using git reset you moved the master pointer back two commits. But since you didn’t move newBranch, it still points to the commit it originally did.

9

  • 75

    I also needed to do a git push origin master --force for the change to show up in main repository.

    – Dženan

    Nov 26, 2014 at 19:20


  • 14

    This answer causes commits to be lost: next time you git rebase, the 3 commits will be silently discarded from newbranch. See my answer for details and safer alternatives.

    Apr 6, 2016 at 22:47

  • 21

    @John, that’s nonsense. Rebasing without knowing what you’re doing causes commits to be lost. If you lost commits, I’m sorry for you, but this answer didn’t lose your commits. Note that origin/master doesn’t appear in the above diagram. If you pushed to origin/master and then made the changes above, sure, things would go funny. But that’s a “Doctor, it hurts when I do this” kind of problem. And it’s out of scope for what the original question asked. I suggest you write your own question to explore your scenario instead of hijacking this one.

    Apr 7, 2016 at 3:20

  • 1

    @John, in your answer, you said “Don’t do this! git branch -t newbranch“. Go back and read the answers again. Nobody suggested doing that.

    Apr 7, 2016 at 15:02

  • 1

    @Kyralessa, sure, but if you look at the diagram in the question, it’s clear that they want newbranch to be based off their existing local master branch. After performing the accepted answer, when the user gets around to running git rebase in newbranch, git will remind them that they forgot to set the upstream branch, so they’ll run git branch --set-upstream-to=master then git rebase and have the same problem. They may as well use git branch -t newbranch in the first place.

    Apr 7, 2016 at 15:32


548

In General…

The method exposed by sykora is the best option in this case. But sometimes is not the easiest and it’s not a general method. For a general method use git cherry-pick:

To achieve what OP wants, its a 2-step process:

Step 1 – Note which commits from master you want on a newbranch

Execute

git checkout master
git log

Note the hashes of (say 3) commits you want on newbranch. Here I shall use:
C commit: 9aa1233
D commit: 453ac3d
E commit: 612ecb3

Note: You can use the first seven characters or
the whole commit hash

Step 2 – Put them on the newbranch

git checkout newbranch
git cherry-pick 612ecb3
git cherry-pick 453ac3d
git cherry-pick 9aa1233

OR (on Git 1.7.2+, use ranges)

git checkout newbranch
git cherry-pick 612ecb3~1..9aa1233

git cherry-pick applies those three commits to newbranch.

14

  • 14

    This works very well if you accidentally commit the wrong, non-master branch, when you should have created a new feature branch.

    – julianc

    Feb 27, 2014 at 16:47

  • 6

    The information on git cherry-pick is nice, but the commands in this post don’t work. 1) the ‘git checkout newbranch’ should be ‘git checkout -b newbranch’ since newbranch doesn’t already exist; 2) if you checkout newbranch from the existing master branch it ALREADY has those three commits included in it, so there’s no use in picking them. At the end of the day to get what the OP wanted, you’ll still have to do some form of reset –hard HEAD.

    – JESii

    May 24, 2014 at 9:08


  • 5

    +1 for a useful approach in some situations. This is good if you only want to pull your own commits (which are interspersed with others) into a new branch.

    – Tyler V.

    Oct 1, 2014 at 17:11

  • 10

    It’s better answer. This way you can move commits to any branch.

    – skywinder

    Nov 5, 2014 at 8:32

  • 3

    I was not able to use the cherry-pick range, got “error: could not apply c682e4b…” on one of the commits, but when used cherry-pick on each commit one at a time, it worked fine (I had to do git cherry-pick –abort after the error). Commenting because I thought those would be equivalent. This is on git version 2.3.8 (Apple Git-58)

    – Hudson

    Oct 31, 2015 at 14:33