gitfiltergit-filter-branchgit-filter-repo

How can one change the timestamp of an old commit in Git (Git filter-repo)?


In this question someone answers with a git filter-branch command in this post. But, I would like to know what the equivalent is in git filter-repo as git filter-branch is the old and slow command and git filter-repo is supposed to be the replacement. Does anyone know what the git filter-repo equivalent is of 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

  • The general syntax for a commit callback using git-filter-repo is:

    git filter-repo --commit-callback '
      if commit.original_id == b"dac06eb4530af044b1057528f6d6202c8f25df74":
        # Set the author date to Dec 31, 1999 23:59:59
        commit.author_date =  b"946684799 +0000"
        # Set the committer date to Jan 01, 2000 00:00:00
        commit.committer_date = b"946684800 +0000"
        commit.author_name = b"Joe Schmoe"
        commit.author_email = b"joe.schmoe@ttt.com"
        commit.committer_name = b"Jane Schmoe"
        commit.committer_email = b"jane.schmoe@ttt.com"
        commit.message = b"Fix typo"
      '
    

    Note that with filter-repo you need to use Unix timestamps, which can be converted here.

    When using filter-repo, if you don't have a fresh clone (which is highly recommended), you'll need to use the --force option.

    Here's the above example in action which changes both authors, both emails, both dates, and the commit message of a specific commit, with the before and after:

    Example:

    $ git log -n1 --pretty=fuller
    commit dac06eb4530af044b1057528f6d6202c8f25df74 (HEAD)
    Author:     John Doe <john.doe@ttt.com>
    AuthorDate: Sun Aug 13 11:13:00 2023 -0500
    Commit:     Jane Doe <jane.doe@ttt.com>
    CommitDate: Sun Aug 13 11:13:00 2023 -0500
    
        fixed typo
    
    $ git filter-repo --commit-callback '
    >   if commit.original_id == b"dac06eb4530af044b1057528f6d6202c8f25df74":
    >     # Set the author date to Dec 31, 1999 23:59:59
    >     commit.author_date =  b"946684799 +0000"
    >     # Set the committer date to Jan 01, 2000 00:00:00
    >     commit.committer_date = b"946684800 +0000"
    >     commit.author_name = b"Joe Schmoe"
    >     commit.author_email = b"joe.schmoe@ttt.com"
    >     commit.committer_name = b"Jane Schmoe"
    >     commit.committer_email = b"jane.schmoe@ttt.com"
    >     commit.message = b"Fix typo"
    >   ' --force
    Parsed 21 commitsHEAD is now at 1f579bb Fix typo
    Enumerating objects: 53, done.
    Counting objects: 100% (53/53), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (30/30), done.
    Writing objects: 100% (53/53), done.
    Total 53 (delta 10), reused 51 (delta 9), pack-reused 0
    
    New history written in 0.08 seconds; now repacking/cleaning...
    Repacking your repo and cleaning out old unneeded objects
    Completely finished after 0.28 seconds.
    
    $ git log -n1 --pretty=fuller
    commit 1f579bbf21a7537e177e367c0c96f0b867b5ad34 (HEAD)
    Author:     Joe Schmoe <joe.schmoe@ttt.com>
    AuthorDate: Fri Dec 31 23:59:59 1999 +0000
    Commit:     Jane Schmoe <jane.schmoe@ttt.com>
    CommitDate: Sat Jan 1 00:00:00 2000 +0000
    
        Fix typo
    

    Another way to do it without using a callback

    Here's a simple general algorithm for making changes to commits that don't affect the state of the file system. Examples of non-state changes are commit authors, dates, or the commit message.

    1. Checkout the commit you wish to change.
    2. Amend it the way you wish to change it. (In your case, perhaps this answer.)
    3. Replace it: git replace <old-commit-id> <new-commit-id>
    4. Make all replacements permanent: git filter-repo --replace-refs update-or-add