Reputation: 527
Reading through this question about extracting footers from commits, the answer left something to be desired for my specific use case. Using the suggested command (git log --format="%h %s %(trailers:key=Issue,valueonly)"
), all commits are shown, even those that do not have an "Issue" footer.
Continuing with the example footer "Issue": Say that my repository contains some commits that do declare Issue, and some that don't, and I'm looking only for the commits that have the footer in question - what's the best way to go about showing only commits that declare a certain footer?
One option, of course, is to remove ,valueonly
and then grep for "Issue:": git log --format="%h %s %(trailers:key=Issue)" | grep Issue:
, but this requires the key to be shown. Obviously, in some cases, this can be worked around - following the aforementioned question, for example, we could then use sed to remove "Issue:", but that brings up the following challenges:
Another, perhaps rather convoluted, solution I've considered would be to show just %h %(trailers:key=Issue)
while using --grep for Issue:
[1], extract %h
and git show
each of those commits with the desired format. This approach leaves me with the command: git log --format="%h %(trailers:key=Issue)" --grep Issue: | awk '{print $1}' | xargs git --no-pager show
, which seems un-neccesarily convoluted and inefficient (in that it runs git-log
twice).
Is there a better (syntactically cleaner and/or more programmatically efficient) way of showing only commits which declare a certain footer?
[1] Thanks to Guildenstern for reminding me in the comments that git-log --grep
exists and I didn't have to git log | grep
.
Upvotes: 1
Views: 79
Reputation: 3841
Unfortunately there seems to be no way to specifically search for trailers/footers directly. As you’ve correctly pointed out just searching for the strings is not reliable since the trailer keys can occur before the trailer section.
But we don’t need to do much:
git log --format="%H %(trailers:key=Issue)%-C()" \
| sed -e '/^I/Id' \
| sed -e '/I/!d' \
| cut -d' ' -f1 \
| git log --no-walk --stdin
As you’ve sketched we should start with
--format
:
git log --format="%H %(trailers:key=Issue)"
Next we need to filter out some needless output since a trailer key can occur multiple times in the same commit message:
fedc612314acfebf506e071bf3a941076aa56d10 Issue: 987
Issue: 465
Which means we need:
sed -e '/^I/Id'
We need the I
(case-insenstive match) because apparently the trailer
key matching is case-insensitive. [1]
The next sed(1) expression filters out commits without this trailer.
sed -e '/I/!d'
Here though I couldn’t get the I
switch to work. And I couldn’get
[Ii]
to work either.
The final line takes all the input (all hashes) and displays them.
--no-walk
makes sure that ancestors aren’t found since they are
irrelevant to your search.
git log --no-walk --stdin
(git-show(1) could also be used instead of git-log(1))
Upvotes: 0