What is the difference between `checkout` and `reset`?

Question

The behavior of git reset and git checkout seem similar in the way that they treat the HEAD pointer and the commits that we have access to as a result. How do they differ?

Answer

The differences in the way that checkout and reset treat the HEAD pointer can be a bit subtle. The following image from ProGit Git reference book is very helpful.


So what are we seeing here? First, let’s understand that (1) master and develop are different branches of our project and (2) the HEAD pointer points to a particular branch, not a commit directly. With that, we have the following difference between the two commands:

  1. git checkout master: checkout updates HEAD. It simply makes HEAD point to the master branch instead of the develop branch as it did initially.
  2. git reset master: On the other hand, reset will move the branch that HEAD points to. That branch is updated but HEAD still points to the same branch.

So although the commit that the HEAD pointer is referring to is the same, the way that the commands behave are quite different.

6 Likes

Hmm… Does the title imply that I can use this explanation to understand the difference between the commands 'git checkout – ’ and ‘git reset --hard/soft’? Or does it work only for those particular commands in the explanation? :slight_smile:

2 Likes

This not explain checkout HEAD vs reset HEAD!!!

7 Likes

Not sure if I’m correct but this is what I gathered. Say you make a big change to your working directory then later in your session decide you want to convert back to the way the file was before. Problem is you forgot exactly how it was worded or structured. Checkout HEAD actually changes the working directory of specified filename to its last committed state. Removing all changes from the file itself.

Reset HEAD simply removes the specified filename from the staging area in the event you no longer want it to be committed together with certain other changes.

Reset HEAD 2 is a way to rewind to a previous commit at a point before you made some mistake that left all following commits invalid to some degree. Results in completely removing commits that come after point of reset from your repository since they are now useless and pollute repository, possibly adding confusion for other developers.

7 Likes

What makes this tricky is that git checkout and git reset do different things depending on the following argument.

git checkout [branch], as explained above, moves HEAD to the specified branch. It also clears your staging area/index and changes your working directory to match the commit on the specified branch. On the other hand, git checkout HEAD [filename] replaces that file in your working directory with the one in the commit that HEAD points to.

git reset [branch or commit SHA], as explained above, moves the branch that HEAD points to. This is the context of git reset --hard/soft, which determine what happens to your working directory and staging area/index. On the other hand, git reset [filename] unstages the file from your staging area/index.

3 Likes

git reset [branch or commit SHA] doesn’t remove commits from the repository. It changes the commit that the branch you’re resetting points to. You could still have another branch pointing to the later commits. Even if no branches pointed to the later commits, the commits are still there, just “orphaned.” They would no longer show in git log for any branches. But you could create a new branch that points to the SHA of a later commit.

4 Likes

Where do we find these orphans?

1 Like

So, if I understand correctly, neither reset or checkout ever deletes a file or a commit. it just moves the HEAD pointer to a previous commit in the case of reset or it modifies files in the current staging area in the case of checkout.

If that’s right, this is good in terms of tracking all changes - nothing is ever deleted. But as someone asked previously, how do you find the orphaned changes or commits if they no longer appear in the log?

This tells you where they are or how to get back to them.
Once we reset a project to an earlier point, do the commits after that point get deleted?.