Skip to content

Instantly share code, notes, and snippets.

@unbracketed
Created April 7, 2015 17:49
Show Gist options
  • Save unbracketed/889c844473bcca1917e2 to your computer and use it in GitHub Desktop.
Save unbracketed/889c844473bcca1917e2 to your computer and use it in GitHub Desktop.
Moving commits between branches

Example: Moving up to a few commits to another branch

Branch A has commits (X,Y) that also need to be in Branch B. The cherry-pick operations should be done in the same chronological order that the commits appear in Branch A.

cherry-pick does support a range of commits, but if you have merge commits in that range, it gets really complicated

git checkout branch-B
git cherry-pick X
git cherry-pick Y

Example: Moving a range of commits

Branch A has a series of commits (X..Y) that need to be moved to branch B. For this case, you'll need to specify the commit before the initial commit you're interested in order for it to be included. Example: you want commits B..D from (...A->B->C->D-E->...) you would use "A" as the starting commit. You'll also need the commit SHA for the HEAD of the branch you are transferring to.

git checkout branch-B
git log  # Note the SHA of most recent commit (M)
git rebase --onto M <commit before X> Y
git rebase HEAD branch-B
@olivierphi
Copy link

So useful! I was banging my head against a wall every time I had to do something like this, doing it manually cherry-pic by cherry-pick, but the way you describe here work perfectly.
Thank you so much! :-)

@UrielSalomon
Copy link

UrielSalomon commented Sep 13, 2017

What does this do?

git rebase HEAD branch-B

I can't figure out the meaning of this based on the doc (https://git-scm.com/docs/git-rebase). Will it just fast forward branch-B to the resulting commit?

@jameshoward
Copy link

The final rebasing is to get you back on branch-B with the up-to-date history. Until this point you are in a detached state.

@KarlZ
Copy link

KarlZ commented Mar 7, 2018

Is this "Copying commits between branches"? (X and Y are in both Branch A and B at the end)
Or is this "Moving commits between branches"? (X and Y are MOVED from Branch A and placed in Branch B, so X and Y are ONLY in Branch B at the end)
I was looking for a way to Move some commits. After implementing some features it was decided we don't want to release then until the next major release. Had we known that we would have created the dev branch for those features. I hope what I'm saying makes sense.

@dieuwkehupkes
Copy link

Thank you, super helpful!

@kemjones
Copy link

@KarlZ If this sequence of commands is equivalent to serially applying cherry-picked commits (and I believe it is), then it should be a COPY of those commits from one branch to another.

@nivekalara237
Copy link

helpful, thank

@Anh3h
Copy link

Anh3h commented Feb 4, 2019

Super helpful, thanks.

@ToniIvanov-Nano
Copy link

ToniIvanov-Nano commented May 22, 2019

Thank you. it was slow resolving conflicts from each commit at a time before continuing rebase to the next one. (if there is a conflict after each commit in the sequence, you have to resolve it then git add and git rebase --continue). It would be useful instead to combine all the commits and resolve the conflicts that all of them made to a file.

@RepeatDaily
Copy link

This line is confusing... git rebase --onto M <commit before X> Y

What is M in this case? If we're moving commits from branch-A to branch-B wouldn't it be git rebase --onto A <[one before]start> <end>?

@unbracketed
Copy link
Author

unbracketed commented Jun 26, 2019

@RepeatDaily from the line above the one you referenced, M is the SHA of the most recent commit:

git log # Note the SHA of most recent commit (M)

@Buzzardo
Copy link

Thanks. I needed to move only one commit, so cherry-pick did the trick.

@willyfresh
Copy link

This was awesome. thank you so much!

@earthbound19
Copy link

earthbound19 commented Mar 27, 2021

I think you're referring to a series of commits as both X..Y and A, B, C.. here. On top of that, you refer also to branches as A and B. Will you please rewrite this with consistent and non-redundant names?

@EvgenyArtemov
Copy link

A great and elegant solution, thanks!

@irizzant
Copy link

I don't think you need
git log # Note the SHA of most recent commit (M)

Just:

git checkout branch-B
git rebase --onto branch-B <commit before X> Y
git rebase HEAD branch-B

@bfrg
Copy link

bfrg commented Jul 23, 2021

There's an alternative way for moving a range of commits to another branch, but the following only works for the latest commits.

  • First create a new branch:
    $ git branch branch-b
    This new branch will contain all the commits from master (or whatever the current branch is).
  • Now move the master branch back as many commits as you like:
    $ git reset --keep HEAD~2    # Move master branch back 2 commits
    $ git reset --keep <commit>  # Move master branch back to a specific commit

I found the explanation here.

@skys215
Copy link

skys215 commented Oct 14, 2021

I think it's like this:

Branch A has commit ...->a->b->c->d->e
Branch B is the destination of merging. ...->z
And you want to move commits b..e on top of the commit z (whis is in branch B).
In this case, run

git checkout B
git rebase --onto z a e` on branch B
git rebase HEAD B

It's better to make a buckup before running commands.

@dbzix
Copy link

dbzix commented Nov 17, 2021

I have only branch master with commits ...->a->b->c->d->e:

o - o - a - b - c - d - e (master HEAD)

Now I'd like to move commits b to e to branch second so that it will branch out right from commit a of master:

o - o - a (master HEAD)
         \ 
          b - c - d - e (second HEAD)

How am I supposed to do that? The scenario used here doesn't work to me.

How do I do it now:

git checkout master
git branch second
git reset --hard a

then I go and remove unneeded files left in master after reset.

So now I'm done with desired result.
But I believe there is a better way to do what I want.

@otheus
Copy link

otheus commented Feb 22, 2022

Sorry, but this makes no sense. It still needs some clarification. And what really drives me crazy, is that if you don't do this command exactly right, you can create a complete mess that will take hours of cherry-picking and searching through the reflog to undo. So it's not like you can experiment.

Branch A has a series of commits (X..Y) that need to be moved to branch B. For this case, you'll need to specify the commit before the initial commit you're interested in order for it to be included. Example: you want commits B..D from (...A->B->C->D-E->...) you would use "A" as the starting commit. You'll also need the commit SHA for the HEAD of the branch you are transferring to.

Where are commits X through Y in relation to commits A through E ? You're referring to Branch A and commit A. Are they the same? Where did branch B come from? Is it related to branch A or commit B? or does that not matter?

OK, you checkout branch B. Now rebase "onto" it the commits X through Y.

For this case, you'll need to specify the commit before the initial commit you're interested in order for it to be included.

In your example, we're interested in X and Y. So we find "M" which is the "most recent commit". You say the command is:

git rebase --onto M <commit before X> Y

so that's:

git rebase --onto <most recent commit> <commit before X> Y

But since we just did a checkout of branch B, why isn't M == HEAD? Or why not

git rebase --onto HEAD <commit before X> Y

which is (according to the documentation) the save as:

git reset --hard HEAD  ; git rebase <commit before X> Y

which is the same as

git rebase X^ Y

Or ... am I missing something? If not, the example is simply:

git checkout -b new-branch commit-of-starting-point
git rebase X^ Y

@iampeterbanjo
Copy link

I used this today and the Git did not implode 🎉 Thank you

@Simulacron-3
Copy link

Thanks, used cherry-pick today for the first time without collapsing the space-time continuum <3
@iampeterbanjo i feel your concerns :)

@piankris
Copy link

Nice and easy, thank you for the explanation and comments in the section for alternatives!

@dataheadless
Copy link

This article explains it well in details.

How To Move A Commit To Another Branch In Git

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment