Subject: Re: Possible git blame bug?

From: Junio C Hamano <[email-masked]>
Date: Mon, 13 Mar 2017 15:19:47 -0700

Domagoj Stolfa <[email-masked]> writes:

> For example, saying:
>
> $ git blame time.h --since=2017
> ^e19f2a27ed8 (Domagoj Stolfa 2017-03-12 20:43:01 +0100  33) #ifndef _SYS_TIME_H_
>
> $ git blame time.h --since=2016
> ^21613a57af9 (bz  2016-03-13 21:26:18 +0000  33) #ifndef _SYS_TIME_H_
>
> $ git blame time.h --since=2015
> ^48507f436f0 (mav 2015-03-13 21:01:25 +0000  33) #ifndef _SYS_TIME_H_
>
> and so on, with different hashes.

The output lines "^deadbeef" does *NOT* mean that commit deadbeef
changed the revision.  It just is telling you that the hisory was
dug down to that revision and it was found that since that revision
there is no change (and you told the command not to bother looking
beyond that time range, so we do not know what happened before that
time).

It is understandable, when your history has a lot of merges, the
history traversal may stop at commits on different branches.

Imagine a case where the line in question never changed throughout
the history:

          o---o---B
         /         \
    O---o---o---A---C---o---o

Imagine A is from 2015, B is from 2016 and C is from 2017.  C's
first parent, i.e. C^1, is A and C^2 is B.

If you ask the command to stop digging when you hit a commit on or
before 2017-03-13 (03-13 is because today's date is appended to your
2017), your traversal will stop at C and you get a line that begins
with ^C.

If you ask it to stop at 2016, A won't be even looked at because it
is older.  The command will keep digging from C to find B.  If B's
parent is also newer than the cutoff, but its parent is older, then
the line will be shown with ^ and commit object name of B's parent.

If you ask it to stop at 2015, the command will first consider A
(C's earlier parent) and pass blame to the lines common between
these two commits.  In this illustration, we are pretending that the
file did not change throughout the hsitory, so blame for all lines
are passed to A and we don't even look at B.  Then we keep digging
through A to find the culprit, or hit a commit older than the
specified cut-off time.  The line will be shown with ^A or perhaps
its ancestor.

So it is entirely sane if you saw three boundary commits named with
three different time ranges.