skip to content

When commit history is rewritten, what happens to the original commits?

level: seniorimportance: should knowfreq 57%

answer

  1. Nothing is edited in place
  2. New commits, moved pointer
  3. The old ones linger unreferenced
  4. The expensive part is other people

basics

~20 s

Nothing edits them. A rewrite builds new commits carrying the intended content and moves the line's pointer to them; the originals stay in the repository, unreferenced, until a cleanup pass removes them. Anyone holding the old identifiers now has a diverged copy.

solid answer

~50 s

Commits cannot be modified, because a commit's identifier is derived from its own contents - change anything and you have a different commit. So every operation described as **rewriting history** does the same thing underneath: it builds *new* commits carrying the content you wanted, moves the line's pointer from the old newest commit to the new one, and leaves the old commits stored but referenced by nothing until a maintenance pass eventually removes them. The technical step is instant and cheap. What varies enormously is the social cost: every copy that already holds the old commits still holds them, nothing propagates the change, and anyone who built work on top of the old commits is now sitting on a parent chain the shared line no longer carries. Rewrite freely while the work is yours alone; treat rewriting a shared line as a coordination event.

code

pseudocode · 5 lines
pseudocode
before:  a1c9 -> b7f2 -> c3e8      # the line points at c3e8
after:   a1c9 -> d40b              # the line points at d40b

# d40b holds c3e8's content with a corrected message
# b7f2 and c3e8 are still stored, now referenced by nothing

go deeper

for a junior

Recall that commits cannot be edited: any change produces a new commit with a new identifier. Know the rule of thumb - tidy your own unshared work freely, and treat anything already shared as something you do not quietly reshape.

for a middle

Explain what a rewrite does mechanically: new commits are built, the line's pointer moves, and the old commits remain stored but unreferenced until cleanup. Be able to say why correcting only a message still changes the identifier.

for a senior

Demonstrate judgement about blast radius. An interviewer expects you to reason about who already holds the old commits, what happens to work built on top of them, and how you would sequence and announce a rewrite that is genuinely necessary.

for a principal

Own the policy. Be ready to argue when a shared line may be rewritten at all, what the team's response is when a credential reaches history, and how you weigh a readable history against the coordination cost the rule imposes on everyone.

## Why nothing can be edited in place A commit's identifier is derived from its own contents - the file snapshot, the parent link, the authorship metadata, the message. That makes editing a stored commit impossible in a strict sense: change any of it and what you have is a different commit with a different name. Immutability here is not a policy someone chose to enforce; it falls out of how commits are named. So every operation described as "rewriting history" - correcting a message, combining several commits into one, splitting one into two, dropping a commit, removing a file that should never have been recorded - does the same thing underneath. ## What a rewrite actually does 1. **Read the content you want to end up with**, taken from the commits that already exist. 2. **Build new commits** carrying that content. Each gets a new identifier, because the content, the parent link, or the message differs from the original. 3. **Move the line's pointer** from the old newest commit to the new one. A line of development is a movable pointer, and the rewrite repoints it. 4. **Leave the old commits exactly where they are.** They are still stored. Nothing references them any more, which is a very different thing from being deleted. 5. **Wait for cleanup.** Unreferenced objects are removed by a maintenance pass after a grace period rather than at the moment of the rewrite. That is why work that felt lost immediately after a rewrite has usually not gone anywhere yet - though the window is a grace period, not a guarantee. The sentence worth having ready in an interview: *a rewrite adds commits and moves a pointer; it never modifies a commit.* ## The cost is social, not technical Building the new commits is cheap and essentially instant. What varies by orders of magnitude is who else is already holding the old identifiers. | Who holds the old commits | What the rewrite costs | |---|---| | Only your own machine | Nothing. Reshape as much as you like. | | Shared, but nobody has taken them yet | Little - the next person to take the line simply gets the new shape | | Shared, and teammates already have them | Every teammate must deliberately repoint their copy; anyone who takes the line naively ends up holding both shapes of the same work | | Teammates have built new work on top | Expensive - their commits' parent chains reference commits the shared line no longer carries | | A deploy, ticket or incident record cites an old identifier | The reference resolves only for as long as the old commit survives cleanup | This is the whole reason for the rule of thumb candidates recite: rewrite freely while the work is yours alone, and treat rewriting a shared line as a coordination event rather than a tidy-up. ## A rewrite that goes wrong A bike-share operations team of 11, 6 of them hired within the last quarter, keeps a shared integration line. The median wait for a review is 2 days, so at any moment several people have already taken the line and are working on top of it. An engineer decides that 4 messy commits on that line should have been 1, rewrites them, and repoints the line. Nothing breaks for them. For everybody else, the next time they take the line, their copy now contains both the 4 original commits - which they already had - and the 1 replacement describing the same work again. The newly-hired half of the team, who have never seen this, untangle the result by hand and in several different ways, and one of them silently reintroduces a change the rewrite was meant to remove. The technical operation took under a second; the cleanup took the rest of the day. The failure was not the rewrite. It was repointing something other people were standing on without telling them. ## What good practice looks like - **Rewrite before you share, not after.** Tidying a series while it is still local is free and makes the shared history better for everyone who reads it later. - **When a shared rewrite is genuinely necessary** - a credential recorded by accident, content that must be removed - announce it, agree a moment when nobody is mid-change, say exactly which line and which commits are affected, and tell every holder what to do with their copy. - **Never assume other copies update themselves.** Nothing propagates a rewrite. Each holder of the old commits acts, or keeps the old shape indefinitely. - **Remember that a rewrite does not erase.** A secret committed by accident and then rewritten out is still stored locally until cleanup, still present in every copy anyone already took, and possibly still present in any system that mirrored or built from that line. Rewriting is not a substitute for rotating the secret - rotate it. - **Expect external references to dangle.** Tickets, deploy records and chat links citing an old identifier stop resolving once cleanup runs. ## What the interviewer is checking A candidate who says "you should never rewrite history" has memorised a slogan. A candidate who says "a rewrite creates new commits and moves a pointer, so the question is always who else is holding the old ones" has the model, and can then reason about a case the slogan does not cover - which is what the scenario is really testing.

  • A teammate says their work vanished right after a rewrite. Why is it usually still present?
    The rewrite created new commits and moved a pointer; it neither modified nor deleted the old commits. They remain in that repository as unreferenced objects until a maintenance pass removes them after a grace period, so the pre-rewrite state normally still exists on that machine for some time. The window is a grace period, not a guarantee.
  • A secret was committed and then rewritten out of the shared line. Is it safe now?
    No - rotate it. The old commit still exists locally until cleanup, it exists in every copy anyone already took, and it may exist in anything that mirrored or built from that line. Rewriting changes which commits a line points at; it does not reach other people's copies or undo the exposure.
  • How would you make a genuinely necessary rewrite of a shared line safe for a team?
    Announce it before it happens, pick a moment when nobody is mid-change, state exactly which line and which commits are affected, and tell every holder what to do with their copy. Confirm afterwards that each person has repointed. The technical step takes a second; the coordination is the actual work.

Rewriting history is like reprinting a document rather than erasing a line: the new copy replaces the old one on your desk, but every colleague who already took a copy still has the old text.

saying these in an interview costs you the question

  • Says rewriting edits the existing commit in place
  • Believes the old commits are destroyed immediately
  • Expects teammates' copies to update themselves
  • Thinks rewriting a secret out makes it safe
  • Repoints a shared line without announcing it