Reputation: 1720
I knew that
git branch --contains <REVISION>
can show names of all child branches since <REVISION>
git log --branches=<BRANCH_REGEX>
can filter branchesIs there any way to conceptually direct output of the former command to the latter?
i.e. git branch --contains <REVISION> | git log --branches=
The goal is to filter branches when using git log --decorate --graph --oneline [OTHER_OPTIONS]
Thanks~
Upvotes: 1
Views: 185
Reputation: 487993
Is there any way to conceptually direct output of [one] command [as arguments to another]?
The shell (sh
or bash
or whatever shell command interpreter you use) generally has a method of doing that.
There are two common spellings, one using backquotes which is convenient for very short items, and one using $(...)
which is better in general because it nests properly.
The problem with git branch --contains
is that it formats its output improperly: it will print *
if one of the branch names that it prints, that contains the given commit, is the current branch. You must either do something to remove the asterisk, or use a more command-oriented command. The latter is better in general but requires that your Git not be too old (2.6 or later): replace git branch --contains <rev>
with git for-each-ref --contains=<rev> --format='%(refname)' ref/heads
.
Now, you can't turn this into a set of glob patterns for --branches=
for git log
, but you don't need to, because all --branches=<glob>
does is tell git log
to start from the references that match refs/heads/<glob>
, and the git for-each-ref
is already going to produce a complete list of such references. So all you need to do is pass that complete list of references on to git log
.
Since shells also expand $name
as a variable holding some name, I'll use that below instead of <...>
, which is otherwise ambiguous (it could mean a literal less-than sign etc). This gives:
git log $log_args $(git for-each-ref --contains=$rev --format='%(refname)')
If your git for-each-ref
is too old to handle --contains
, you must use git branch --contains
and strip off the first two columns, e.g.:
git log $log_args $(git branch --contains $rev | cut -c3-)
This has a flaw because git branch
does not prefix the branch names with refs/heads
. If you have a branch named xyzzy
and a tag also named xyzzy
, git branch
knows to use the branch name, and --branches=xyzzy
would know to use the branch rather than the tag, but just naming xyzzy
on the command line will get you the tag, because in general tags have higher priority than branches. (See the gitrevisions documentation, which lists the six steps taken to resolve a name: try it as a tag is step 3 and try it as a branch is step 4. The tag has higher priority.) To fix that—to avoid this xkcd—you need to fancy it up some more:
git log $log_args $(git branch --contains $rev | cut -c3- | sed s,^,refs/heads,)
for instance. (And of course, see also this xkcd.)
Upvotes: 2