1

In git help log and git help revisions, it is documented how to include or exclude specific commits/refs and their ancestors in git log.

I am now looking for a way to exclude children of a given rev, and combine this with other range specifiers.

So:

  • Include TARGET and its ancestors
  • Exclude BASE_1 and all its parents / ancestors, even if they are ancestors of TARGET.
  • Exclude BASE_2 and all its parents / ancestors, even if they are ancestors of TARGET.
  • Exclude START_1 and all its children / descendants, even if they are ancestors of TARGET. In my case, START_1 is an ancestor of TARGET, but is not an ancestor of any of the other revs I am excluding.

The first three steps can be done with ^ negation, or with --not.

git log TARGET ^BASE_1 ^BASE_2

The last step would require something new, which I don't know if it exists.

git log --exclude-descendants-of=START_1 TARGET ^BASE_1 ^BASE_2

Use case / motivation

We have an "acceptance" branch which merges a lot of feature branches. It also contains some commits that were done directly on acceptance, to amend faulty merges (don't judge!).

I am rebasing this on master with git rebase -i --rebase-merges to preserve branch topology.

I want find out which feature branches were merged to the old version, but not (yet) to the rebased version. I want to exclude from this list the feature branches that I already know to be missing, so that I can narrow it down step by step.

So I would have something like this:

git log --exclude-descendants-of=START_OF_OLD_ACC origin/acceptance ^acceptance ^FEATURE_1 ^FEATURE_2

What I considered so far

I already found --ancestry-path. But I don't see how I can negate this and combine with other range specifiers to achieve the desired result.

Alternatives

Alternatively, I would already be happy if I could exclude all commits that appear in git log --first-parent TARGET, because these happen to be more or less the same as the descendants I would like to exclude.

Related

git log range exclude ancestors of multiple base refs

donquixote
  • 4,877
  • 3
  • 31
  • 54
  • 1
    You'll need a compound operation using `--stdin` or an external program such as `comm`. For instance, you could use `--ancestry-path` to get a list of commits to knock out, then use `git rev-list` for a list of commits to include, and last, use `comm` to exclude the excluded commits from the included ones. If `--stdin` combines well with `--not` (I suspect it doesn't) that would let you do it all with `git rev-list`. – torek Apr 05 '20 at 19:41
  • Your answers and comments are always appreciated @torek! I sounds like what you propose requires some extra steps of learning. – donquixote Apr 05 '20 at 20:03
  • I think `--not` will remove all ancestors of the listed revisions, not just the commit itself. So I suspect your idea would not work. – donquixote Apr 05 '20 at 20:04
  • In the meantime I generated the list of commits to exclude with `--ancestry-path`, used a text editor to turn this into a grep condition, then used `git log ... | egrep -v "commit_1|commit_2|commit_3|..."`. Feels dirty but kinda works. – donquixote Apr 05 '20 at 20:06
  • 1
    Consider `fgrep` instead of `egrep` as you have fixed strings to eject from the overall list, but either way that seems like a reasonable approach. – torek Apr 05 '20 at 23:08
  • 1
    Oh: and, on reading your use-case section, I'd suggest looking at the `git patch-id` documentation too. – torek Apr 05 '20 at 23:10

0 Answers0