Change git history while preserving timestamps of GPG signatures

89 views Asked by At

I’m trying to erase sensitive data from a git history of an old local repository before pushing it to Github, while also maintaining/forging the original GPG signature timestamps.

I know it is not recommended to change git history like this, but I really need to erase this sensitive data while maintaining the GPG timestamps (even though I know the hashes will be different).

I used to be able to do this in the following way:

I would run git rebase -i {HEAD} (HEAD would be of the commit previous to the one I want to edit), then select to edit the desired commit, and after that run:

  1. sudo date -f "%s" {UNIX-TIMESTAMP}
  2. GIT_COMMITTER_DATE="$(date)" git commit -—amend --date="$(date)" -S

The first command is to change the machine’s date to that of the commit in the past that I want to edit.
 The second command I used to run after making the needed changes and running git add ., would amend the commit and sign it with the desired date while still maintaining the signature date of all subsequent commits.


This used to work fine, but now when I try to run this, all the commits that come after the commit I want to edit will have a new GPG signature timestamp that is the same as the UNIX-TIMESTAMP I choose to edit the desired commit with, and this will be visible when I push it to Github.

I have also tried GIT_COMMITTER_DATE="$(date)" git commit -—amend --no-edit --date="$(date)" -S but it is resulting in the same issue.

What can I do to maintain the GPG timestamps of subsequent (and unedited) commits after running git rebase —continue? Or is there any other way to do this?

1

There are 1 answers

0
VonC On

(First, backup your repository!)

I do not think Git would natively support preserving GPG timestamps during such operations.

Identify the hash of the commit you want to edit (Commit B). And start an interactive rebase that begins with the parent of the commit you wish to edit.

git rebase -i <commit-hash>^

Mark the commit you intend to edit with edit in the interactive rebase todo list. And amend the commit with your changes.

git commit --amend -S

Continue with the rebase (git rebase --continue).

For each subsequent commit, reset the GIT_COMMITTER_DATE to the original commit date. This can be automated with a script.
You can use a script to automate the resetting of GIT_COMMITTER_DATE. This script would:

  • Extract the original commit date for each commit.
  • Set GIT_COMMITTER_DATE to this original date.
  • Amend each commit without changing its content (git commit --amend --no-edit -S).
#!/bin/bash

# The hash of the first commit to start processing (exclusive)
START_COMMIT="<commit-hash>"

# Checkout to a temporary branch to avoid directly modifying the main branch
git checkout -b temp-branch

# Iterate over each commit from HEAD to START_COMMIT
while [ $(git rev-parse HEAD) != $START_COMMIT ]; do
    # Get the original author date
    AUTHOR_DATE=$(git show -s --format=%aI HEAD)

    # Amend the commit without changing its message/content, but reset the author date
    GIT_COMMITTER_DATE="$AUTHOR_DATE" git commit --amend --no-edit -S --date="$AUTHOR_DATE"

    # Move to the previous commit
    git reset --soft HEAD~1
done

# Finally, rename the temporary branch back to the original branch name if needed
git checkout -b new-branch-name
git branch -D temp-branch

echo "All commits amended with original author dates."

Or, you can also use git filter-branch:

#!/bin/bash

# The range of commits to process, e.g., master..feature-branch
COMMIT_RANGE="<commit-range>"

# Function to extract and set the original author date for each commit
export -f set_original_date
set_original_date() {
    # Extract the original author date
    local AUTHOR_DATE=$(git log -1 --format=%aI $GIT_COMMIT)

    # Set the GIT_COMMITTER_DATE to the original author date
    export GIT_COMMITTER_DATE=$AUTHOR_DATE
}

# Run git filter-branch with the above function
git filter-branch --env-filter 'set_original_date' $COMMIT_RANGE

After completing the rebase and ensuring all dates are correct, you can push the changes to GitHub.