linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Chapters
  • How it works
  • Lessons
  • Knowledge base
  • Interview prep
Cluster

← все кластеры

Rewriting history

amend, interactive rebase, git filter-repo, force-push. When it is safe to rewrite history, how to avoid breaking your teammates' copies, and why filter-branch is no longer used. Senior questions: what to do once the rewrite has already happened and the team is suffering.

5 вопросов · ~30 мин чтения

Questions

На этой странице

  1. 01When is `git commit --amend` safe, and when is it not?
  2. 02How do you rewrite a series of commits in a feature branch before a PR?
  3. 03You accidentally committed `.env` with a secret into a public repo a month ago. How do you clean it out?
  4. 04How do you align with the team before rewriting history on a shared branch?
  5. 05I force-pushed, and now a teammate's `git log` shows my old commits plus my new ones. What happened and how do I fix it?

#git-amend-safe-or-not

juniorчасто

When is `git commit --amend` safe, and when is it not?

Что отвечать

It is safe on a **local commit that has not been pushed yet**. amend creates a new commit with a new SHA (the old one becomes dangling). Physically it is a replace, not an edit. It is dangerous on a pushed commit: after the amend you need a force-push, and if a teammate has already based work on the old SHA, their commits are orphaned. It is also dangerous with `--no-edit` when you do not realize you are changing the author or timestamp: amend rewrites the committer data, the author stays, and that can confuse blame.

Что хотят услышать

A senior should: - explain that amend is a **technically new commit**, not an edit of the existing one. The SHA changes. - name a concrete safe case: "forgot to add a file, typo in the message, not pushed yet" → `git add forgot.txt && git commit --amend --no-edit` - say that after amending a pushed commit you need `git push --force-with-lease`, and if someone already pulled the old SHA, they get a broken history - mention `git commit --amend --reset-author` for the case where you deliberately want to update the author stamp - name `git commit --fixup=<sha>` + `git rebase -i --autosquash` as a more structured amend for a commit that is not the last one

Подводные камни

  • ✗ Amending a pushed commit without coordination. Teammates get a broken branch.
  • ✗ Thinking `--no-edit` means "nothing changes". The SHA is new anyway.
  • ✗ Amending and then running `git push` without force. You get a reject, then you panic-run `git pull` and drag the old commit back in as a merge.

Follow-up

  • ? After an amend, does `git log` show both the old and new commit, or only the new one?
  • ? How does `git commit --amend --reset-author` differ from a plain amend?
  • ? When do you reach for `git commit --fixup=<sha>` instead of amend?

Глубина в базе знаний

  • git commit --amend
  • Commit
  • Force push
tags: rewriting, amend, safety

#git-rebase-interactive-rewrite

intermediateчасто

How do you rewrite a series of commits in a feature branch before a PR?

Что отвечать

`git rebase -i origin/main` opens an editor with your commits from main to HEAD. You change `pick` to `fixup` where you want to squash, to `reword` where you want to rewrite the message, and to `edit` where you want to stop and adjust the content. Reorder the lines and the order changes. Close the editor and Git applies them one by one. On a conflict, run `git rebase --continue` after the resolve, or `git rebase --abort` to undo everything.

Что хотят услышать

A senior should: - describe a concrete scenario: 5 commits like `wip`, `fix typo`, `address review` → one atomic commit plus one atomic commit plus the real feature - name `--autosquash` plus prior `git commit --fixup=<sha>` as the cleanest workflow: you commit fixes already targeted, then a single command squashes them - say that after the rebase you need a force-push (on a feature branch that is fine, `--force-with-lease`) - mention that `exec <cmd>` in the todo list lets you insert a check: for example `pick A` / `exec npm test` / `pick B`. If the tests fail, the rebase stops. - name `git rebase --abort` as the safety net if you get tangled up

Подводные камни

  • ✗ Running rebase -i on a branch that several other developers have already pulled. After the force-push it breaks for them.
  • ✗ Closing the editor with an empty list of commits by accident. Git takes it to mean you want to delete everything, and the branch goes empty.
  • ✗ Starting a rebase from a dirty working tree. The first conflict mixes with your local changes.

Follow-up

  • ? What does `--autosquash` do with commits prefixed `fixup!`?
  • ? How do you move a commit from the middle to the front with rebase -i?
  • ? What does `git status` show in the middle of an interactive rebase with a conflict?

Глубина в базе знаний

  • git rebase
  • Interactive rebase
  • git commit --amend
  • Force push
tags: rewriting, rebase, prep

#git-filter-repo-secrets

seniorиногда

You accidentally committed `.env` with a secret into a public repo a month ago. How do you clean it out?

Что отвечать

`git filter-repo --invert-paths --path .env` (or `--path-glob '*.env'`). This rewrites the whole history, removing the file from every commit, **changes the SHA of every commit that touched the file**, and requires `git push --force` on all branches and tags. Then the important part: **rotate the secret**. Removing it from history does not help. It has already been seen, downloaded, and cached by GitHub. filter-repo is cleanup, not a cure.

Что хотят услышать

