4

I have a problem very similar to this one, but I can't figure out how to apply the solution there to my case, because my case is slightly more complex.

Considering the following history:

X0 - X1 - - X - X - Xn - ... - Xinf
 \         /   /   /
  \   C - D   /   /
   \ /     \ /   /
    A - E - F - H
     \ /     \ /
      B       G

master points to Xinf, and release points to H.

After the release branch was created from master, a bunch of fixes were made. Some of them were only merged into release (e.g. B and G), some of them were merged both into release and master (e.g. C-D). The release branch was also merged back into master several times. In this example I've ensured that all of these things have happened, but in reality they can have happened more times (or less) than indicated by my example.

Given knowledge only about the release and master refs, how can I get a list of all commits in the release branch, i.e. A through H?

I've created a sample repo with the history outlined above to make this easier to test.

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402
  • 2
    The simplest thing to do is `git rev-list release` or `git log release`, but that includes commit `X0` because `X0` is reachable from `A` (it's the parent of `A`). To cut that off, use `^A^`, but of course you'll have to find `A` first, or use `^X0`, but you'll have to find `X0` first. – torek May 05 '20 at 17:15
  • 1
    Fundamentally, there's no automatic way to find `X0`. You can use `git log --first-parent master` to trace all the `X` commits, but there is no way to know which one to use as the stop item. `X0` and `X1` will both work as stop items (`^X1` is fine) but some of the X's have, e.g., D or F as a parent and hence won't work: they'll stop out too many commits. – torek May 05 '20 at 17:17
  • 1
    If you already know `A`, you can find a correct stop item by checking for X's that are ancestors of `A`. In this case only `X0` is an ancestor. But if you know `A` you can just use `^A^`. – torek May 05 '20 at 17:18

1 Answers1

2

One way to target X0 is :

  • it is the closest ancestor which is both in the chain of first parents from master and the chain of first parents from release

I don't know how to do it in one go with git rev-list or git log alone, but here is a way to get it through a script :

# get the list of first-parents of master, store this list in a file :
$ git rev-list --first-parent master > /tmp/tmp-rev-list

# get the list for release, and grep it using 'tmp-rev-list'
# commits will be listed in topo order, 'X0' is the first one :
$ git rev-list --first-parent release | grep -f /tmp/tmp-rev-list | head -1

You can speed up grep by using -F (meaning : all patterns are blunt strings, no regexp there),
and you can skip the tmp file using <( ... ) :

$ X0=$( git rev-list --first-parent release |\
    grep -Ff <(git rev-list --first-parent master) |\
    head -1 )

# obviously : it would be better to write this command in a script,
# and then use it to get X0:   X0=$(bash myscript.sh)

Once you have this commit id, you can just run :

$ git log $X0..release
LeGEC
  • 46,477
  • 5
  • 57
  • 104