How can one change the timestamp of an old commit in Git?

GitTimestampCommitGit Rewrite-History

Git Problem Overview


The answers to https://stackoverflow.com/questions/179123/how-do-i-edit-an-incorrect-commit-message-in-git describe a way to amend previous commit messages that haven't yet been pushed upstream. The new messages inherit the timestamps of the original commits. This seems logical, but is there a way to also re-set the times?

Git Solutions


Solution 1 - Git

You can do an interactive rebase and choose edit for the commit whose date you would like to alter. When the rebase process stops for amending the commit you type in for instance:

git commit --amend --date="Wed Feb 16 14:00 2011 +0100" --no-edit

P.S. --date=now will use the current time.

Afterward, you continue your interactive rebase.

To change the commit date instead of the author date:

GIT_COMMITTER_DATE="Wed Feb 16 14:00 2011 +0100" git commit --amend --no-edit

The lines above set an environment variable GIT_COMMITTER_DATE which is used in amending commit.

Everything is tested in Git Bash.

Solution 2 - Git

Use git filter-branch with an env filter that sets GIT_AUTHOR_DATE and GIT_COMMITTER_DATE for the specific hash of the commit you're looking to fix.

This will invalidate that and all future hashes.

Example:

If you wanted to change the dates of commit 119f9ecf58069b265ab22f1f97d2b648faf932e0, you could do so with something like this:

git filter-branch --env-filter \
    'if [ $GIT_COMMIT = 119f9ecf58069b265ab22f1f97d2b648faf932e0 ]
     then
         export GIT_AUTHOR_DATE="Fri Jan 2 21:38:53 2009 -0800"
         export GIT_COMMITTER_DATE="Sat May 19 01:01:01 2007 -0700"
     fi'

Solution 3 - Git

A better way to handle all of these suggestions in one command is

LC_ALL=C GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"

This will set the last commit's commit and author date to "right now."

Solution 4 - Git

Just do git commit --amend --reset-author --no-edit. For older commits, you can do an interactive rebase and choose edit for the commit whose date you want to modify.

git rebase -i <ref>

Then amend the commit with --reset-author and --no-edit to change the author date to the current date:

git commit --amend --reset-author --no-edit

Finally continue with your interactive rebase:

git rebase --continue

Solution 5 - Git

I wrote a script and Homebrew package for this. Super easy to install, you can find it on GitHub PotatoLabs/git-redate page.

Syntax:

git redate -c 3

You just have to run git redate and you'll be able to edit all the dates in vim of the most recent 5 commits (there's also a -c option for how many commits you want to go back, it just defaults to 5). Let me know if you have any questions, comments, or suggestions!

enter image description here

Solution 6 - Git

Each commit is associated with two dates, the committer date and the author date. You can view these dates with:

git log --format=fuller

If you want to change the author date and the committer date of the last 6 commits, you can simply use an interactive rebase :

git rebase -i HEAD~6

.

pick c95a4b7 Modification 1
pick 1bc0b44 Modification 2
pick de19ad3 Modification 3
pick c110e7e Modification 4
pick 342256c Modification 5
pick 5108205 Modification 6

# Rebase eadedca..5108205 onto eadedca (6 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

For all commits where you want to change the date, replace pick by edit (or just e), then save and quit your editor.

You can now amend each commit by specifying the author date and the committer date in ISO-8601 format:

GIT_COMMITTER_DATE="2017-10-08T09:51:07" git commit --amend --date="2017-10-08T09:51:07"

The first date is the commit date, the second one is the author date.

Then go to the next commit with :

git rebase --continue

Repeat the process until you amend all your commits. Check your progression with git status.

Solution 7 - Git

git commit --amend --date="now"

Solution 8 - Git

How to Edit Multiple Commit Dates

Other answers aren't very convenient for editing several commit dates. I've come back to this question after a few years to share a technique.

To change the dates of the last 4 commits:

git rebase -i HEAD~4

Edit the rebase as follows, inserting exec lines to modify dates as needed:

pick 4ca564e Do something
exec git commit --amend --no-edit --date "1 Oct 2019 12:00:00 PDT"
pick 1670583 Add another thing
exec git commit --amend --no-edit --date "2 Oct 2019 12:00:00 PDT"
pick b54021c Add some tests
exec git commit --amend --no-edit --date "3 Oct 2019 12:00:00 PDT"
pick e8f6653 Fix the broken thing
exec git commit --amend --no-edit --date "4 Oct 2019 12:00:00 PDT"
Update (Sep. 2021):

