Git: undo (almost) anything

updated 2026-07-01#git#annuler#restore

Undo unstaged changes

You changed a file and want to go back to the last committed version. ⚠️ git restore overwrites your changes with no way back — check with git diff that you're not throwing away anything important.

shell
git diff                   # relis ce que tu vas perdre / re-read what you're about to lose
git restore <fichier>      # ⚠️ écrase les modifs du fichier / discards the file's changes
git restore .              # ⚠️ écrase TOUTES les modifs / discards ALL changes

Unstage a file

Ran git add on too much? restore --staged removes the file from the staging area without touching its content. No risk here: your changes stay in the file.

shell
git restore --staged <fichier>
git restore --staged .     # dé-stage tout / unstage everything

Fix the last commit

Bad message, forgotten file? --amend replaces the last commit with a new one. ⚠️ It rewrites history: only do it if the commit has not been pushed yet. If it's already on the remote, use revert (next section).

shell
git commit --amend -m "meilleur message"      # corrige le message / fix the message
git add fichier-oublie && git commit --amend --no-edit   # ajoute un fichier / add a file

Undo a pushed commit

The commit is already on the remote, others may have pulled it: don't rewrite anything. git revert creates a new commit that applies the inverse — history stays intact and everyone stays in sync. It's THE safe method on a shared branch.

shell
git revert <commit>        # annule ce commit par un commit inverse / undo via an inverse commit
git push

Roll back locally

git reset moves your branch to an earlier commit. Three modes, from gentlest to most destructive:

  • --soft: changes from the undone commits stay staged (great for re-splitting).
  • --mixed (default): they stay in your files, unstaged.
  • ⚠️ --hard: everything is wiped, commits AND pending changes. Local use only, and only when you're sure of your git status.
shell
git reset --soft HEAD~1    # annule le commit, garde tout stagé / undo commit, keep staged
git reset HEAD~1           # annule le commit, garde les fichiers / undo commit, keep files
git reset --hard HEAD~1    # ⚠️ efface commit ET modifs / wipes commit AND changes

Recover a "lost" commit

One reset --hard too many, deleted a branch? Breathe: a commit is almost never truly lost. git reflog journals every move of HEAD for ~90 days. Find the hash from before the mistake, and start again from there.

shell
git reflog                        # historique des positions de HEAD / history of HEAD positions
git switch -c secours <hash>      # nouvelle branche sur le commit retrouvé / new branch on the recovered commit

push --force: the real danger

⚠️ Never git push --force on a shared branch: you silently overwrite commits your teammates may have pushed in the meantime. If you really must force (after rebasing YOUR feature branch), use --force-with-lease: it refuses to push if the remote moved since you last fetched.

shell
git push --force-with-lease    # force "poli" : échoue si le distant a changé / "polite" force: fails if remote changed