How to copy commits from one branch to another?
Asked Answered
G

11

1210

I've got two branches from my master:

  • v2.1: (version 2) I've been working on for several months
  • wss: that I created yesterday to add one specific feature to my master (in production)

Is there a way to copy yesterday's commits from wss to v2.1?

Groat answered 19/3, 2010 at 0:51 Comment(2)
To simply copy commits (or a range of commits) from one branch to another this answer helped me best: stackoverflow.com/questions/1994463/…Mixedup
Cherry-Picking specific commits from another branchHardi
C
730

You should really have a workflow that lets you do this all by merging:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

So all you have to do is git checkout v2.1 and git merge wss. If for some reason you really can't do this, and you can't use git rebase to move your wss branch to the right place, the command to grab a single commit from somewhere and apply it elsewhere is git cherry-pick. Just check out the branch you want to apply it on, and run git cherry-pick <SHA of commit to cherry-pick>.

Some of the ways rebase might save you:

If your history looks like this:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

You could use git rebase --onto v2 v2-only wss to move wss directly onto v2:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

Then you can merge! If you really, really, really can't get to the point where you can merge, you can still use rebase to effectively do several cherry-picks at once:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

Note: the reason that it takes some extra work in order to do this is that it's creating duplicate commits in your repository. This isn't really a good thing - the whole point of easy branching and merging is to be able to do everything by making commit(s) one place and merging them into wherever they're needed. Duplicate commits mean an intent never to merge those two branches (if you decide you want to later, you'll get conflicts).

Cricoid answered 19/3, 2010 at 0:59 Comment(7)
Couldn't agree more with this answer. +1. See also my old answer to illustrates the consequences of cherry-picking: stackoverflow.com/questions/881092/…Countless
@VonC: Thanks for the support, and the extra info on why not to cherry-pick - I know I skimped a little there. @gotgenes: Thanks! I think it's totally worth the effort - just look at the git-rebase manpage. There's no better way to explain it.Cricoid
As for why you might be unable to merge - Git merging does not play nice with git-svn. To copy a series of commits from one SVN branch to another, I ended up cherry-picking them and then performing an interactive rebase/reword to remove the incorrect git-svn-id references before dcommiting again. Though I probably could have left out the cherry-pick step and just used a rebase by itself.Afford
Thanks jefromi, this info helped me understand and write this question / answer - stackoverflow.com/questions/32600066/….Messily
Here's my use case: critical bug fixes were committed to feature branch. I need it in master to go into production now. This will save my butt.Shiverick
what happen if we have 2 feature branches and for every branch have 4 commits for example and then we want to cherry-pic these 8 commits into master for example.Sheaff
I don't get the note at the end. How can making two branches more similar by applying the same changes from a commit introduce conflicts? –Truthful
N
1473

Use

git cherry-pick <commit>

to apply <commit> to your current branch.

I myself would probably cross-check the commits I pick in gitk and cherry-pick them with right-clicks on the commit entry there instead.


If you want to go more automatic (with all its dangers) and assuming all commits since yesterday happened on wss you could generate the list of commits using git log (with --pretty suggested by Jefromi)

git log --reverse --since=yesterday --pretty=%H

so everything together assuming you use bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

If something goes wrong here (there is a lot of potential) you are in trouble since this works on the live checkout, so either do manual cherry-picks or use rebase like suggested by Jefromi.

