Say I have the following git repo:
I want to specify a git rev-list of all branches (--all
) but excluding a given branch (say, feature-D
), but I want to show common ancestors of feature-D
and the other branches i.e. commit Initial
and 1
.
If I try git rev-list --all ^feature-D
commits Initial
and 1
are excluded:
Of course I can list all branches except for feature-D
explicitly (git rev-list feature-A feature-B feature-C
) to get what I want:
But is there a way to specify a rev-list that obtains the prior result, only by reference to feature-D
?
(Note that this question was inspired by this answer: https://stackoverflow.com/a/20978568/430128)
This is a bit indirect but seems to work. We start with:
git rev-list --no-walk --all ^feature-D
which produces a list of all SHA-1s directly pointed to by any ref (including tags, branches, stashes, etc; use --branches
rather than --all
if you want only branches) except those under feature-D
:
$ git log --oneline --decorate --graph --all
* 74e0d3e (feature-D) 7
* 0448a13 6
| * ab3a532 (feature-C) 5
|/
| * 50477c7 (feature-B) 4
| * 28717e5 3
|/
* 2ac5cef (HEAD, master, feature-A) 2
* c6a10b4 1
* 76c511f Initial
$ git rev-list --no-walk --all ^feature-D
ab3a5320e792e945b896634d667df5ace4a8b871
50477c7b28b5479587e45fe97292e71a3c0851c5
28717e5628ad111e8b68323dc485fd190a780446
Now we feed this to git rev-list
again to get the history-walking:
$ git rev-list --no-walk --all ^feature-D | git rev-list --stdin
ab3a5320e792e945b896634d667df5ace4a8b871
50477c7b28b5479587e45fe97292e71a3c0851c5
28717e5628ad111e8b68323dc485fd190a780446
2ac5cefb971c7f5c5be33a77a6db71127982eaf5
c6a10b4568136d65b31b7e262ef7745db4962460
76c511fcf38076e0ea98db73a4923de6fc806b4a
Pipe that to git log --oneline --decorate --graph --stdin
to verify that those are the right commits, if eyeballing it is not sufficiently clear:
* ab3a532 (feature-C) 5
| * 50477c7 (feature-B) 4
| * 28717e5 3
|/
* 2ac5cef (HEAD, master, feature-A) 2
* c6a10b4 1
* 76c511f Initial
(and one side note: if using git log --oneline --decorate --graph
to view your middle version, i.e., git rev-list --all ^feature-D
, you need to add --boundary
to see commit 2; gitk probably adds --boundary
to make it show up, not that I tested this).
There's a defect here: if feature-C
and feature-B
branches did not exist you would not see commits 2 through Initial. I'm not sure, but I think the only real fix for this is to use something much more complex.
Edit: ok, not that much more complex. Start with git for-each-ref
to print branches. Pipe through grep -v ^feature-D$
to eliminate feature-D
. Now you have all the branches you want as arguments:
$ git log --oneline --graph --decorate $(git for-each-ref \
> --format '%(refname:short)' refs/heads/ | grep -v '^feature-D$')
* ab3a532 (feature-C) 5
| * 50477c7 (feature-B) 4
| * 28717e5 3
|/
* 2ac5cef (master, feature-A) 2
* c6a10b4 1
* 76c511f Initial
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