Git Course 0%

restore vs reset vs revert vs rebase

Intermediate Core Git ≈ 12 min

Before this lesson

What you will learn

  • What each of the four actually changes
  • Which are safe on shared branches and which are not
  • How to choose in one sentence

After this lesson you can

  • I can explain the difference between these four to someone else

Why this matters

These four names are the reason Git has a reputation for being confusing. They sound interchangeable and are not: two of them rewrite history and two do not, and choosing wrongly on a shared branch is how a quiet afternoon becomes a team-wide problem.

The one-line answers

Command In one sentence
git restore Put a file back the way it was; nothing about history changes
git reset Move the branch pointer to another commit, optionally taking the files with it
git revert Add a new commit that undoes an old one, leaving both in the history
git rebase Replay your commits on top of a different base, giving them new hashes

What each one touches

Recall the three areas from lesson 2.2: the working tree, the staging area, and the commit history.

Working tree Staging area History Safe when pushed?
git restore <file> Overwritten Untouched Untouched Yes, it is local only
git restore --staged <file> Untouched Unstaged Untouched Yes
git reset --soft Untouched Gets the change Branch moves No
git reset --mixed Keeps the change Cleared Branch moves No
git reset --hard Overwritten Cleared Branch moves No
git revert <hash> Updated by the new commit Used briefly Adds a commit Yes
git rebase <base> Rebuilt Used during replay Commits replaced No

Read the last column as the decision. Anything that says no is a command for work that only exists on your computer.

Reset or revert: the pair that matters

Both undo a commit. The difference is what the history looks like afterwards.

git reset moves the branch back, so the commit is simply not there any more:

Text
before   A ─ B ─ C   (main)
after    A ─ B       (main)          C is unreferenced

git revert adds a commit whose content is the opposite of the one you name:

Text
before   A ─ B ─ C          (main)
after    A ─ B ─ C ─ C'     (main)   C' undoes C

If C has been pushed, your colleagues already have it. Reset makes your branch disagree with theirs, and the only way to publish that is a force push, which rewrites the shared branch under them (lesson 12.8). Revert is an ordinary commit that everyone receives with an ordinary pull.

Rebase belongs here too

git rebase is not an undo command, but it appears in this list because it is the fourth thing that changes commits (lesson 6.7). It replays your commits on a new base, and replaying means new hashes, which means the old commits are gone in the same way a reset leaves them behind.

The rule is the same and is worth stating as one: never rewrite commits that other people have. Rebasing your own unpushed branch onto an updated main is routine and encouraged. Rebasing a shared branch is the thing teams write rules about.

Restore is the odd one out

git restore never touches history at all. It is a file command: take the version from the commit (or from the staging area) and write it into the working tree.

That makes it the safest of the four for other people and the most dangerous for you, because the edit it discards was never recorded anywhere. The reflog cannot bring back what was never committed (lesson 12.1).

Choosing, in practice

Situation Command
"This file is a mess, give me the committed version" git restore <file>
"I staged the wrong file" git restore --staged <file>
"My last three commits should be one, and nothing is pushed" git reset --soft HEAD~3, then commit again
"That commit should never have gone in, and it is on main" git revert <hash>
"My branch is behind main and I want a straight history" git rebase main, on your own branch
"I have no idea what I did" git reflog first, then decide

How to do it

The four commands, with the safety question attached:

Terminal
$ git restore <file>            # discards your edit permanently
$ git restore --staged <file>   # unstages, keeps the edit
$ git reset --soft HEAD~1       # local only
$ git revert <hash>             # safe anywhere

git status before and git log --oneline -3 after: those two habits catch nearly every mistake in this lesson.

Common mistakes

  • Resetting a pushed branch, then force pushing to "fix" it, and rewriting history under three colleagues.
  • Confusing git restore <file> with git restore --staged <file>.
  • Reverting a merge commit without -m, which fails with a message about a mainline; that is lesson 12.6.
  • Rebasing a shared branch to tidy it up.
  • Thinking revert means "go back to that commit". It undoes one commit, it does not restore an old state.

Try it yourself

Goal: see the two histories side by side.

  1. On a branch, make commits A, B and C (any small edits).
  2. Run git log --oneline -4 and note the hashes.
  3. Run git reset --hard HEAD~1 and look at the log: C is gone.
  4. Bring it back with git reset --hard ORIG_HEAD.
  5. Now run git revert HEAD and look at the log: C is still there, with a new commit above it.
  6. Compare the two logs and write down which one a colleague would have to reconcile.

Expected result: two ways of removing the same change, one of which leaves a history that no longer matches anyone else's.

Show solution

Step 6 is the answer to the whole lesson. After the reset, your main and your colleague's main have different commits with the same name, which Git can only resolve with a force push and a lot of communication. After the revert, they run git pull and are done.

Check yourself

1. Which two of these rewrite history?
2. A commit is on the shared main and must be undone. Which command?
3. Why is git restore <file> described as dangerous even though it is safe for other people?

Key terms

Restore Revert Rebase Rewriting history Staging area