Nunnery answered 19/3, 2010 at 1:22 Comment(10)
All the placeholders for the --pretty option are in the git-log manpage. You can get any format you want - particularly useful for getting the fields you want for a script in an easily parsable form.Cricoid
I also would like to point out that, assuming you really do want to create duplicate commits, the method using git rebase in my answer is more robust. In particular, using a for loop like this, if one of the cherry-picks fails, it will still try to do all the rest of them. This is... very very not good, let's say.Cricoid
Agreed. That's why I never use it, but do it manually. But cherry-pick is still the answer, at least to the question title. I modified the response.Nunnery
Someone committed to an old/incorrect branch, and cherry-pick let me put that commit into the right branch (while still keeping them as the committer). Perfect.Mellifluous
So surprised I've never run across cherry-pick in any of my prior Git readings/lookups. The hours and hours of work it would have saved me... I'd multi-upvote this answer if I could!Ghostwrite
I use this successfully by repeating the command for each commit I want to copy over. Essentially the process I use is 1) Checkout using git checkout <branch-name> the source branch you're copying from, and git log the commits and copy the full hashes to a notepad 2) Checkout the target branch you're copying to 3) git cherry-pick <hash> using the hashes you copied to your notepad 4) repeat step 3 for any other commits you want to copy. If there are issues you'll need to resolve them and git cherry-pick --continue after resolving them.Carrera
@BenjaminBannier Could you please elaborate "I myself would probably cross-check the commits I pick in gitk and cherry-pick them with right-clicks on the commit entry there instead." What do you mean by "cross-check"? Will cherry-pick prompt me before importing each file(is there an option for that)? Is there anything that can be done on command line to achieve the same that you do by "right-click"?Blond
@Carrera at step 3: Is it possible to use multiple hashes ( e.g. git cherry-pick hash_n1 hash_n2 hash_n3 ? If not, do you start with most recent hash or oldest hash ?Blond
@Blond I've not used it but you can do git cherry-pick A^..B from A-B. A should be older than B.Carrera
Also you can just do git cherry-pick A C G H, where letters are any of the commits that you want to apply to the branch (in chronological order)Astonishing
C
730

You should really have a workflow that lets you do this all by merging:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

So all you have to do is git checkout v2.1 and git merge wss. If for some reason you really can't do this, and you can't use git rebase to move your wss branch to the right place, the command to grab a single commit from somewhere and apply it elsewhere is git cherry-pick. Just check out the branch you want to apply it on, and run git cherry-pick <SHA of commit to cherry-pick>.

Some of the ways rebase might save you:

If your history looks like this:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

You could use git rebase --onto v2 v2-only wss to move wss directly onto v2:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

Then you can merge! If you really, really, really can't get to the point where you can merge, you can still use rebase to effectively do several cherry-picks at once:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

Note: the reason that it takes some extra work in order to do this is that it's creating duplicate commits in your repository. This isn't really a good thing - the whole point of easy branching and merging is to be able to do everything by making commit(s) one place and merging them into wherever they're needed. Duplicate commits mean an intent never to merge those two branches (if you decide you want to later, you'll get conflicts).

Cricoid answered 19/3, 2010 at 0:59 Comment(7)
Couldn't agree more with this answer. +1. See also my old answer to illustrates the consequences of cherry-picking: stackoverflow.com/questions/881092/…Countless
@VonC: Thanks for the support, and the extra info on why not to cherry-pick - I know I skimped a little there. @gotgenes: Thanks! I think it's totally worth the effort - just look at the git-rebase manpage. There's no better way to explain it.Cricoid
As for why you might be unable to merge - Git merging does not play nice with git-svn. To copy a series of commits from one SVN branch to another, I ended up cherry-picking them and then performing an interactive rebase/reword to remove the incorrect git-svn-id references before dcommiting again. Though I probably could have left out the cherry-pick step and just used a rebase by itself.Afford
Thanks jefromi, this info helped me understand and write this question / answer - stackoverflow.com/questions/32600066/….Messily
Here's my use case: critical bug fixes were committed to feature branch. I need it in master to go into production now. This will save my butt.Shiverick
what happen if we have 2 feature branches and for every branch have 4 commits for example and then we want to cherry-pic these 8 commits into master for example.Sheaff
I don't get the note at the end. How can making two branches more similar by applying the same changes from a commit introduce conflicts? –Truthful
P
133

git cherry-pick : Apply the changes introduced by some existing commits

Assume we have branch A with (X, Y, Z) commits. We need to add these commits to branch B. We are going to use the cherry-pick operations.

When we use cherry-pick, we should add commits on branch B 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 B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

Example of workflow :

enter image description here

We can use cherry-pick with options

-e or --edit : With this option, git cherry-pick will let you edit the commit message prior to committing.

-n or --no-commit : Usually the command automatically creates a sequence of commits. This flag applies the changes necessary to cherry-pick each named commit to your working tree and the index, without making any commit. In addition, when this option is used, your index does not have to match the HEAD commit. The cherry-pick is done against the beginning state of your index.

