git cherry is superior to git log for getting the difference between two branches. The problem is that its output is limited. 
I'm trying to extract the email address (or user) associated with a commit. Here is what I'm doing.
git cherry firstbranch secondbranch | awk '/^+/ {print $2}' | awk '{ system("git show $1"); }'
All I get is the details of one commit. Instead of every commit that I do get with:
git cherry firstbranch secondbranch | awk '/^+/ {print $2}'
Something is going wrong with the second pipe operation.
My question is: How do I use git cherry to get committer email?
                        
Steven Penny's approach of piping to
git log --no-walk --stdinis a correct method, and is required in the most complex cases (complex filtering of selected commit-IDs).There are a couple of tricks that one can use for this particular case though. If you check the (extensive, albeit confusing) documentation for
git rev-listyou will find the options--left-right,--left-only,--right-only,--cherry-mark,--cherry-pick, and--cherry.The
--left-rightoption works with any symmetric difference, i.e., commits selected byA...B, which means "all commits that are on branchAor branchB, excluding any commits that are on both branches." This is howgit cherrydoes the first part of its thing: it finds commits that are on the symmetric difference. However,git cherrygoes on to throw out all the commits that are "the same"1 on both branches, then marks those on one side with-and those on the other with+. The--left-rightoption marks all commits as either<(left side) or>(right side).Since
rev-listis the Swiss Army Chainsaw command, it also has the ability to throw out commits that are the same. It has even more abilities too: it can throw out commits on one side entirely, same-or-different. This is what we want in this case: throw out "commits that are the same" (so that we keep only "different" ones), then throw out all "left side" commits (so that we keep only those that are in the right side but not the left). We get the former with--cherry-pick: it keeps only commits that are considered "different". Then we add--right-onlyto keep only those on the right side, i.e., when we sayfirstbranch...secondbranch, keep only those that are both different and insecondbranch... which is exactly whatgit cherrydoes.Hence:
produces the same commit ID list as:
(with the single difference being that instead of
+ face0ff..., it prints+face0ff, i.e., no space after the+mark).This seems pretty silly: instead of just the four words
git cherryand two branch names, we needgit rev-listand a bunch of options and two branch names and three periods. We've typed in lots more letters to get pretty much the same thing. So we could just use the shorter command and pipe it togit log, but now we get to the tricky bit.git logandgit rev-listare very nearly the same commandIn fact, they are built from the same source code, they just set some internal options differently (and
git logwill pretend you saidHEADif you don't name any other starting points). Since we're about to pipe the output ofgit rev-listtogit log --pretty='%h %ce', maybe we can just do the whole thing ingit logdirectly.Sure enough, we can. We need all those same options as with
git rev-list, but now we can just run:(you may want
--no-mergeshere as well—I'm not sure offhand whatgit cherrydoes about merges!).1"Sameness", in this case, is determined by the output of
git patch-id, which basically strips identifying line numbers off diffs (and also strips certain white space details). Thus, if one commit was cherry-picked into another branch, both such commits will usually have the same patch-ID. (The patch-IDs will differ if someone had to resolve merge conflicts.)