Cherry pick all the commits from a merged branch
Tags: bash, git, gitalias
Published: 2020-05-17 16:12:14

---
title: Cherry pick all the commits from a merged branch
published: true
date: 2020-05-17 16:07:37 UTC
tags: bash,git,git-alias
canonical_url: https://le0nidas.gr/2020/05/17/cherry-pick-all-the-commits-from-a-merged-branch/
---

I recently had to revert an entire feature and create a new branch that would be merged in the future. In git terms, I had to [revert](https://git-scm.com/docs/git-revert) my merged branch, [create a new one](https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt-emgitcheckoutem-b-Bltnewbranchgtltstartpointgt) and [cherry pick](https://git-scm.com/docs/git-cherry-pick) the reverted commits to it.

I’ve been working with git for years but up until now I never had to revert a commit, let alone an entire branch. Turns out reverting is quite simple and can be done in [a single command](https://git-scm.com/docs/git-revert#Documentation/git-revert.txt--mparent-number) but cherry-picking all the branch’s commits is a repeatable and tedious task since we need to copy each commit, create a string out of them and give it to `cherry-pick`.

What I wanted was a way to give git the merge commit and let it figure out which commits to cherry-pick. For example, in the case described below:

![](https://le0nidasgr.files.wordpress.com/2020/05/0.cherry-grab.png?w=904)

I would like to cherry-pick all five commits edaa436, 5d48f23, a8f2b4d, 63f2f4e, 1dc3f6a by just providing to git the commit f51c08c.

[I had already done a “custom” git-alias](https://le0nidas.gr/2020/03/27/git-alias-with-parameters/) so I figured I could do something similar and create _cherry-grab_: `git cherry-grab f51c08c`

#### commit^

Two things helped in creating _cherry-grab_ and the first one is the `^` suffix that [one of its usages](https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt-emltrevgtltngtemegemHEADv1510em) is to get the commit’s parent. So if we run `git show edaa436^` git will translate it to `git show 84f8f45`.

In our case where the commit is the result of a merge we can specify which of the two parents we want. f51c08c^1 will be translated to 84f8f45 and f51c08c^2 to 1dc3f6a (in a similar way if we need the nth parent we request it by using ^n).

#### git rev-list <commit>

The second thing was `rev-list` [which returns a list with all the commits](https://git-scm.com/docs/git-rev-list) that can be reached through the parent “pointer” starting from the provided commit. So if we run `git rev-list edaa436` git will return edaa436, 84f8f45 and 55da68d.

Also, `rev-list` can exclude all commits that are reachable from a given commit as long as we prefix it with the caret (^) symbol. So if we run `git rev-list edaa436 ^84f8f45` git will return just edaa436.

## cherry-grab

First we need to get the list with all of the branch’s commits. To do that we will use the `rev-list` command and request all commits starting from the merge-commit’s second parent but exclude all commits that are reachable from the merge-commit’s first parent:

`git rev-list 1dc3f6a ^84f8f45`

this returns 1dc3f6a, 63f2f4e, a8f2b4d, 5d48f23, edaa436 which are the commits that construct the merged branch.

Then we need to reverse this list so that we can apply each commit in the proper order:

`git rev-list 1dc3f6a ^84f8f45 | tac`

which returns edaa436, 5d48f23, a8f2b4d, 63f2f4e, 1dc3f6a.

Having the commits in the correct order we just need to pass them to the `cherry-pick` command to apply their changes:

`git rev-list 1dc3f6a ^84f8f45 | tac | xargs git cherry-pick`

Finally we need to put in an alias to make it reusable:

{% gist https://gist.github.com/le0nidas/8215a67e1b448d2af39310186bfd7251 %}

Nothing fancy or special, we just wrap the sequence of command with a function and tell git to call that function when ever we use the `cherry-grab` alias.

In order to make it reusable we replace the parent commits with `$1^2` and `$1^1` respectively which are translated to the second and first parent of the passed commit.

That’s it:

![](https://le0nidasgr.files.wordpress.com/2020/05/1.cherry-grab.png?w=754)