As far back as commit c64b9b8 (git 0.99, May 2005), time has always been referred as
Date in ‘seconds since epoch’
commit 6eb8ae0 defines date as an
unsigned long since April 2005.
date before unix epoch can be stored, but cannot be sure to be correctly represented.
But that has evolved since 2014 (see at the end)
Trying to represent a date before has been attempted before: see this thread
The date I’m trying to set is October 4, 1958, that is around timestamp -354808800.
First technique, using the commit
--dateflags with ISO 8601: it says
Second technique, described in the git ml archive, not using the porcelain:
git commit git cat-file -p HEAD > tmp.txt # at this point, edit the file to replace the timestamp git hash-object -t commit -w tmp.txt #=> 2ee8fcc02658e23219143f5bcfe6f9a4615745f9 git update-ref -m 'commit: foo' refs/heads/master \ 2ee8fcc02658e23219143f5bcfe6f9a4615745f9
Commit date is effectively updated, but
git showclamps the date to zero (
Jan 1 1970).
55 years agoso the actual commit date is properly stored.
Last issue: when trying to push this commit to a remote repository:
#=> remote: error: object 2ee8fcc02658e23219143f5bcfe6f9a4615745f9:invalid # author/committer line - bad date #=> remote: fatal: Error in object #=> error: unpack failed: index-pack abnormal exit
Finally, when running
test-datefrom git sources:
./test-date show -354808800 #=> -354808800 -> in the future
The discussion at the time mentioned:
I am not sure there isn’t some unportability at the lowest level.
We freely interchange between time_t and unsigned long in the low-level date code. It probably happens to work because casting the bits back and forth between signed and unsigned types generally works, as long as you end up with the type that you want.
But it isn’t necessarily portable, and there can be subtle bugs. See, for example, my recent 9ba0f033.
The good news that this is purely a code problem. The data format is fine. It would just take somebody going through the code and switching all “
unsigned long” to “
long long” (or
time_t, or even “
gittime_t” if we want to abstract it).
and fixing the parser algorithm at least in
It is not just “
sed s/unsigned long/long long“, but rather checking every change to make sure that you aren’t introducing new bugs, and that the code correctly handles signed
Which is why nobody has done it. 😉
As I mentioned in 2017, in “Use future date while making git commits”, Git has started to adopt a different and dedicated
As illustrated in Legilibre/Archeo-Lex issue 47:
Dates are now using the
timestamp_ttype, defined as
typedef uintmax_t timestamp_t;, in place of
unsigned longtype, in order to fix some issues on 32bits platforms… and Windows 64 bits ^^.
The project archeo-lex.fr (which depends on older dates) is using git hash-object, combined with the Git repo viewer
This is now (Feb. 2019) done, as commented by Seb35