Normally, when you rebase another author's commit with git, git adds a Commit:
header with your name and email address. I have a situation where I don't want this to happen. I want the rebased commit to end up with the same SHA1 as it would have if the original author had done the equivalent rebase him/herself. Is this possible?

- 29,546
- 11
- 78
- 79
-
3Even if you do this, the new commit will *not* have the same SHA1 as the original commit. The original commit contains: the "tree" containing all the files in your project, as they were at the time of the commit, the author name/email/date, the committer name/email/date, and a reference to the parent commit. When you rebase, you end up with a totally new commit, that just happens to have the same author information and a similar tree, but even if all that were exactly the same, it would have a new parent. So the SHA1 would change. – Tyler Apr 02 '11 at 05:50
-
Related (at least closely enough that I found this current question on Google while looking for the linked one): https://stackoverflow.com/q/4981126/5419599 – Wildcard Sep 22 '17 at 08:40
3 Answers
All git commits have a committer field internally; you can see this by typing git cat-file commit HEAD
immediately after committing something. As such you cannot erase it; you can only make it equal to the author field.
That said, you might be seeing git porcelain showing the commit field because the datestamp has changed. It's not possible to predict what someone else would get for the commit datestamp if they were rebasing, obviously, but you can alter it to be equal to the original commit timestamp, at least.
git filter-branch --commit-filter 'export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; git commit-tree "$@"' -- basecommit..HEAD
This will alter commits after basecommit, in the history of HEAD (including HEAD, not including basecommit), making their committer field identical to the author field in all respects. If the original author agrees to do the same thing, then you can get a consistent SHA1.

- 224,562
- 31
- 268
- 324
-
John: This is your answer. Go have a look at any commit you've made - you'll see committer information (name, email, date) there, identical to the author information. Not all methods of viewing commits show the committer date by default - try `gitk`, or `git log --pretty=full`. (or `fuller`, or even `raw`) – Cascabel Apr 02 '11 at 05:08
-
This worked flawlessly after a big rebase. I would feel better if it were writter with git filter-repo, though. Any experts out there? – Nei Neto Feb 26 '21 at 16:50
Try setting the environment variable GIT_COMMITTER_NAME
and GIT_COMMITTER_EMAIL
when rebasing (maybe also GIT_COMMITTER_DATE
, too). (This will effect all commits created now, though.)

- 73,284
- 20
- 146
- 210
-
That doesn't work. It makes the value of the `Commit:` header identical to the `Author:` header. I want it removed entirely. – John Apr 02 '11 at 01:45
-
3Make sure to only set those variables for that command to avoid affecting other commits: `GIT_COMMITER_NAME=... ... git rebase ...`. Otherwise just be sure to `unset` them after you're done! – Cascabel Apr 02 '11 at 05:16
-
@John: I think the `Commit:` header would be there always. More exactly, the raw commit has always an `author ...` and a `committer ...` header entry, even if those have the same value. Only some porcelain tools sometimes select to show only one or both. Use `git show-object ...` or `git cat-file -p ...` to see what is in the commit object. – Paŭlo Ebermann Apr 02 '11 at 15:38
-
-
3You're right -- once I set all of GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE to the appropriate values, the resulting SHA1 comes out the same as if the original author had done the same rebase on that date. – John Apr 05 '11 at 21:18
You can preserve the original committer information when rebasing by using Interactive Rebase with instructionFormat
.
In your config file .gitconfig
, set this:
[rebase]
instructionFormat = %s%nexec GIT_COMMITTER_DATE=\"%cI\" GIT_COMMITTER_NAME=\"%cN\" GIT_COMMITTER_EMAIL=\"%cE\" git commit --amend --no-edit%n
[alias]
rb = rebase --interactive
Explanation:
rebase.instructionFormat
- a configuration for interactive rebase to give a custom instruction in the to-do file.%s
- the subject of the commit message (the default value ofinstructionFormat
).%n
- a line break; can double-up (%n%n
) to add a blank line for readability.exec
- instructsgit rebase
to execute the rest of the line as a shell command.- It can be shortened to
x
(useful if you're usingabbreviateCommands = true
).
- It can be shortened to
GIT_COMMITTER_DATE=\"%cI\"
- get the commit date in strict ISO 8601 format.GIT_COMMITTER_NAME=\"%cN\"
- get the name of the committer.GIT_COMMITTER_EMAIL=\"%cE\"
- get the email address of the committer.- Above two respect
.mailmap
file if any found. To disregard the file, use%cn
and%ce
instead.
- Above two respect
git commit --amend --no-edit
- amend the commit with the above three environment variables, without opening an editor for the commit message.%n
- a line break (to add a blank line for readability in the to-do file; can repeat for more blank lines).alias.rb
- for convenience, an alias is defined to quickly call interactive rebase withgit rb [new base]
To use it, be sure you're checked out on the branch you wish to rebase, then run the command git rb [new base]
where [new base]
is the branch or commit-ish on top of which you want to rebase the checked-out branch. (Example: git rb main
)
An editor will open with the interactive rebase to-do. Simply close the editor (unless you know what you're doing and want to edit it). If you're curious, you can see the output of the above config in the file.
Note 1: This is only possible via Interactive Rebase, since the regular rebase doesn't support instructionFormat
. You have to bear with the editor opening for no good reason, and just close it (if you have no plans to edit it).
Note 2: Even if you preserve all of the committer information, you may still not get the same SHA1 because the SHA1 is dependent on the parent commit. When the parent changes, the SHA1 changes too. However, if the parent didn't change, you will always get the same SHA1. So this is a deterministic operation.
Note 3: For Windows, you may need to use Git Bash, and you may need to change the quote \"
to """
. If you didn't need to change it, make a comment and let me know. If you use WSL2, you don't need to change it. Also, this won't work in Command Prompt and PowerShell since DOS doesn't support inline environment variables.)

- 8,999
- 5
- 68
- 93