Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 886
e-satis Avatar asked Mar 29 '10 21:03

e-satis


People also ask

What is the difference between git reset and git checkout?

git reset is specifically about updating the index, moving the HEAD. git checkout is about updating the working tree (to the index or the specified tree). It will update the HEAD only if you checkout a branch (if not, you end up with a detached HEAD).

What is the difference between reset and reset git?

So, in short, we can say that “git reset” is a command, whereas “git reset –hard” is its variation that is used when you want to wipe out all the traces of your last commit.

What does hard reset mean in git?

git reset --hard. Reset the staging area and the working directory to match the most recent commit. In addition to unstaging changes, the --hard flag tells Git to overwrite all changes in the working directory, too.

Should you use git reset hard?

First, it's always worth noting that git reset --hard is a potentially dangerous command, since it throws away all your uncommitted changes. For safety, you should always check that the output of git status is clean (that is, empty) before using it.


2 Answers

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.

like image 155
Cascabel Avatar answered Sep 20 '22 18:09

Cascabel


If documentation provided with Git doesn't help you, take a look at A Visual Git Reference by Mark Lodato.

In particular if you are comparing git checkout <non-branch> with git reset --hard <non-branch> (hotlinked):

git checkout master~3
(source: github.com)

git reset --hard master~3

Note that in the case of git reset --hard master~3 you leave behind a part of DAG of revisions - some of commits are not referenced by any branch. Those are protected for (by default) 30 days by reflog; they would ultimately be pruned (removed).

like image 40
Jakub Narębski Avatar answered Sep 17 '22 18:09

Jakub Narębski