Here an interesting article git cherry-pick: it might not be what you think concerning cherry-pick.

Perforate answered 5/9, 2018 at 8:40 Comment(0)
P
86

Suppose I have committed changes to the master branch. I will get the commit id (xyz) of the commit now. Then I have to go to the branch for which I need to push my commits.

Single commit id xyz

git checkout branch-name
git cherry-pick xyz
git push origin branch-name

Multiple commit id's xyz abc qwe

git checkout branch-name
git cherry-pick xyz abc qwe
git push origin branch-name
Prospector answered 17/7, 2020 at 9:24 Comment(0)
P
40

The answers already mentioned cover most of the stuff but one thing that seems to be missing is the --no-commit feature of cherry-picking.

Assume, you have more than one commits on the feature branch and you want to "merge" all of them into a single commit and put them on your main branch. In that case what you need to do is:

git checkout <branch-on-which-to-add-features>
git cherry-pick --no-commit <commit-hash>
git cherry-pick --no-commit <commit-hash>
.
.
.

And finally, once you have cherry-picked all the required features, you could do a final commit:

git commit -m "Some message for the merge commit"

Ideally, as @Cascabel mentioned, you should be using merge or rebase. But if you feel there's no other choice, you could get away with using cherry-picking.

Plenipotentiary answered 11/3, 2021 at 10:29 Comment(0)
C
25

You could create a patch from the commits that you want to copy and apply the patch to the destination branch.

Concretize answered 19/3, 2010 at 0:55 Comment(2)
Even if you for some reason really want to use patch(es) instead of cherry-pick(s)/rebase, the straightforward way to do it is with git format-patch <revision range> and git am *.patch.Cricoid
It requires checkout to another branch.Limn
V
14

Or if You are little less on the evangelist's side You can do a little ugly way I'm using. In deploy_template there are commits I want to copy on my master as branch deploy

git branch deploy deploy_template
git checkout deploy
git rebase master

This will create new branch deploy (I use -f to overwrite existing deploy branch) on deploy_template, then rebase this new branch onto master, leaving deploy_template untouched.

Vault answered 14/12, 2011 at 22:18 Comment(0)
S
5

Here's another approach.

git checkout {SOURCE_BRANCH}               # switch to Source branch.
git checkout {COMMIT_HASH}                 # go back to the desired commit.
git checkout -b {temp_branch}              # create a new temporary branch from {COMMIT_HASH} snapshot.
git checkout {TARGET_BRANCH}               # switch to Target branch.
git merge {temp_branch}                    # merge code to your Target branch.
git branch -d {temp_branch}                # delete the temp branch.
Shotputter answered 6/10, 2020 at 21:23 Comment(2)
Feel like this is a really good approach in case you mess things up by resetting your progress and have a separate branch (testing environment in my case) from which you can use to restore your commits from.Richardson
I used this approach to add commits I missed during head resetting. Thanks!Thug
E
5

It's safer to use built-in git gui for cherry-picking specific commits:

For ex: copy one commit from dev branch to main branch:

git checkout main
gitk --all

And then right-click on desired commit and select Cherry-pick this commit

enter image description here

gitk for Mac: Install gitk on Mac

Elfish answered 13/11, 2021 at 11:2 Comment(3)
This answers assumes a particular OS and app install. Can you make it more generic?Slice
gitk is available for multiple OS. For mac: https://mcmap.net/q/22693/-install-gitk-on-macElfish
Could you explain why it is inherently safer to cherry-pick through the UI vs through the CLI?Cockleboat
D
3

The cherry-pick command can read the list of commits from the standard input.

The following command cherry-picks commits authored by the user John that exist in the "develop" branch but not in the "release" branch, and does so in the chronological order.

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
Damson answered 6/5, 2020 at 15:20 Comment(0)
C
2

For the simple case of just copying the last commit from branch wss to v2.1, you can simply grab the commit id (git log --oneline | head -n 1) and do:

git checkout v2.1
git merge <commit>
Coping answered 27/8, 2018 at 18:49 Comment(1)
This requires checking out to another branch.Limn

© 2022 - 2024 — McMap. All rights reserved.