Cosmophile's Blog: Home

Git notes

Table of contents

Sign commits

SSH signing is more practical than GPG signing. Below are global configurations:

git config --global gpg.format ssh
git config --global gpg.ssh.allowedsignersfile=~/.ssh/allowed_signers

echo "$(git config user.email) $(cat ~/.ssh/id.pub)" >> ~/.ssh/allowed_signers

Set signing key and enable siging on a repository:

git config user.signingkey ~/.ssh/id.pub
git config commit.gpgsign true

Verify signatures:

git log --show-signature
git verify-commit HEAD

Rewrite all commits in history to add a new author email for that author

This functionality was necessary when transitioning to a different Git provider with a new username and email address. To retain the old username and email address, we opted to include Co-Authored-By: statements in commit messages.

Below, this is implemented with filter-repo command. Commit callback accepts Python script. --refs main ensures changes are made only on the main branch, this can be omitted to process all branches. --force might be necessary if the repository is not clean.

git filter-repo --refs main --commit-callback '
target_email = b"user.old@example-old.com"
trailer = b"\nCo-Authored-By: User New <user.new@example-new.com>\n"

if commit.author_email == target_email:
    if b"Co-Authored-By:" not in commit.message:
        commit.message += trailer
'

It is necessary to have 'force push' permissions at the origin to push the new tree with git push --force origin main.

If the output contains multiple extra newlines, the following updates them:

git filter-repo --refs main --commit-callback '
commit.message = commit.message.replace(b"\n\n", b"\n")
'