Changing commit author and dates
A commit has an author and a committer, each with its own date. Fix the last with --amend --author or --reset-author; set dates via GIT_AUTHOR_DATE or --date; rewrite many with rebase --exec or git filter-repo. A .mailmap fixes displayed names without rewriting history.
You forgot to set user.email before a week of work, and now every commit is attributed to you@old-laptop.local. Or a commit went out under a personal address that should have been your work one. Git records who wrote each commit and when — and unlike the file contents, that identity feels untouchable. It is not. Git gives you precise tools to fix authorship on one commit, on a range, or across an entire repository’s history.
By the end of this lesson you will be able to change a commit’s author and dates — for the last commit, for many commits, and for an entire repo — and know exactly which of those operations rewrite history and which only change how it is displayed.
After this lesson you can distinguish a commit’s author from its committer, change the author and dates of the last commit, reset authorship across a range with rebase --exec, bulk-rewrite all history with git filter-repo --mail-map, and use a .mailmap to correct displayed names without rewriting history.
Every commit carries two identities: the author and the committer, each with its own date. The author is who originally wrote the change; the committer is who last applied it. Normally they are the same person, but they diverge when someone applies a patch you wrote, or when a rebase replays your commits (you stay author, the rebaser becomes committer). See both:
git show --format=fuller HEAD
# Author: Jane Dev <jane@old.local> AuthorDate: ...
# Commit: Jane Dev <jane@work.com> CommitDate: ...This distinction matters because most commands change only the author unless you also act on the committer — and git log shows the author by default, so author is usually what you actually want to fix.
Fix the last commit’s author with --amend --author, or adopt your current identity with --reset-author. Two everyday fixes for the most recent commit:
# Set a specific author explicitly:
git commit --amend --author="New Name <new@email.com>" --no-edit
# Or stamp it with whatever your current git config identity is:
git commit --amend --reset-author --no-edit--author= overrides just the author field; --reset-author sets both author and committer to your current user.name / user.email (and resets the author date to now). --no-edit keeps the existing message. Both rewrite the last commit into a new SHA, exactly like any other amend.
Set commit dates with the GIT_AUTHOR_DATE / GIT_COMMITTER_DATE environment variables, or --date for the author date alone. Dates are just metadata fields, and you can set them explicitly:
# --date affects only the AUTHOR date:
git commit --amend --date="2026-05-01T09:00:00" --no-edit
# Set BOTH author and committer dates by exporting env vars:
GIT_AUTHOR_DATE="2026-05-01T09:00:00" \
GIT_COMMITTER_DATE="2026-05-01T09:00:00" \
git commit --amend --no-editThe trap: --date moves only the author date, leaving the committer date untouched, so the two can silently disagree. When you need both aligned, set both env vars. Git accepts ISO-8601, RFC 2822, and relative forms like "2 days ago".
Change author across MANY commits with an interactive rebase or a rebase --exec range. For several commits, two approaches. Mark each target edit in an interactive rebase and amend at every stop:
git rebase -i <base> # mark the commits to fix as 'edit'
# at each stop:
git commit --amend --author="New Name <new@email.com>" --no-edit
git rebase --continueOr run a command automatically across a whole range — here, resetting every commit’s author to your current identity:
git rebase -r <base> --exec 'git commit --amend --reset-author --no-edit'--exec runs the given command after replaying each commit in the range, so you fix dozens of commits without stopping at each one.
For a wrong email on the entire history, use git filter-repo — and prefer a .mailmap when you only need correct display. To rewrite authorship across all commits (e.g. a leaked or wrong email on every one), the modern tool is git filter-repo:
# mailmap.txt maps old identities to new ones, then rewrites every commit:
git filter-repo --mail-map mailmap.txtgit filter-branch did this historically but is deprecated — it is slow and full of footguns; filter-repo is the officially recommended replacement. But if you only need names/emails to appear correct in git log and git shortlog without touching history at all, add a .mailmap file at the repo root:
Correct Name <correct@email.com> <old@wrong.com>A .mailmap remaps identities at display time only — no SHAs change, no force-push, no coordination. Reach for it first whenever display correctness is all you actually need.
▸Common mistake
Every technique here except .mailmap rewrites commits, producing new SHAs. That means a force-push and the full golden-rule problem: anyone who pulled the old history now diverges. Rewriting authorship across a shared main is a coordinated, announced operation — never a casual one. If your goal is purely cosmetic (“the contributor list should show my real name”), the .mailmap gets you there with zero history rewriting and zero risk to collaborators.
A whole feature branch committed under the wrong email.
You did a week of work before noticing git config user.email still pointed at a personal address. The branch has 12 commits, none pushed, all authored by me@personal.com; they should be me@company.com. Since nothing is shared, rewriting is safe.
git config user.email "me@company.com" # fix the config first
git rebase -r origin/main \
--exec 'git commit --amend --reset-author --no-edit'
git show --format=fuller HEAD # verify Author + Commit now match--reset-author stamps every commit in the range with your now-correct identity, and --exec applies it across all 12 without manual stops. Each commit gets a new SHA, which is fine because the branch was never pushed. Had these commits already been on a shared branch, the right tool would instead be a .mailmap (to fix the displayed name without rewriting), or a carefully coordinated git filter-repo --mail-map plus an announced force-push.
▸Why this works
Why does a separate committer identity exist at all? Because git separates who created a change from who placed it into this history. When a maintainer applies a contributor’s patch, fairness says the contributor stays the author while the maintainer is recorded as committer — preserving credit and an audit trail of who actually landed the code. Rebases exploit the same split: replaying your commits keeps you as author but makes the person rebasing the committer, which is why committer dates often look newer than author dates.
A commit has an author and a committer, each with its own date. Fix the last commit with git commit --amend --author="…" or --reset-author (which adopts your current config identity); set dates with --date (author only) or the GIT_AUTHOR_DATE / GIT_COMMITTER_DATE env vars (both). For many commits, mark them edit in an interactive rebase or run git rebase -r <base> --exec 'git commit --amend --reset-author --no-edit'. For an entire history, use git filter-repo --mail-map (filter-branch is deprecated). Crucially, every method except a .mailmap rewrites SHAs and demands a coordinated force-push — so when you only need correct display, the .mailmap is the safe, history-preserving choice.
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.