What does git commit --amend --no-edit do, and why does the commit SHA change?
answer
- immutability, not editing
- the branch ref moves
- identity is a hash of the content
- committer timestamp is part of the hash
- old commit survives in the reflog
basics
~20 sgit commit --amend replaces the tip commit with a brand-new commit built from the current index, and --no-edit reuses the old message. A commit's name is a hash of its whole content, including the committer timestamp, so the replacement gets a new SHA.
solid answer
~40 s`git commit --amend` does not modify the existing commit — commit objects are immutable. It builds a **new** commit from whatever is currently staged, gives it the same parent(s) as the old tip, and moves the current branch to point at it. `--no-edit` means "keep the previous message, do not open an editor". The SHA changes because a commit's identity is the hash of its serialized content: tree, parent list, author, committer and message. Even with an identical tree and message the committer timestamp is refreshed, so the hash differs. The original commit is not destroyed — it becomes unreferenced but stays reachable through the reflog as `HEAD@{1}` until it expires and is garbage collected. Amend touches only HEAD; it never rewrites older commits.
code
bash · 3 linesgit add forgotten-file.txt
git commit --amend --no-edit
git reflog -2go deeper
Recall that amend replaces the last commit and produces a new SHA, and that --no-edit keeps the existing message. Be able to demo the forgot-a-file fix: git add, then git commit --amend --no-edit.
Explain the mechanics: the index becomes a new tree, a new commit object reuses the old parents, and the branch ref moves. Say which fields feed the hash, including the committer timestamp.
Show the operational consequence: the old object survives only in your local reflog, so amend is safe for unpublished work and a coordination problem once the commit has been shared.
Frame the tradeoff of a rewrite-friendly local workflow against a strictly append-only shared history, and where your team draws the line between the two.
## Amend does not edit anything It is natural to read `git commit --amend` as "go back and change my last commit". Git cannot do that. Every object in Git's database is content-addressed: the object's name *is* a hash of its bytes. Change one byte and you have a different object with a different name. Nothing in the object store is mutated in place. What amend actually does: 1. Writes the current index (staging area) out as a tree object. 2. Creates a **new** commit object whose parent list is copied from the commit currently at HEAD — not HEAD itself. If HEAD was a merge commit with two parents, the amended commit keeps both. 3. Uses the old message (with `--no-edit`) or the message you type. 4. Moves the current branch ref to the new commit, and writes a reflog entry. The old commit object is untouched and still in the object database. It is simply no longer pointed at by the branch. ## Why the SHA is different A commit object is a small text blob that Git hashes. It contains the tree id, zero or more `parent` lines, an `author` line with name, email and timestamp, a `committer` line with name, email and timestamp, and the message. The hash of that text is the commit id. So a new SHA appears whenever any of those change. Amending with a different tree changes the tree line; amending with a different message changes the message; and even when both are byte-identical, the **committer timestamp** is set to the moment of the amend. That alone guarantees a fresh id. This is why `git commit --amend --no-edit` with nothing staged still succeeds and still produces a different commit: it is a legitimate way to "re-date" a commit, and a good demonstration that identity is content, not a mutable row in a table. ## Typical uses - You forgot a file: `git add forgotten.txt` then `git commit --amend --no-edit`. - The message has a typo: `git commit --amend` with nothing staged, fix the text, save. - You want to fold a one-line correction into the commit you just made instead of adding a "fix typo" commit to the history. ## The old commit is recoverable Because the previous commit is still an object, the reflog for the branch records where the ref pointed before the amend. `git reflog` shows entries such as `HEAD@{1}` labelled `commit (amend)`. Resetting the branch back to that entry restores the pre-amend state exactly. The object survives until reflog entries expire (90 days by default for reachable-from-reflog entries) and garbage collection prunes it. One important limit on that safety: the reflog is **local**. It protects you on your machine; it does nothing for a teammate who already fetched the old commit. ## What amend cannot do - It only replaces HEAD. To change a commit further back you need an interactive rebase, or a `fixup` commit that a rebase later squashes into the target. - It does not rewrite descendants, because the branch tip has none. If another branch or tag points at the pre-amend commit, that ref still points at the old object; the two histories now diverge from their shared parent. - It does not merge your staged changes into the old tree in a clever way. The new commit's tree is simply whatever the index holds — which is why `git status` before amending matters. ## Interview framing A good answer names three things: amend creates a new object rather than editing one, the branch ref is moved to it, and the old commit lives on in the reflog. Adding "and that is exactly why amending something you already pushed is a different problem" shows you understand the consequence rather than just the command.
- If nothing is staged, does git commit --amend --no-edit still create a commit?Yes. Amend is not subject to the usual "nothing to commit" check, because it is replacing an existing commit rather than adding one. You get a new commit with the same tree and message but a refreshed committer timestamp, so a different SHA. It is a quick way to demonstrate that a commit's identity is its content, not a mutable record.
- How do you get the pre-amend commit back?Read `git reflog`, find the entry above the amend (usually `HEAD@{1}`, labelled `commit (amend)`), and point the branch back at it with a reset. The old commit object was never deleted — only unreferenced — so it remains available until reflog entries expire and garbage collection runs. The reflog is local only, so this rescue works on your clone, not a teammate's.
- Does amending a merge commit lose its second parent?No. Amend copies the parent list from the commit being replaced, so a merge commit stays a merge commit with all of its parents. Only the tree, message and committer metadata come from the amend.
saying these in an interview costs you the question
- Says amend edits the existing commit in place
- Thinks the SHA stays the same if the message is unchanged
- Believes the original commit is deleted immediately
- Claims amend can rewrite any commit, not just HEAD
- Thinks --no-edit means no changes are committed