Use git rev-list to exclude a branch, but keep common ancestors with the included branches
git, version-control
Solution
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
Problem
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)