tags:

views:

194

answers:

3

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?

A: 

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

Charles Ma
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`.
Jefromi
+9  A: 

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).

Jefromi
Couldn't agree more with this answer. +1. See also my old answer to illustrates the consequences of cherry-picking: http://stackoverflow.com/questions/881092/how-to-merge-a-specific-commit-in-git/881112#881112
VonC
Superb answer on how to do this the *proper* way! I wish I could up-vote twice for the effort of creating ASCII diagrams, too.
gotgenes
@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.
Jefromi
+1  A: 

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.

honk
The shorter version you're looking for is `git log --since=yesterday --reverse --pretty=%H`.
Jefromi
@Jefromi Thanks, that's a `pretty` useful flag. Updated answer.
honk
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.
Jefromi
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.
Jefromi
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.
honk