Karu
Karu

Reputation: 4627

List Git commits between a and b, considering only first parents of b AND only first parents of a

With Git you can list all ancestors of b, excluding all ancestors of a:

git log a..b

You can also list all first-parent ancestors of b, excluding all ancestors of a:

git log --first-parent a..b

But I want to list all first-parent ancestors of b, excluding all first-parent ancestors of a. I haven't found any way to get the first-parent requirement to also apply to the negative part(s) of a revision range.

Is there a way to do this? If there's no way to do this using only Git commands, is there a plausible way to achieve this with a Bash script?


Some more detail. For this commit graph (parents shown in left-to-right order):

    b --> 9
          |\
          | \
          |  \
a --> 6   7   8
      |\  |   |
      | \ |   |
      |  \|   |
      3   4   5
       \  |  /
        \ | /
         \|/
          2
          |
          |
          1

git log a..b would list 9, 8, 7 and 5. git log --first-parent a..b would list 9 and 7. I'm looking for a way to list 9, 7 and 4.

Upvotes: 2

Views: 69

Answers (1)

LeGEC
LeGEC

Reputation: 52226

You can build the two lists, and use grep to exclude one from another :

git rev-list --first-parent a > lista.txt
git rev-list --first-parent b > listb.txt

# use grep, use '-f' to read patterns from 'lista.txt',
# use '-v' to say "exclude these patterns"
cat listb.txt | grep -v -f lista.txt

You can avoid creating the files on disk ; in bash and zsh you can use a so called process substitution (syntax is : <(command)) :

git rev-list --first-parent b | grep -v -f <(git rev-list --first-parent a)

One extra flag you can use with grep is -F, --fixed-strings) : since in this case all patterns are flat strings (not regexps), you can indicate that to grep, it speeds things up

git rev-list --first-parent b | grep -v -F -f <(git rev-list --first-parent a)

Upvotes: 6

Related Questions