skip to content

questions

18

What does git commit --amend --no-edit do, and why does the commit SHA change?

level: juniorimportance: must knowfreq 80%

answer

  1. immutability, not editing
  2. the branch ref moves
  3. identity is a hash of the content
  4. committer timestamp is part of the hash
  5. old commit survives in the reflog

basics

~20 s

git 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 lines
bash
git add forgotten-file.txt
git commit --amend --no-edit
git reflog -2

go deeper

for a junior

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.

for a middle

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.

for a senior

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.

for a principal

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

context

open as a page

How should a Git commit message be structured, and what is the 50/72 convention?

level: juniorimportance: must knowfreq 66%

basics

~20 s

A Git commit message is a short subject line, a blank line, then an optional body. The convention keeps the subject under about 50 characters and wraps body lines at 72. The blank line is the part Git itself depends on.

open as a page

In Git, how do git add -A, git add -u, and git add . differ?

level: juniorimportance: must knowfreq 68%

basics

~20 s

In modern Git, add -A stages new, modified and deleted paths across the whole working tree; add -u stages modifications and deletions for already-tracked paths only, never new files; add . does what -A does but limited to the current directory and below.

open as a page

In Git, what are the working tree, the index, and HEAD?

level: juniorimportance: must knowfreq 82%

basics

~20 s

Git juggles three trees: the working tree (your files on disk), the index or staging area (the proposed next commit), and HEAD (the commit you are on). git add copies working tree into index; git commit turns the index into a commit.

open as a page

What does git add -p do, and why would you stage only part of a file?

level: middleimportance: must knowfreq 62%

basics

~20 s

git add -p walks the diff between your working tree and the index hunk by hunk and asks whether to stage each one. Only the accepted hunks enter the index, so one messy file can become several focused commits.

open as a page

In Git, which changes does git commit -a stage, and what are its pitfalls?

level: middleimportance: should knowfreq 52%

basics

~20 s

git commit -a automatically stages modifications and deletions of files Git already tracks, then commits. It ignores untracked files, sweeps in every unrelated edit in the working tree, and overrides any partial staging you set up for those files.

open as a page

How do git commit --fixup and git rebase -i --autosquash work together?

level: middleimportance: should knowfreq 48%

basics

~20 s

git commit --fixup=<commit> records a normal commit whose subject is "fixup! " plus the target's subject. A later git rebase -i --autosquash reads those markers, moves each fixup commit next to its target, and marks it to be folded in.

open as a page

In a Conventional Commits message, what do the type, scope, and trailing ! mean?

level: middleimportance: should knowfreq 50%

basics

~20 s

Conventional Commits shapes the subject as type(scope)!: description. The type classifies the change, the optional scope names the affected area, and a ! before the colon marks a breaking change. It makes commit history machine-readable for versioning and changelogs.

open as a page

What are Git commit trailers, and how do Signed-off-by and Co-authored-by get added?

level: middleimportance: should knowfreq 38%

basics

~20 s

Trailers are Token: value lines in the last paragraph of a commit message, giving it machine-readable metadata. git commit -s adds a Signed-off-by line from your committer identity, and git interpret-trailers or git commit --trailer adds arbitrary ones such as Co-authored-by.

open as a page

In git add -p, what do the y, n, s, e and q keys do?

level: middleimportance: should knowfreq 40%

basics

~20 s

At the git add -p prompt, y stages the shown hunk, n skips it, s splits it into smaller hunks when context lines allow, e opens it in your editor for line-level control, and q quits leaving earlier answers already staged.

open as a page

In Git, what is the difference between git restore --staged and git restore -p?

level: middleimportance: should knowfreq 36%

basics

~20 s

git restore --staged changes the index, unstaging a path while leaving your working-tree edits intact. git restore -p asks hunk by hunk and, without --staged, overwrites working-tree hunks from the index — which permanently discards those edits.

open as a page

In Git, what does git rm --cached do, and when do you need it?

level: middleimportance: should knowfreq 55%

basics

~20 s

git rm --cached removes a path from the index but leaves the file on disk. The next commit records the deletion, so the file becomes untracked locally while everyone who pulls that commit loses their copy on disk.

open as a page

How do you read the two status columns in git status --short output?

level: middleimportance: should knowfreq 52%

basics

~20 s

In git status --short each path gets two columns: the left column is index versus HEAD (staged), the right is working tree versus index (unstaged). A space means no change on that side, and ?? marks an untracked file.

open as a page

In Git, why is amending an already-pushed commit riskier than amending a local one?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Amending replaces a commit with a new object. If the original was pushed, it still exists on the remote and in every clone that fetched it, so your branch and the remote now diverge, a normal push is rejected, and teammates can reintroduce the old commit.

open as a page

You fixed a bug and reformatted the same file — how do you land two separate commits?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Stage only the fix hunks with git add -p, review git diff --cached, commit the fix, then commit the formatting separately. Where fix and reformat share a line, use the e key to hand-edit the hunk.

open as a page

When you run git commit --amend, what happens to the author and committer fields?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

Amend preserves the original author name, email and author date, but sets the committer to your current identity with the timestamp of the amend. That refreshed committer line is why the SHA changes even when the tree and message are unchanged.

open as a page

What does Git's commit.template setting do, and how far can it enforce a convention?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

commit.template names a file whose contents pre-fill the editor when you run git commit. It is a prompt, not a check: the author can delete every line, -m skips it entirely, and the setting lives in local config that a clone does not carry.

open as a page

What is the difference between git update-index --assume-unchanged and --skip-worktree?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Both set a bit on an index entry that hides working-tree edits to a tracked file. --assume-unchanged is a performance promise Git may discard and overwrite; --skip-worktree declares the index version authoritative and is respected and preserved far more carefully.

open as a page