If you want to see the original commit date in the rebase instruction list (Git 2.6+):

git config --add rebase.instructionFormat "[%ai] %s"

Then you'll see something like

pick 4f5a371f [2021-09-08 02:56:50 -0700] Add npm events
pick 67937227 [2021-09-09 03:05:42 -0700] Fixup

Solution 9 - Git

Building on theosp's answer, I wrote a script called git-cdc (for change date commit) that I put in my PATH.

The name is important: git-xxx anywhere in your PATH allows you to type:

git xxx
# here
git cdc ... 

That script is in bash, even on Windows (since Git will be calling it from its msys environment)

#!/bin/bash
# commit
# date YYYY-mm-dd HH:MM:SS

commit="$1" datecal="$2"
temp_branch="temp-rebasing-branch"
current_branch="$(git rev-parse --abbrev-ref HEAD)"

date_timestamp=$(date -d "$datecal" +%s)
date_r=$(date -R -d "$datecal")

if [[ -z "$commit" ]]; then
    exit 0
fi

git checkout -b "$temp_branch" "$commit"
GIT_COMMITTER_DATE="$date_timestamp" GIT_AUTHOR_DATE="$date_timestamp" git commit --amend --no-edit --date "$date_r"
git checkout "$current_branch"
git rebase  --autostash --committer-date-is-author-date "$commit" --onto "$temp_branch"
git branch -d "$temp_branch"

With that, you can type:

git cdc @~ "2014-07-04 20:32:45"

That would reset author/commit date of the commit before HEAD (@~) to the specified date.

git cdc @~ "2 days ago"

That would reset author/commit date of the commit before HEAD (@~) to the same hour, but 2 days ago.


Ilya Semenov mentions in the comments:

