How to move certain commits to be based on another branch in git?

240,731

Solution 1

This is a classic case of rebase --onto:

 # let's go to current master (X, where quickfix2 should begin)
 git checkout master

 # replay every commit *after* quickfix1 up to quickfix2 HEAD.
 git rebase --onto master quickfix1 quickfix2 

So you should go from

o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)
              \
               q2a--q2b (quickfix2 HEAD)

to:

      q2a'--q2b' (new quickfix2 HEAD)
     /
o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)

This is best done on a clean working tree.
See git config --global rebase.autostash true, especially after Git 2.10.

Solution 2

You can use git cherry-pick to just pick the commit that you want to copy over.

Probably the best way is to create the branch out of master, then in that branch use git cherry-pick on the 2 commits from quickfix2 that you want.

Solution 3

The simplest thing you can do is cherry picking a range. It does the same as the rebase --onto but is easier for the eyes :)

git cherry-pick quickfix1..quickfix2

Solution 4

I believe it's:

git checkout master
git checkout -b good_quickfix2
git cherry-pick quickfix2^
git cherry-pick quickfix2
Share:
240,731
Alex Yarmula
Author by

Alex Yarmula

Updated on July 08, 2022

Comments

  • Alex Yarmula
    Alex Yarmula almost 2 years

    The situation:

    • master is at X
    • quickfix1 is at X + 2 commits

    Such that:

    o-o-X (master HEAD)
         \
          q1a--q1b (quickfix1 HEAD)
    

    Then I started working on quickfix2, but by accident took quickfix1 as the source branch to copy, not the master. Now quickfix2 is at X + 2 commits + 2 relevant commits.

    o-o-X (master HEAD)
         \
          q1a--q1b (quickfix1 HEAD)
                  \
                   q2a--q2b (quickfix2 HEAD)
    

    Now I want to have a branch with quickfix2, but without the 2 commits that belong to quickfix1.

          q2a'--q2b' (quickfix2 HEAD)
         /
    o-o-X (master HEAD)
         \ 
          q1a--q1b (quickfix1 HEAD)
    

    I tried to create a patch from a certain revision in quickfix2, but the patch doesn't preserve the commit history. Is there a way to save my commit history, but have a branch without changes in quickfix1?

  • Max Chernyak
    Max Chernyak over 11 years
    Beware that these steps will modify quickfix2's history, so if you already shared the branch, use cherry-picking instead (see following answers).
  • akavel
    akavel almost 11 years
    also, it doesn't lose the original commits, IIUC, so seems preferable for "play-it-safes" like me ;) or does rebase --onto also preserve the original changes?
  • Christoph
    Christoph almost 11 years
    both rebase and cherry-pick give you new SHA keys. That's because each commit is a unique snapshot of the repository.
  • Mr_and_Mrs_D
    Mr_and_Mrs_D over 10 years
    What @akavel meant is that cherry-pick will keep the original commits in their branch which is true
  • Thomas S.
    Thomas S. almost 9 years
    Just for the records: with SmartGit's log just drag q2a onto X and select Rebase 2 commits from the options of the occurring dialog.
  • VonC
    VonC almost 9 years
    @ThomasS. Interesting. That is a nice GUI implementation of a git rebase --onto.
  • WORMSS
    WORMSS almost 9 years
    I have to admit, I do silly things like committing on to the wrong branch more often that I really should, the SmartGit log view GUI has saved me so many times with the same situation.
  • VonC
    VonC almost 9 years
    @WORMSS another interesting GUI: kickstarter.com/projects/diffplug/git-for-diffplug
  • John Leidegren
    John Leidegren over 8 years
    cherry-pick works with commit hashes so, if you just want to grab a commit from somewhere and put it somewhere else this is the way to go. Just make sure you do the checkout <branch> of the correct branch first.
  • carmenism
    carmenism almost 8 years
    For whatever it is worth, I tried to cherry-pick a range like in this answer and it confused my repo. I had to do individual cherry-picks for each commit. (And maybe it goes without saying, but in case anyone is struggling, you have to cherry-pick in the chronological order that your commits were applied.)
  • Sławomir Lenart
    Sławomir Lenart over 7 years
    git checkout is crucial here. what is your HEAD :) ?
  • Cosine
    Cosine about 7 years
    Careful! If not careful this will overwrite your working directory. I lost work with this command.
  • VonC
    VonC about 7 years
    @Cosine Agreed. I have edited my answer to add the reference to rebase.autostash configuration: that will avoid any loss of work in progress in the working tree when doing a rebase.
  • Alex from Jitbit
    Alex from Jitbit over 4 years
    This is also the best option if you want to move just one commit. Thanks.