I want to log all changes on a specific set of branches to see the relationshop between them, and I found that:
git log --graph --oneline --topo-order --decorate --simplify-by-decoration `git branch --list -a origin/foo/*`
does exactly what I want (i.e. log changes on all branches that are prefixed with foo/*).
But now I am curious about the --branches
option of git log. It seems like that should work in a similar way, but if I use --branches=origin/foo/*
or --branches=remotes/origin/foo*
or even --branches=foo
the output is very different (only very few and irrelevant commits are showing).
The documentation say:
--branches[=<pattern>]
Pretend as if all the refs in refs/heads are listed on the command line as
<commit>. If <pattern> is given, limit branches to ones matching given shell
glob. If pattern lacks ?, *, or [, /* at the end is implied.
What is the difference ? My problem is already solved since I can use the first version - but I am asking this since I am curious. ( And also adding a git alias is slightly simpler if use of back ticks can be avoided. )
This question discusses related topics - but I could not see any info about my specific issue.
Now that's a perfect case of "you need to know git's internals to understand the documentation". Which we would need less of.
The documentation for --branches
states it works on "refs in refs/heads". Remote-tracking references aren't in refs/heads
, they're in refs/remotes
. Because of that, when looking for "origin/foo/*", no branch will be found. So git log will revert to its default behaviour, which is to start discovering commits from HEAD
.
You need to use the --remotes
option, which is similar to --branches
but works for refs in refs/remotes
. So that becomes:
git log --graph --oneline --topo-order --decorate --simplify-by-decoration --remotes='origin/foo/*'
Alternatively, you can use --glob
, which works on all branches, but then you need to prepend heads/
or remotes/
, or use a wildcard. For instance:
git log --graph --oneline --topo-order --decorate --simplify-by-decoration --glob='refs/*/foo/*'
On a side note, your first command won't work in all cases, because you're using git branch
, which is a porcelain command, inside your backticks. It may break in the future because the output of porcelain commands is subject to change. In fact, it does break already on some cases like when you're listing HEAD
. For instance:
git log --graph --oneline --topo-order --decorate --simplify-by-decoration $(git branch --list -a 'origin/*')
This command gave me an error, saying it couldn't recognize ->
as an argument. That's because of the output of git branch
:
remotes/origin/HEAD -> origin/master
remotes/origin/master
To make your command work in all cases and be future-proof, you can use git for-each-ref
(which is a plumbing command), like so:
git log --graph --oneline --topo-order --decorate --simplify-by-decoration $(git for-each-ref --format='%(refname)' 'refs/remotes/origin/*')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With