313

I am trying to learn how to restore or rollback files and projects to a prior state, and don't understand the difference between git revert, checkout, and reset. Why are there 3 different commands for seemingly the same purpose, and when should someone choose one over the other?

Elrond_EGLDer
  • 47,430
  • 25
  • 189
  • 180
haziz
  • 11,199
  • 14
  • 48
  • 69

6 Answers6

511

These three commands have entirely different purposes. They are not even remotely similar.

git revert

This command creates a new commit that undoes the changes from a previous commit. This command adds new history to the project (it doesn't modify existing history).

git checkout

This command checks-out content from the repository and puts it in your work tree. It can also have other effects, depending on how the command was invoked. For instance, it can also change which branch you are currently working on. This command doesn't make any changes to the history.

git reset

This command is a little more complicated. It actually does a couple of different things depending on how it is invoked. It modifies the index (the so-called "staging area"). Or it changes which commit a branch head is currently pointing at. This command may alter existing history (by changing the commit that a branch references).

Using these commands

If a commit has been made somewhere in the project's history, and you later decide that the commit is wrong and should not have been done, then git revert is the tool for the job. It will undo the changes introduced by the bad commit, recording the "undo" in the history.

If you have modified a file in your working tree, but haven't committed the change, then you can use git checkout to checkout a fresh-from-repository copy of the file.

If you have made a commit, but haven't shared it with anyone else and you decide you don't want it, then you can use git reset to rewrite the history so that it looks as though you never made that commit.

These are just some of the possible usage scenarios. There are other commands that can be useful in some situations, and the above three commands have other uses as well.

Dan Moulding
  • 183,296
  • 21
  • 89
  • 97
  • 18
    So the three commands can be used to UNDO some work, which means they're not so "entirely different". Same concept, different contexts. – Bruno Santos Sep 28 '14 at 21:40
  • 20
    @BrunoSantos: Candlesticks, lead pipes, daggers, and rope can all be used to murder people, but that doesn't mean any of those things are particularly similar. – Dan Moulding Sep 29 '14 at 15:50
  • 14
    @Dan Mounlding - Actually, there are many cases where `git reset` and `git checkout` can do the exact same thing. Saying that they are "not even remotely similar" is not just an over exaggeration: it's not even remotely true. These two commands can do so many different things, some of which completely overlap. Example: `git reset --hard` and `git checkout -- .` will do the exact same thing. And logically speaking, `git reset --hard ` and `git checkout ` should also do the exact same thing - git however prevents you from doing that. Confusing these two commands is VERY easy. – DanGordon Jan 08 '16 at 15:15
  • 8
    @DanGordon I realize we will probably just have a difference of opinion here. Nevertheless, I feel I should provide some explanation. You cannot do `git reset --hard ` like you can `git checkout ` precisely because the two commands do something *completely* different. `git reset` tells Git to move HEAD to a different commit. `git checkout` on the other hand doesn't ask Git to do anything with HEAD at all. It leaves HEAD alone and merely checks out a file. Yes, you can craft them in a way such that they have similar effects. But what they actually *do* is totally different. – Dan Moulding Jan 08 '16 at 18:33
  • very good explain – Guido Mocha Jan 13 '21 at 11:12
68

Let's say you had commits:

C
B
A

git revert B, will create a commit that undoes changes in B.

git revert A, will create a commit that undoes changes in A, but will not touch changes in B

Note that if changes in B are dependent on changes in A, the revert of A is not possible.

git reset --soft A, will change the commit history and repository; staging and working directory will still be at state of C.

git reset --mixed A, will change the commit history, repository, and staging; working directory will still be at state of C.

git reset --hard A, will change the commit history, repository, staging and working directory; you will go back to the state of A completely.

Akavall
  • 68,050
  • 39
  • 179
  • 227
29
  • git revert is used to undo a previous commit. In git, you can't alter or erase an earlier commit. (Actually you can, but it can cause problems.) So instead of editing the earlier commit, revert introduces a new commit that reverses an earlier one.
  • git reset is used to undo changes in your working directory that haven't been comitted yet.
  • git checkout is used to copy a file from some other commit to your current working tree. It doesn't automatically commit the file.
Arslan Ali
  • 16,294
  • 7
  • 51
  • 65
Jonathan
  • 1,033
  • 7
  • 12
  • 7
    I believe you are wrong about "git reset". "git reset" resets your HEAD to one of previous commits, it doesn't reset your working directory. Working directory is "reset" by "git checkout [filename]" – luigi7up Feb 04 '14 at 22:42
  • 11
    `git reset --soft` resets the HEAD only, `git reset --hard` resets the HEAD and your working directory. – Ehryk Nov 19 '14 at 23:29
  • git reset --mixed (default): uncommit + unstage changes – Deja Jul 10 '19 at 07:08
24
  • git checkout modifies your working tree,
  • git reset modifies which reference the branch you're on points to,
  • git revert adds a commit undoing changes.
Arslan Ali
  • 16,294
  • 7
  • 51
  • 65
dan_waterworth
  • 5,923
  • 1
  • 25
  • 39
  • 4
    `git reset` **does not just modify the commit that a branch points to**, it's also used to unstage files from the index, and can modify the working copy with `git reset --mixed` (the default). –  Jun 24 '14 at 18:41
  • git reset --soft: uncommit changes, changes are left staged (index). git reset --mixed (default): uncommit + unstage changes, changes are left in working tree. git reset --hard: uncommit + unstage + delete changes, nothing left. – Deja Jul 10 '19 at 07:00
6

Reset - On the commit-level, resetting is a way to move the tip of a branch to a different commit. This can be used to remove commits from the current branch.

Revert - Reverting undoes a commit by creating a new commit. This is a safe way to undo changes, as it has no chance of re-writing the commit history. Contrast this with git reset, which does alter the existing commit history. For this reason, git revert should be used to undo changes on a public branch, and git reset should be reserved for undoing changes on a private branch.

You can have a look on this link- Reset, Checkout and Revert

Sachchidanand Singh
  • 1,236
  • 1
  • 12
  • 14
5

If you broke the tree but didn't commit the code, you can use git reset, and if you just want to restore one file, you can use git checkout.

If you broke the tree and committed the code, you can use git revert HEAD.

http://book.git-scm.com/4_undoing_in_git_-_reset,_checkout_and_revert.html

Arslan Ali
  • 16,294
  • 7
  • 51
  • 65
LostMohican
  • 2,818
  • 7
  • 27
  • 36