If I cherry-pick from multiple branches, is there a simple way to figure out where the commit was coming from (e.g. the sha of the original commit)?
Example:
– at master branch
– cherry pick commit A from a dev branch
– A becomes D at the master branch
Before:
* B (master) Feature Y
| * C (dev) Feature Z
| * A Feature X
|/
* 3
* 2
* 1
After:
* D (master) Feature X
* B Feature Y
| * C (dev) Feature Z
| * A Feature X
|/
* 3
* 2
* 1
Is it possible to figure out that D was cherry-picked from A (aside from searching for the commit message)?
Edit:
Although I will go with daggy-fixes (see VonCs answer) I accepted Chris Johnsens answer because it is closer to the actual question. Thanks guys.
By default, the information about the original, “cherry” commit is not recorded as part of the new commit.
Record the Source Commit in the Commit Message
If you can force the use of particular workflows/options,
git cherry-pick has the
-xoption:This is obviously useless if you can not rely on the cherry pickers using the option.
Also, since the recorded information is just plain text—not an actual reference as far as Git is concerned—even if you use
-x, you still have to take steps to make sure that the original commit is kept alive (e.g. is is part of the DAG of a tag or a non-rewinding branch).git cherry and git patch-id
If you can restrict your search to two particular branches of the history DAG, then git cherry can find both “unpicked” and “picked” cherries.
Note: This command (and the related git patch-id) can only identify conflict-free cherries that were individually picked without extra changes. If there was a conflict while picking the cherry (e.g. you had to slightly modify it to get it to apply), or you used
-n/--no-committo stage extra changes (e.g. multiple cherries in a single commit), or the content of the commit was rewritten after the picking, then you will have to rely on commit message comparison (or the-xinformation if it was recorded).git cherry is not really designed to identify the origin of picked cherries, but we can abuse it a bit to identify single cherry pairs.
Given the following history DAG (as in the original poster’s example):
you will see something like this:
(A, B, C, and D are full SHA-1 hashes in the real output)
Since we see one cherry (the
-lines) in each list, they must form a cherry pair. D was a cherry picked from C (or vice versa; you can not tell by the DAG alone, though the commit dates might help).If you are dealing with more than one potential cherry, you will have to “roll your own” program to do the mapping. The code should be easy in any language with associative arrays, hashes, dictionaries, or equivalent. In awk, it might look like this:
With an extended example that has two picked cherries:
The output might look like this:
(A, C, D, and E are full SHA-1 hashes in the real output)
This tells us that C and D represent the same change and that E and A represent the same change. As before, there is no way to tell which of each pair was “the first” unless you also consider (e.g.) the commit dates of each commit.
Commit Message Comparison
If your cherries were not picked with
-x, or they are “dirty” (had conflicts, or other changes added to them (i.e. with--no-commitplus staging extra changes, or withgit commit --amendor other “history rewriting” mechanism)), then you may have to fall back on less the less reliable technique of comparing commit messages.This technique works best if you can find some bit of the commit message that is likely to be unique to the commit and is unlikely to have changed in the commit that resulted from the cherry pick. The bit that would work best would depend on the style of commit messages used in your project.
Once you have picked out an “identifying part” of the message, you can use git log to find commits (also demonstrated in Jefromi’s answer).
The argument to
--grepis actually a regular expression, so you might need to escape any regexp metacharacters ([]*?.\).If you are not sure which branches might hold the original commit and the new commit, you can use
--allas Jefromi showed.