confusion about git rev-list

Marslo picture Marslo · Jul 6, 2017 · Viewed 10.8k times · Source

I want to know the related commit-id with the 100 submit in branch dev. (for example: git rev-list --reverse --branches=dev --date-order --count <commit-id> == 100):

And got the 100 commit is 1f345e80fba518c72dec7f2e02da5da12be5810f:

$ git rev-list --reverse --branches=dev --date-order HEAD | head -100 | tail -1
1f345e80fba518c72dec7f2e02da5da12be5810f

$ git rev-list --reverse --branches=dev --date-order HEAD | nl | grep 100
   100  1f345e80fba518c72dec7f2e02da5da12be5810f

$ git rev-list --reverse --branches=dev --date-order HEAD | awk '{print NR"\t"$0}' | grep -E ^100
100     1f345e80fba518c72dec7f2e02da5da12be5810f

However, when I try to verify the rev-number about this commit-id (1f345e80fba518c72dec7f2e02da5da12be5810f), the result shows: rev number is 98!!!

$ git rev-list --reverse --branches=dev --date-order --count 1f345e80fba518c72dec7f2e02da5da12be5810f
98

$ git rev-list --reverse --branches=dev --date-order 1f345e80fba518c72dec7f2e02da5da12be5810f | nl | tail -1
    98  1f345e80fba518c72dec7f2e02da5da12be5810f

So I try to find out which 2 commit is missing:

$ git rev-list --reverse --branches=dev --date-order HEAD | head -100 | nl > commit-100.log
$ git rev-list --reverse --branches=dev --date-order 1f345e80fba518c72dec7f2e02da5da12be5810f | head -100 | nl > commit-98.log
$ diff -y commit-100.log commit-98.log
 90  63546ce0207cdd6ade353ea05c466d0210af1d29              |     90  75a8fd85043908049e11595aaa2c988282fa1a0c
 91  75a8fd85043908049e11595aaa2c988282fa1a0c              |     91  c1bbb33cd0241c16dde2579696c08ed2eb146cdf
 92  c1bbb33cd0241c16dde2579696c08ed2eb146cdf              |     92  28e9bbc06cb3036bce4cce71f5acf4b27835e9a0
 93  28e9bbc06cb3036bce4cce71f5acf4b27835e9a0              |     93  7b1d0caddc6218eb982d27c1df27c885bc84204c
 94  7b1d0caddc6218eb982d27c1df27c885bc84204c              |     94  945fd63a256391e72e55e8ac98c449c1473c1e5e
 95  945fd63a256391e72e55e8ac98c449c1473c1e5e              |     95  0ff3f47eb8dc40815ac7effdb2172e5d69dd0e10
 96  0ff3f47eb8dc40815ac7effdb2172e5d69dd0e10              |     96  ac90a7b2a371ff7a0fad0475d94691663aceaa1b
 97  ac90a7b2a371ff7a0fad0475d94691663aceaa1b              |     97  1a0e26b517f88870fed0cf5f346495b67c29463a
 98  937807239dd706f3bf124dd4d3266c71fd8071f4              |     98  1f345e80fba518c72dec7f2e02da5da12be5810f
 99  1a0e26b517f88870fed0cf5f346495b67c29463a              <
100  1f345e80fba518c72dec7f2e02da5da12be5810f              <

Apparent, the 2 missing commit-id is:

90  63546ce0207cdd6ade353ea05c466d0210af1d29
98  937807239dd706f3bf124dd4d3266c71fd8071f4

According to git show <commit-id>, and nothing strange. These two commits was submitted by the same guy. But this person committed 10 times in the first 100 commits.

Does it a git rev-list issue?

Answer

torek picture torek · Jul 6, 2017

I don't know quite what you are trying to do, but git rev-list does not do that, whatever it is.

What git rev-list does is to list reachable commits, by walking the commit graph, starting from particular set of starting-points, while applying some set of constraints. The walk itself may be done in a particular order, some commits may be optionally simplified away, you can stop the walk early with --max-count or skip some initial commits with --skip, and after the set of commits is found it can be reversed and/or counted.

You set no constraints on the graph itself (no path arguments) and did not enable any simplification modes or skips or max counts, but you did ask to reverse the set in the end.

Your starting points are --branches=dev (which means --branches=dev/*) and HEAD in one case, and --branches=dev and commit 1f345e80fba518c72dec7f2e02da5da12be5810f in another.

You asked for the walk to be done in --date-order, which means that whenever Git has two commits it could walk right now, it should select the one with the later commit time stamp, as long as it is not selecting the parent of a child commit that it has not yet selected.

The set of commits reachable from HEAD may include commits not reachable from from the set of commits selected by refs/heads/dev/* (all dev branches). The set of commits reachable from 1f345e80fba518c72dec7f2e02da5da12be5810f may also differ, if 1f345e80fba518c72dec7f2e02da5da12be5810f is not itself reachable from one of the dev branches. It's not surprising that the 100th such commit (after reversing the list) differs.