Creating git commits dated to the last modified timestamp of a file


It turns out that you can make a commit with an arbitrary timestamp!

This can be useful if you forget to commit a change, or if you’d like to cross-reference your git log to other records of your activity history, such as your browser history.

Here, I will assume that you have made a change to a file in your git repository some time since the last commit. That is to say, you would like to create a new commit with a specific timestamp, without rewriting existing history1, such that the order of timestamps will remain chronological.

If you create a new commit, timestamped chronologically before the preceding commit, interfaces such as GitHub might show them incorrectly. For example, at the time of writing, the commit view on GitHub (like https://github.com/torvalds/linux/commits/master) lists commits chronologically, which is not the same ordering as the listing produced by git log.

Modifying the timestamp of a new commit

The most reliable way of setting a timestamp is to set both the GIT_AUTHOR_DATE and GIT_COMMITTER_DATE environment variables before running git commit. You should set both of these to a timestamp in a format understood by git.

In the following snippets, I’ll commit a file foo, setting both the AuthorDate and the CommitDate to the time when this file was last modified.

On Linux

Paste the following snippet into a bash shell. It uses the date command to return the date when the file was last modified as a Unix timestamp, understood by git.

1
2
3
4
5
6
last_modified=$(date -r foo +%s)
export GIT_AUTHOR_DATE=$last_modified
export GIT_COMMITTER_DATE=$last_modified
git add foo
git commit -m "update the file foo"
unset last_modified GIT_AUTHOR_DATE GIT_COMMITTER_DATE

The last line unsets/removes the variables used so that they do not interfere with any subsequent commands.

On Windows

Paste the following snippet into a PowerShell prompt. It uses a standard format string to return the timestamp in the ISO 8601 format understood by git:

1
2
3
4
5
6
7
8
$lastModified = (Get-Item .\foo).LastWriteTime.ToString("s")
$env:GIT_AUTHOR_DATE = $lastModified
$env:GIT_COMMITTER_DATE = $lastModified
git add foo
git commit -m "update the file foo"
Remove-Variable lastModified
Remove-Item env:GIT_AUTHOR_DATE
Remove-Item env:GIT_COMMITTER_DATE

The last three lines unset/remove the variables used so that they do not interfere with any subsequent commands.

What’s really going on

It turns out that there are two timestamp values associated to each commit: the ‘AuthorDate’ and the ‘CommitDate’. You can run git --no-pager log -1 --stat --pretty=fuller to inspect both values associated to the latest commit.

Use cases

The biggest use case for going through all this effort in my experience is the ability you gain to cross-reference your activity across various platforms.

For example, if you were debugging/researching an issue with your project and consequently made some code changes, it can be helpful to make a commit as soon as possible after you’re done editing files. If you would like to revisit the research material you came across at the time, you can look up the websites you visited that day, or the Google searches you made, using Google Activity, isolating the dates close to the relevant commit timestamps.

This process can be similarly useful if you are using git for note-taking, as you might want to revisit the online activity associated with a particular note.

References

https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables#_committing

http://giantdorks.org/alain/how-to-reset-date-timestamps-for-one-or-more-git-commits/


  1. If you do need to rewrite existing history, read the relevant chapter of the Git Pro book, or the tutorial on rewriting history from Atlassian. You will have to think about how to make use of the available tools to meet your specific needs. ↩︎