How can I get the *other* commit-id when running "git cherry"?

322 views Asked by At

The "git cherry" command is great for identifying commits that have already been applied upstream, but how can I obtain the exact upstream commit-id's that correspond 1-for-1 to my matching downstream commits?

Here's my situation:

* 04876f4 (HEAD -> test-rebased) c
* 1e73b75 b
* 8ce948c a
* 8cc1e21 (origin/master) m
| * 4b8bc3e (origin/test) c
| * f207a10 b
| * 1c15641 a
|/  
* 0a943a2

The "git cherry" command is great for noticing that 8ce948c, 1e73b75, and 04876f4 have already been applied to origin/test (or at least patch-equivalent commits). Notice the minus signs "-" next to those 3 commits in this output here:

git cherry -v test HEAD
+ 8cc1e2105f387eeede67a87688b6bfae0cab42c6 m
- 8ce948ca1b54d551581f4574bda2c215cc96a351 a
- 1e73b75de891eab9314856558624e9b4c21bbb1f b
- 04876f4e615b2bb70b969e99de15ec78b1ea84f6 c

But it doesn't tell me how they map 1-for-1 to my local commits (on my "test-rebased" branch). Does anyone know any combination of git commands that could give me that mapping? Note: assume commit-messages are not stable (even though they are in my example here). They might change dramatically in my local branch (e.g., I might do "git commit --amend" to rewrite the commit message).

Probably the only way to do this is by patching the "git cherry" command to add an extra column of output (since surely it knows the mapping under the hood), but thought I'd ask the internet if anyone knows of any possibilities here before I venture down that route.

1

There are 1 answers

2
G. Sylvie Davies On

A quick addendum (I posted the question) - this patch against builtin/log.c (from git's source code) gives me the exact behaviour I want.

Here's the behaviour I want:

git cherry -v test HEAD
+ 8cc1e2105f387eeede67a87688b6bfae0cab42c6 - m
- 8ce948ca1b54d551581f4574bda2c215cc96a351 1c156417bff133e25664fe7047b5df6a81fbd2f7 a
- 1e73b75de891eab9314856558624e9b4c21bbb1f f207a10a5249f9e0fe74184f8b03c75bbf7488c5 b
- 04876f4e615b2bb70b969e99de15ec78b1ea84f6 4b8bc3eab7c625f298ca3bd031ba141b66240da4 c

And here's the patch:

diff --git a/builtin/log.c b/builtin/log.c
index d104d5c688..a32f0bede7 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -2153,17 +2153,19 @@ static const char * const cherry_usage[] = {
        NULL
 };
 
-static void print_commit(char sign, struct commit *commit, int verbose,
+static void print_commit(char sign, struct commit *commit, struct commit *other, int verbose,
                         int abbrev, FILE *file)
 {
        if (!verbose) {
-               fprintf(file, "%c %s\n", sign,
-                      find_unique_abbrev(&commit->object.oid, abbrev));
+               fprintf(file, "%c %s %s\n", sign,
+                      find_unique_abbrev(&commit->object.oid, abbrev),
+                      other ? find_unique_abbrev(&other->object.oid, abbrev) : "-");
        } else {
                struct strbuf buf = STRBUF_INIT;
                pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
-               fprintf(file, "%c %s %s\n", sign,
+               fprintf(file, "%c %s %s %s\n", sign,
                       find_unique_abbrev(&commit->object.oid, abbrev),
+                      other ? find_unique_abbrev(&other->object.oid, abbrev) : "-",
                       buf.buf);
                strbuf_release(&buf);
        }
@@ -2238,12 +2240,17 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
        }
 
        while (list) {
+               struct patch_id *id;
+               struct commit *upstream_commit = NULL;
                char sign = '+';
 
                commit = list->item;
-               if (has_commit_patch_id(commit, &ids))
+               id = has_commit_patch_id(commit, &ids);
+               if (id) {
                        sign = '-';
-               print_commit(sign, commit, verbose, abbrev, revs.diffopt.file);
+                       upstream_commit = id->commit;
+               }
+               print_commit(sign, commit, upstream_commit, verbose, abbrev, revs.diffopt.file);
                list = list->next;
        }
 

Obviously be nicer if there's some way to accomplish this without trying to get a patch accepted into the git project, but thought posting this might help clarify exactly what I'm looking for. Sure enough the data is right there under the hood in the "git cherry" command. :-)