A senior should: - name `git filter-repo` and **not** `git filter-branch`. The latter has been deprecated since 2022, is slow, and is buggy. - stress that cleaning history = rewriting SHAs = force-push of all branches and tags plus a request for every developer to re-clone the repo - say that **rotating the secret is mandatory and comes first**. Cleaning history is housekeeping, not prevention. - mention that GitHub caches all commits, including force-pushed ones: `https://github.com/<repo>/commit/<old-sha>` stays reachable for a long time, and forks keep their own copy - name `git filter-repo --replace-text` to swap the value (for example with `***REDACTED***`) when removing the whole file is not desirable - say that `BFG Repo-Cleaner` is a popular alternative, but filter-repo is the officially recommended tool today

Подводные камни

  • ✗ Using `git filter-branch`. It is deprecated, filter-repo is the replacement.
  • ✗ Running filter-repo and not rotating the secret. The leak is not closed, the file is already downloaded.
  • ✗ Thinking a force-push to main hides the commit on GitHub. The old SHA stays reachable by direct link.
  • ✗ Not warning the team before the force-push. Everyone ends up with broken local clones.

Follow-up

  • ? Why is `git filter-repo` better than `git filter-branch`?
  • ? What do you do about PRs that contained this secret before you removed it?
  • ? How do you use `--replace-text` to hide values without deleting the file?

Глубина в базе знаний

  • git filter-repo: Rewriting History
  • Force push
  • Secret Scanning in a Repository
tags: rewriting, filter-repo, security

#git-coordinate-team-rewrite

seniorредко

How do you align with the team before rewriting history on a shared branch?

Что отвечать

First: confirm that the rewrite is really needed (often a revert commit or a separate cleanup branch is enough). If it is needed: pick a time (Friday evening, for example), notify everyone explicitly (Slack, email, not just the PR description), and have everyone commit and push their work. After the rewrite: write "history has been rewritten, re-clone or run `git fetch && git reset --hard origin/<branch>`". Reset, not pull. A pull draws duplicates.

Что хотят услышать

A senior should: - first ask "can we get by with a revert". A revert is a new commit, not a rewrite, and it is safe. - name a concrete recovery protocol for teammates: `git fetch --all` → `git reset --hard origin/<branch>` (not `pull`, which tries to merge and makes a mess) - mention that uncommitted local work must be preserved with `git stash` or a separate branch **before** the reset - say that for long-lived branches (main, release) this maneuver needs a freeze window and often coordination with CI/CD - name an ADR / RFC / postmortem as a mandatory artifact after the rewrite. Otherwise in half a year nobody remembers why the SHAs jump.

Подводные камни

  • ✗ Rewriting history "quietly" in the hope that nobody notices. They notice through broken local clones and lost work.
  • ✗ Telling people to "run `git pull`" instead of `git reset --hard`. The pull merges the old and new history.
  • ✗ Not saving teammates' local work before the reset. They lose uncommitted changes.

Follow-up

  • ? When is a revert commit better than a rewrite?
  • ? What happens to a teammate who runs `git pull` instead of reset after your force-push?
  • ? How do you recover a teammate's work from their reflog after a rewrite?

Глубина в базе знаний

  • Force push
  • git rebase
  • git reflog
tags: rewriting, team, coordination

#git-lost-commits-after-rewrite

seniorиногда

I force-pushed, and now a teammate's `git log` shows my old commits plus my new ones. What happened and how do I fix it?

Что отвечать

The teammate ran `git pull` (not reset) after your force-push. Pull = fetch + merge: their local branch with your old commits merged with the remote branch holding your new commits. The result is a merge commit that joins the two histories, the one you discarded and the new one. The fix: the teammate runs `git reset --hard origin/<branch>` (after saving their uncommitted work). In the future: `git config pull.ff only` so that pull does not merge.

Что хотят услышать

A senior should: - explain the cause: `git pull` without `--rebase` does a merge that reconciles the "local commits" (old) with the "new remote ones" - name `git reset --hard origin/<branch>` as the correct recovery, after `git stash` for uncommitted work - suggest `git config --global pull.ff only` as prevention: pull will refuse when a merge is needed and force an explicit choice of reset or rebase - say that if the teammate had **their own new** local commits on top of the old ones, those need to be cherry-picked onto the new base without losing them - name how to avoid this entirely: agree on the rewrite in advance and use `--force-with-lease`, which sometimes catches the problem before the push

Подводные камни

  • ✗ Not explaining to the teammate that a reset is needed. They run another pull and get another merge commit.
  • ✗ Reset without stash. They lose uncommitted changes.
  • ✗ Thinking `pull.ff only` is the fix for the problem. It is prevention. After the screwup you still need a reset.

Follow-up

  • ? What does `git log --graph` show for a teammate after a botched pull?
  • ? How does a teammate keep their own local commits during a reset?
  • ? How does `pull.ff only` differ from `pull.rebase true`?

Глубина в базе знаний

  • git pull
  • git rebase
  • git reflog
  • Force push
tags: rewriting, recovery, team
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies