160 lines
4.6 KiB
Markdown
160 lines
4.6 KiB
Markdown
+++
|
||
date = '2025-10-20T00:01:00+02:00'
|
||
draft = false
|
||
title = "Rewriting Git History: Changing Commit Authors"
|
||
+++
|
||
|
||
Recently, I took a bit of a turn — new direction, new mindset, new goals. I dropped some services, cut a few habits, and doubled down on others. It’s not the first time — and definitely won’t be the last. Every time, same story: new alias, maybe a new URL, and off we go again.
|
||
|
||
This time, though, I wanted to change the authors of my Git commits — just to avoid looking like I’ve got multiple personalities committing to the same repo. You know, before someone starts suspecting schizophrenia.
|
||
|
||
Case 1: Replace all authors
|
||
|
||
If you want to replace every single author with one consistent identity:
|
||
|
||
```bash
|
||
git filter-repo --commit-callback '
|
||
commit.author_name = b"Votre Nom"
|
||
commit.author_email = b"email@exemple.com"
|
||
commit.committer_name = b"Votre Nom"
|
||
commit.committer_email = b"email@exemple.com"
|
||
' --force
|
||
```
|
||
|
||
This command walks through every commit and replaces both the author and committer.
|
||
|
||
Important notes:
|
||
• Values must be Python bytes (b"...")
|
||
• The --force flag is required to apply the changes (no confirmation prompt)
|
||
• This operation recreates all commits, so their SHA hashes change
|
||
|
||
Case 2: Replace a specific author
|
||
|
||
If your repo has multiple authors but you only want to fix one of them, add a condition:
|
||
|
||
```bash
|
||
git filter-repo --commit-callback '
|
||
if commit.author_name == b"Ancien Nom":
|
||
commit.author_name = b"Nouveau Nom"
|
||
commit.author_email = b"nouvel@email.com"
|
||
commit.committer_name = b"Nouveau Nom"
|
||
commit.committer_email = b"nouvel@email.com"
|
||
' --force
|
||
```
|
||
|
||
Case 3: Replace only names or only emails
|
||
|
||
You can also apply more granular transformations.
|
||
For example, replace names only:
|
||
|
||
```bash
|
||
git filter-repo --name-callback 'return b"Nouveau Nom"' --force
|
||
```
|
||
|
||
Or replace emails only:
|
||
|
||
```bash
|
||
git filter-repo --email-callback 'return b"nouvel@email.com"' --force
|
||
```
|
||
|
||
Full workflow: a practical example
|
||
|
||
Let’s say your commits are under “Tartanpion old@email.com” and you want to fix that mess.
|
||
|
||
1. Check current authors
|
||
|
||
Before doing anything, list your contributors:
|
||
|
||
```bash
|
||
git log --format='%an <%ae>' | sort | uniq
|
||
```
|
||
|
||
That’ll show all unique authors in the repo.
|
||
|
||
|
||
### 2. Apply the filter
|
||
|
||
```bash
|
||
git filter-repo --commit-callback '
|
||
if commit.author_name == b"Tartanpion":
|
||
commit.author_name = b"DuN0Z"
|
||
commit.author_email = b"dunoz@porzh.me"
|
||
commit.committer_name = b"DuN0Z"
|
||
commit.committer_email = b"dunoz@porzh.me"
|
||
' --force
|
||
```
|
||
|
||
### 3. Verify the result
|
||
|
||
```bash
|
||
git log --format='%an <%ae>' | sort | uniq
|
||
```
|
||
|
||
Authors should now all show the updated identity.
|
||
|
||
### 4. Check repo integrity
|
||
|
||
```bash
|
||
git fsck
|
||
```
|
||
|
||
This ensures the repository is still consistent.
|
||
|
||
### 5. Force push the new history
|
||
|
||
Since you’ve rewritten the history, you’ll need to force push it to the remote:
|
||
|
||
```bash
|
||
git push origin master --force
|
||
```
|
||
|
||
**Warning :** --force overwrites history on the remote.
|
||
Make sure that’s okay for your team — or in my case, it’s all personal stuff, so… who cares.
|
||
|
||
## Common pitfalls
|
||
|
||
Refusing to run without --force:
|
||
Git will refuse to rewrite history unless you explicitly allow it. Use --force consciously.
|
||
|
||
Old references sticking around:
|
||
After filtering, Git keeps old references under .git/refs/original/. You can safely remove them:
|
||
|
||
|
||
```bash
|
||
rm -rf .git/refs/original/
|
||
git reflog expire --expire=now --all
|
||
git gc --prune=now
|
||
```
|
||
|
||
Collaborators affected:
|
||
If others work on this repo, they’ll need to re-clone or rebase their branches.
|
||
Coordinate… or don’t — in my case, nobody else touches these repos. Like this blog, actually — I love throwing digital messages in bottles.
|
||
|
||
## After the force push
|
||
|
||
Once pushed, the remote will now reflect your new commits.
|
||
Old commits will stick around temporarily (until garbage collection), but they’ll fade away soon enough.
|
||
|
||
If someone else cloned the old history:
|
||
|
||
|
||
```bash
|
||
git fetch origin
|
||
git reset --hard origin/master
|
||
```
|
||
|
||
## Conclusion
|
||
|
||
Rewriting Git history with git filter-repo is powerful — and should be used wisely.
|
||
It’s great for fixing author mistakes, cleaning up legacy commits, or prepping a repo before publishing it publicly. Always double-check, and if in doubt, test on a copy first.
|
||
|
||
If you want to avoid this situation in the future, make sure your Git identity is configured properly:
|
||
|
||
```bash
|
||
git config --global user.name "Votre Nom"
|
||
git config --global user.email "email@exemple.com"
|
||
```
|
||
This is especially true if you use multiple machines — it gets messy fast.
|
||
Or better yet, put everything under NixOS and import the same git.nix config everywhere.
|
||
You know what caused my issue? The Mac.
|
||
Classic karma.
|