Is there a difference between "git reset --hard hash" and "git checkout hash"?

e-satis picture e-satis · Mar 29, 2010 · Viewed 16.2k times · Source

While reset and checkout have different usages most of the time, I can't see what difference there is between these two.

There probably is one or nobody would have bothered adding a --hard option to do something the basic checkout can do.

Maybe there is a difference is the way you will see the history?

Answer

Cascabel picture Cascabel · Mar 30, 2010

This answer is mostly quoted from my answer to a previous question: git reset in plain english.

The two are very different. They result in the same state for your index and work tree, but the resulting history and current branch aren't the same.

Suppose your history looks like this, with the master branch currently checked out:

- A - B - C (HEAD, master)

and you run git reset --hard B. You'll get this:

- A - B (HEAD, master)      # - C is still here, but there's no
                            # branch pointing to it anymore

You'd actually get that effect if you use --mixed or --soft too - the only difference is what happens to your work tree and index. In the --hard case, the work tree and index match B.

Now, suppose you'd run git checkout B instead. You'd get this:

- A - B (HEAD) - C (master)

You've ended up in a detached HEAD state. HEAD, work tree, index all match B, same as with the hard reset, but the master branch was left behind at C. If you make a new commit D at this point, you'll get this, which is probably not what you want:

- A - B - C (master)
       \
        D (HEAD)

So, you use checkout to, well, check out that commit. You can fiddle with it, do what you like, but you've left your branch behind. If you want the branch moved too, you use reset.