5

Does any know why before include finish date?

The date 2021-07-01 14:13 actually is after 2021-07-01

enter image description here

Why results are wrong?

git version is 2.32.0

Eugen Konkov
  • 22,193
  • 17
  • 108
  • 158
  • 5
    Given that `--before` and `--until` are synonyms, and it makes sense for `--until` to be inclusive, I lean towards "poorly documented" rather than "buggy". (One could also charitably argue that `2021-07-21` is short for `021-07-21 23:59:59`.) – chepner Jul 02 '21 at 18:43
  • 2
    Perhaps the documentation could use some updating. Other's have [commented](https://stackoverflow.com/questions/19110178/git-log-before-some-commit-date#comment114867287_19110603) on this as well. – TTT Jul 02 '21 at 18:46
  • Programmers are notoriously bad for understanding or adhering to normal concepts and expectations, so programmers shouldn't be the ones making user interfaces. This includes command-line commands, options and arguments. Only a programmer can develop a believable explanation for why "before a certain date" also includes that date. – Lasse V. Karlsen Jul 02 '21 at 19:20

2 Answers2

8

Note the date filters use the commit datetime, not the author datetime.

Although it isn't documented, as noted in jthill's answer and confirmed by my limited testing, surprisingly, it appears that all the date filters, when a time is not specified, refer to the current time of the day on your client machine! Note you can specify a time if you wish to override that:

git log --before=2021-07-02T23:59:59 (end of the day)

or

git log --before=2021-07-02T00:00:00 (beginning of the day)

Below is my test script. It generates a new repo with one empty commit with a committer date from 2 days ago minus 1 minute. (So that 1 minute from now the commit will be exactly 2 days ago.) Then the script loops for a minute and every 10 seconds it prints out the current time, as well as the log using --before and --after options. At first --before doesn't show anything and --after shows the commit, but after a minute the logs flip once the current time surpasses that of the commit date:

#!/bin/bash

# create a test repo
git init
echo ""

# create a date which is 2 days ago minus 1 minute
var1=$(date --date '-2879 min')
# create a date that is the first date in only YYYY-MM-DD format
var2=$(date -d "$var1" +%F)
# show the variables
echo "var1=$var1"
echo "var2=$var2"
echo ""

# create an empty commit with a committer date set to 2 days ago minus 1 minute
GIT_COMMITTER_DATE=$var1 git commit --allow-empty -m 'Create an empty commit'

# display the log; there should only be 1 commit
git log --pretty=fuller
echo ""

# Every 10 seconds for 70 seconds, display the log before 2 days ago without a time specified.
# As soon as the current time passes the time of the commiter_date on the commit, the log will show.
for (( x=1; x<=8; x++ ))
do  
    echo "Current time: $(date)"
    echo "Output of: 'git log --before=$var2':"
    git log --before=$var2
    echo ""
    echo "Output of: 'git log --after=$var2':"
    git log --after=$var2
    echo ""
    sleep 10
done
TTT
  • 22,611
  • 8
  • 63
  • 69
  • 1
    Still badly documented. This is not how dates or anything else that has a sequential orderly order works. "Before X" does not include X, as in "nobody expects that". – Lasse V. Karlsen Jul 02 '21 at 19:22
  • 1
    The problem isn't so much with "before" as using a non-standard expansion of `2021-07-02` to be the end of the day rather than the beginning (which I think is a far more common interpretation). – chepner Jul 02 '21 at 19:25
  • 1
    No, the "end of day" interpretation is exactly what programmers do. For everyone else, "2021-07-02" is a date, not a time on that date. Before the 2nd of February does not mean "any time on the 2nd of February or before", it really means "before". The 1st of February is before, 12 o'clock on 2nd of February is comparing apples and oranges, one is a date, the other is a time of day on a date, and if you ask any non-programmer whether "12 o'clock on 2nd of February" is "before 2nd of February" you're either going to get a "no" or a tilted head asking "what are you actually asking right now". – Lasse V. Karlsen Jul 02 '21 at 19:33
  • 1
    @LasseV.Karlsen since I tested late in the day, I wrongly concluded that the times were end of day. IMHO the newly updated answer is even worse news, since every time you run it you could get a different result! Also, please go upvote jthill's answer, since he discovered it before I did. – TTT Jul 03 '21 at 06:15
  • @chepner please see my previous comment. – TTT Jul 03 '21 at 06:16
  • @LasseV.Karlsen: you're quite correct. But note that "after 2nd of Feb" clearly means Feb 3 and later, not 23:59:59 of Feb 2 for instance. Yet if you ask that same human if "after 2nd Feb" includes *on* 2-Feb, you'll probably get a "yes" answer *provided* you prefix the question with one about exactly what "before 2nd Feb" means. Humans are simply not consistent. – torek Jul 03 '21 at 12:38
4

If you don't specify a time on your cutoff it uses the current wall clock,so --before=yesterday asked at 5pm means before 5pm yesterday. If you want to specify midnight add T00:00, --before=yesterday.T00:00. I have this as surprising enough to count as a full-fledged wart, like find's behavior with sizes. This is unfortunately used by core commands, so-called "plumbing", and Git has explicitly promised script writers that their behavior and so this date parsing wart won't change.

edit: try this:

unset head; for h in {0..23}; do
    head=$( GIT_COMMITTER_DATE=`date -d yesterday\ T$h:00` \
                    git commit-tree ${head+-p $head} -m - @: )
done

git log -1 --pretty=fuller $head
git log -1 --pretty=fuller --before=yesterday $head

and you'll see that before=yesterday picks the one with the commit timestamp before the current wall clock.

jthill
  • 55,082
  • 5
  • 77
  • 137