> For OS X you may also install GNU coreutils (brew install coreutils), add it to PATH (PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") and then use "2 days ago" syntax.

Solution 10 - Git

After reading all the answers I came up with a more succinct and convenient way of editing the date of multiple commits at once without the need of rebasing interactively:

git rebase HEAD~4 --exec "git commit --amend --no-edit --date 'now'"

It changes both the committer and author dates.

Solution 11 - Git

I created this npm package to change date of old commits.

https://github.com/bitriddler/git-change-date

Sample Usage:

npm install -g git-change-date
cd [your-directory]
git-change-date

You will be prompted to choose the commit you want to modify then to enter the new date.

If you want to change a commit by specific hash run this git-change-date --hash=[hash]

Solution 12 - Git

To change both the author date and the commit date:

GIT_COMMITTER_DATE="Wed Sep 23 9:40 2015 +0200" git commit --amend --date "Wed Sep 23 9:40 2015 +0200"

Solution 13 - Git

if it is previous last commit.

git rebase  -i HEAD~2
git commit --amend --date=now

if you already push to orgin and can force use:

git push --force 

if you can't force the push and if it is pushed, you can't change the commit! .

Solution 14 - Git

Here is a convenient alias that changes both commit and author times of the last commit to a time accepted by date --date:

[alias]
    cd = "!d=\"$(date -d \"$1\")\" && shift && GIT_COMMITTER_DATE=\"$d\" \
            git commit --amend --date \"$d\""

Usage: git cd <date_arg>

Examples:

git cd now  # update the last commit time to current time
git cd '1 hour ago'  # set time to 1 hour ago

Edit: Here is a more-automated version which checks that the index is clean (no uncommitted changes) and reuses the last commit message, or fails otherwise (fool-proof):

[alias]
    cd = "!d=\"$(date -d \"$1\")\" && shift && \
        git diff-index --cached --quiet HEAD --ignore-submodules -- && \
        GIT_COMMITTER_DATE=\"$d\" git commit --amend -C HEAD --date \"$d\"" \
        || echo >&2 "error: date change failed: index not clean!"

Solution 15 - Git

The following bash function will change the time of any commit on the current branch.

Be careful not to use if you already pushed the commit or if you use the commit in another branch.

# rewrite_commit_date(commit, date_timestamp)
#
# !! Commit has to be on the current branch, and only on the current branch !!
# 
# Usage example:
#
# 1. Set commit 0c935403 date to now:
#
#   rewrite_commit_date 0c935403
#
# 2. Set commit 0c935403 date to 1402221655:
#
#   rewrite_commit_date 0c935403 1402221655
#
rewrite_commit_date () {
    local commit="$1" date_timestamp="$2"
    local date temp_branch="temp-rebasing-branch"
    local current_branch="$(git rev-parse --abbrev-ref HEAD)"

    if [[ -z "$date_timestamp" ]]; then
        date="$(date -R)"
    else
        date="$(date -R --date "@$date_timestamp")"
    fi
    
    git checkout -b "$temp_branch" "$commit"
    GIT_COMMITTER_DATE="$date" git commit --amend --date "$date"
    git checkout "$current_branch"
    git rebase "$commit" --onto "$temp_branch"
    git branch -d "$temp_branch"
}

Solution 16 - Git

The most simple way to modify the date and time of the last commit

git commit --amend --date="12/31/2021 @ 14:00"

Solution 17 - Git

If you want to get the exact date of another commit (say you rebase edited a commit and want it to have the date of the original pre-rebase version):

git commit --amend --date="$(git show -s --format=%ai a383243)"

This corrects the date of the HEAD commit to be exactly the date of commit a383243 (include more digits if there are ambiguities). It will also pop up an editor window so you can edit the commit message.

That's for the author date which is what you care for usually - see other answers for the committer date.

Solution 18 - Git

If commit not yet pushed then I can use something like that:

git commit --amend --date=" Wed Mar 25 10:05:44 2020 +0300"

after that git bash opens editor with the already applied date so you need just to save it by typing in the VI editor command mode ":wq" and you can push it

Solution 19 - Git

If you want to perform the accepted answer (https://stackoverflow.com/a/454750/72809) in standard Windows command line, you need the following command:

git filter-branch -f --env-filter "if [ $GIT_COMMIT = 578e6a450ff5318981367fe1f6f2390ce60ee045 ]; then export GIT_AUTHOR_DATE='2009-10-16T16:00+03:00'; export GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; fi"

Notes:

  • It may be possible to split the command over multiple lines (Windows supports line splitting with the carret symbol ^), but I didn't succeed.
  • You can write ISO dates, saving a lot of time finding the right day-of-week and general frustration over the order of elements.
  • If you want the Author and Committer date to be the same, you can just reference the previously set variable.

Many thanks go to a blog post by Colin Svingen. Even though his code didn't work for me, it helped me find the correct solution.

Solution 20 - Git

Set the date of the last commit to the current date

GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"

Set the date of the last commit to an arbitrary date

GIT_COMMITTER_DATE="Mon 20 Aug 2018 20:19:19 BST" git commit --amend --no-edit --date "Mon 20 Aug 2018 20:19:19 BST"

Set the date of an arbitrary commit to an arbitrary or current date

Rebase to before said commit and stop for amendment:

  1. git rebase <commit-hash>^ -i
  2. Replace pick with e (edit) on the line with that commit (the first one)
  3. quit the editor (ESC followed by :wq in VIM)
  4. Either:
  • GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
  • GIT_COMMITTER_DATE="Mon 20 Aug 2018 20:19:19 BST" git commit --amend --no-edit --date "Mon 20 Aug 2018 20:19:19 BST"

Source: https://codewithhugo.com/change-the-date-of-a-git-commit/

Solution 21 - Git

For those using Powershell

git rebase DESIRED_REF^ -i

$commitDateString = "2020-01-22T22:22:22"
$env:GIT_COMMITTER_DATE = $commitDateString
git commit --amend --date $commitDateString
$env:GIT_COMMITTER_DATE = ""

git rebase --continue

Credit to https://mnaoumov.wordpress.com/2012/09/23/git-change-date-of-commit/

Solution 22 - Git

Edit the author date and the commit date of the last 3 commits:

git rebase -i HEAD~3 --committer-date-is-author-date --exec "git commit --amend --no-edit --date=now"

The --exec command is appended after each line in the rebase and you can choose the author date with the --date=..., the committer date will be the same of author date.

Solution 23 - Git

For updating the date of the 5 last commits to the current date (this method doesn't allow to update the initial commit):

git rebase HEAD~5 --exec "git commit --amend --no-edit --date 'now'"

For all commits after commit 95f5074…15074db2:

git rebase 95f5074…15074db2 --exec "git commit --amend --no-edit --date 'now'"

For all commits (including the initial commit):

git rebase --root --exec "git commit --amend --no-edit --date 'now'"

Add -i for the interactive mode.

Run git log --format=fuller --show-signature to validate the changes.

Run git push -f to update the remote repository (⚠️Danger zone)

There are implications. For instance:

  • Commit IDs will change, so you will have to recreate tags
  • You will lose original signatures
  • This will use your .gitconfig, this means your key will be used for signing commits (if Git is configured to sign commits)

Solution 24 - Git

I wanted to make sure that I update my code’s copyright comments at precisely midnight, and I didn’t want to risk a tiny delay with at or cron. So, I commited the code and then:

GIT_COMMITTER_DATE="Fri Jan 1 00:00:00 2021 +1000" git commit --amend --no-edit --date="Fri Jan 1 00:00:00 2021 +1000"

(Or perhaps even set the UTC offset to 0? Decisions… ) Now I can push!

Happy new year, everybody 拾

Solution 25 - Git

There are already many great answers, but when I want to change date for multiple commits in one day or in one month, I don't find a proper answer. So I create a new script for this with explaintion, hope it will help someone:

#!/bin/bash

# change GIT_AUTHOR_DATE for commit at Thu Sep 14 13:39:41 2017 +0800
# you can change the data_match to change all commits at any date, one day or one month
# you can also do the same for GIT_COMMITTER_DATE

git filter-branch --force --env-filter '

date_match="^Thu, 14 Sep 2017 13+"              

# GIT_AUTHOR_DATE will be @1505367581 +0800, Git internal format 
author_data=$GIT_AUTHOR_DATE;                   
author_data=${author_data#@}                  
author_data=${author_data% +0800}                # author_data is 1505367581     

oneday=$((24*60*60))

# author_data_str will be "Thu, 14 Sep 2017 13:39:41 +0800", RFC2822 format
author_data_str=`date -R -d @$author_data`      

if [[ $author_data_str =~ $date_match ]];
then
	# remove one day from author_data
	new_data_sec=$(($author_data-$oneday))
	# change to git internal format based on new_data_sec
	new_data="@$new_data_sec +0800"             
	export GIT_AUTHOR_DATE="$new_data"
fi
' --tag-name-filter cat -- --branches --tags

The date will be changed:

AuthorDate: Wed Sep 13 13:39:41 2017 +0800

Solution 26 - Git

TL;DR: Matching dates + re-creating GPG signatures

(Comment/edit if you know a workaround for the stripping to preserve the original signature.)


I'll bump this old thread because a feature of signing commits has been introduced and all of these git filter-branch and likes basically strip the signatures as specified in the docs:

> ... If the tag has a signature attached, the signature will be stripped. It is by definition impossible to preserve signatures. ... (source: --tag-name-filter )

But it'll also break the pretty Verified badge on a GitHub commit (and in other Git hosting places if implemented in the same way), so this will fix that as well. Partially.

Afaik it's not possible to mangle a (GPG) signature through git command in a way that it also contains the date of a commit instead of the date of signing in a simple way and therefore even if the dates for authoring and commit are moved, it'll still be the present date, example:

commit <hash>
gpg: Signature made Sun 25 Jul 2021 00:00:00 PM TZ
gpg:                using TYPE key KEY
gpg: Good signature from "Signer <[email protected]>"
Author:     Author <[email protected]>
AuthorDate: Sat Jan 1 00:00:00 2000 +0000
Commit:     Author <[email protected]>
CommitDate: Sat Jan 1 00:00:00 2000 +0000

So imagine you have a repo you want to sign from a certain commit (I'll go for the root commit; not recommended if somebody else works on the repo). The documentation for git commit says it pulls data from env vars too, if present, thus we have a place to put the input to.

To retrieve the data (can be set with git commit --date=...) we can take a look at git show --format=%ad, so for a raw date string that would be:

git show --format=%ad --no-patch
# Sat Jan 1 00:00:00 2000 +0000

So we have:

  • point of start
  • raw date string for each commit
  • GIT_COMMITTER_DATE to match the dates (author -> committer)

For rebasing let's do this:

git rebase --root <branch-name> --keep-empty --interactive

which will go for the root commit of a branch <branch-name>, preserve any empty commits created with git commit -m "empty" --allow-empty and ask you which commits to modify. There you change the desired commits from pick to edit (for my case that'd be marking all of them as edit), then you'll be dropped into a detached HEAD commit and from here the fun begins.

# or "while :"
while true
do
    GIT_COMMITTER_DATE=$(git show --format=%ad --no-patch) \
        git commit --amend --gpg-sign --no-edit --allow-empty
    git rebase --continue
done

(if you do not have user.signingkey specified, use --gpg-sign=<fingerprint>)

This will go through each of the edit-marked commit, set the committer's date to match the author's date, keep any empty commit, won't touch the overall patch body and will add a signature with a date of when the command was executed.

Once you see fatal: No rebase in progress? press Ctrl-C to stop the loop and check the logs to confirm that the dates match and the signatures are present everywhere with:

git log --pretty=fuller --show-signature

If everything is okay in the logs, simply issue git push --force and you're done. Now you should see that Verified badge for each commit.

Example with a real history tree. GitHub doesn't seem to care about the signature's date (no reference anywhere), but it'll still be present in the git log.

Solution 27 - Git

I have recently needed this and made my own script looking a lot like git-redate

However my scripts does the minimal modifications and takes a lot less time to rewrite (if you need to update) many commits as it does them all at once

change_git_history

Actually this allows to change commit messages too

Explaination:

The scripts concatenates a bunch of bash if-expression looking like so

Here are the ones modifiying the commit date

if [ "$GIT_COMMIT" = "$com_hash" ]; # com is commit
then
    export GIT_AUTHOR_DATE="$com_date";
    export GIT_COMMITTER_DATE="$com_date";
fi;

Here are the ones modifiying the commit message:

if [ true = false ]; # impossible
then
    : # pass
elif [ "$GIT_COMMIT" = "$com_hash" ];
then
    sed 's/.*/$com_msg_esc/g'" # replace content with new content
else
    cat - # returns previous content
fi;

And we push all the update using

git filter-branch -f \
    --env-filter "$UPDATES" \
    --msg-filter "$MESSAGES" \
    -- "$REV"

(doc is here filter-branch man)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDhskjlkakdhView Question on Stackoverflow
Solution 1 - GitPaul PladijsView Answer on Stackoverflow
Solution 2 - GitDustinView Answer on Stackoverflow
Solution 3 - GitLuke EhresmanView Answer on Stackoverflow
Solution 4 - GitgypaetusView Answer on Stackoverflow
Solution 5 - GitbigpotatoView Answer on Stackoverflow
Solution 6 - GitOrtomala LokniView Answer on Stackoverflow
Solution 7 - GitHarald NordgrenView Answer on Stackoverflow
Solution 8 - GitMatt MontagView Answer on Stackoverflow
Solution 9 - GitVonCView Answer on Stackoverflow
Solution 10 - GitPere Joan MartorellView Answer on Stackoverflow
Solution 11 - GitKareem ElbahrawyView Answer on Stackoverflow
Solution 12 - GitJan HView Answer on Stackoverflow
Solution 13 - GitSérgioView Answer on Stackoverflow
Solution 14 - GiteoldView Answer on Stackoverflow
Solution 15 - GittheospView Answer on Stackoverflow
Solution 16 - GitThomas GotwigView Answer on Stackoverflow
Solution 17 - GitMr_and_Mrs_DView Answer on Stackoverflow
Solution 18 - GitAlex CumaravView Answer on Stackoverflow
Solution 19 - GitPeterView Answer on Stackoverflow
Solution 20 - GitevolvedView Answer on Stackoverflow
Solution 21 - GitK.NovichikhinView Answer on Stackoverflow
Solution 22 - GitgfdevelopView Answer on Stackoverflow
Solution 23 - GitJean-Alexis AufauvreView Answer on Stackoverflow
Solution 24 - GitJensView Answer on Stackoverflow
Solution 25 - Gitdetective0922View Answer on Stackoverflow
Solution 26 - GitPeter BadidaView Answer on Stackoverflow
Solution 27 - GitXiaojibaView Answer on Stackoverflow