3

In my project there are a stable branch and a dev branch. Commits are cherry-picked from dev branch to stable branch.

In order to filter all commits on dev that have not been merged to stable, git cherry -v stable dev looks like a good choice. However it identifies equivalence by diff, which usually changes after resolving merge conflict during cherry-pick:

The equivalence test is based on the diff, after removing whitespace and line numbers. git-cherry therefore detects when commits have been "copied" by means of git-cherry-pick(1), git-am(1) or git-rebase(1).

I was wondering that is there any command that works like git cherry, but identifies equivalent commits by commit message?

lz96
  • 2,816
  • 2
  • 28
  • 46
  • If you simply want to clean up the `dev` branch in order to not have changes repeated in multiple commits, you can do `git rebase stable`. Of course, then you have to clean up all conflicts. – Code-Apprentice Jul 30 '17 at 04:30
  • Do you ever force-push `dev`? – max630 Jul 30 '17 at 05:30
  • @max630 Nope. `dev` branch is protected by gerrit. – lz96 Jul 30 '17 at 05:54
  • 2
    Commit messages are not reliable. – ElpieKay Jul 30 '17 at 06:06
  • @ElpieKay Yeah. Gerrit's `Change-Id` is a far more better solution. Unfortunately in our case many old commits are not marked with correct `Change-Id` so commit messages become our only choice. – lz96 Jul 30 '17 at 06:21

3 Answers3

2

It seems that there is no direct way to do this, so I wrote a short script:

#!/bin/bash
git cherry -v stable dev | grep + | cut -d ' ' -f 3- > /tmp/unmerged
xargs -a /tmp/unmerged  -I{} git --no-pager log stable --pretty=oneline --grep {} | cut -d ' ' -f 2- > /tmp/cherry-picked
diff /tmp/unmerged /tmp/cherry-picked

Explanation:

git cherry -v stable dev | grep + | cut -d ' ' -f 3- > /tmp/unmerged writes commit messages of commits that only exist on dev branch. These commits include those have been cherry-picked and changed to stable branch, and we need to filter out these commits in the next step.

xargs -a /tmp/unmerged -I{} git --no-pager log stable --pretty=oneline --grep {} | cut -d ' ' -f 2- > /tmp/cherry-picked outputs messages of commits from (1) that appears with the same message on stable. In other words, /tmp/cherry-picked stores all commits that are cherry-picked and changed from dev to stable.

Finally, diff /tmp/unmerged /tmp/cherry-picked gives out all commits on dev where no commit with identical commit message is found on stable.

lz96
  • 2,816
  • 2
  • 28
  • 46
  • Relying on commit messages is brittle, using `patch-id` is the right way if one wants to match the commits the way `git cherry` does – Jakub Bochenski Nov 14 '17 at 15:00
1

If commits in dev are not rebased, then you could use git cherry-pick -x, marking the source explicitly. There is no automatic use of this information, but with some bash fu it is possible to use it.

max630
  • 8,762
  • 3
  • 30
  • 55
0

You want to use patch-id. This is the mechanism used by git cherry.

To find an equivalent of commit 3642151 run:

git show 3642151 | git patch-id

You should get a line with two hashes; the first is the patchid (call it PATCHID_FROM_ABOVE)

git log -p | git patch-id | grep PATCHID_FROM_ABOVE

This should give you a list of all commits that correspond to that patchid.

Stolen from: http://git.661346.n2.nabble.com/git-cherry-to-find-equivalent-commit-IDs-td3440883.html

Jakub Bochenski
  • 3,113
  • 4
  • 33
  • 61
  • The diff of a commit may change after resolving conflicts during `cherry-pick`, and that's why `git cherry` or `git patch-id` does not work in this case. – lz96 Nov 14 '17 at 15:00
  • Why are you asking "I was wondering that is there any command that works like git cherry"? – Jakub Bochenski Nov 14 '17 at 15:19