UP | HOME

Git reset vs checkout

1 Reset

1.1 3 trees

There are three "trees" that git keeps track of:

  • the staging area or working index: this is where files get put when you git add. Note that once in the staging area, a file is frozen in the moment it was staged. That is, if I modify a file with changes so it is in state \(A\), stage it, and then modify it to be in state \(B\), then the file will still be in state \(A\) in the staging area. Think of the staging area as holding a snapshot of a change.
  • the working directory: this is what you see when you open a file with vim or some other editor. All the changes, even if they are unstaged or uncommitted, appear here. Note that only tracked files appear in git's working directory. When we begin tracking a file with git add, it gets staged immediately.
  • the commit history: these are the files, frozen in a snapshot, at a particular commit

Note that reset behaves differently depending on whether it is called on the file level or commit level.

1.2 3 modes of git reset

git reset is used to move the branch tip and HEAD back to a certain commit.

There are three modes to reset:

1.2.1 soft

--soft only sets the git commit back to the specified commit. It doesn't change the index or the working directory. When do you want to use this? Whenever, you realize that the past few commits may have been a mistake, so you want to trash them, but you also want to keep your current work, maybe as scratch work or to see what you can salvage.

---before---
      master, head
            |
      A--B--C

---after---
   master, head
         |
      A--B--C

1.2.2 mixed

--mixed will move the branch and HEAD to the specified commit and will set the staging area to be the snapshot at the specified commit. But it won't change anything in the working directory.

tl;dr – your working directory will stay the same, but you'll lose everything in the staging area

1.2.3 hard

--hard will do everything that --mixed does, but it will ALSO set the working tree to be the same as the specified commit.

tl;dr – your working directory, staging area, and commit history will now all match the snapshot in the specified commit

1.3 file level

When we git reset on a file, we will set its state in the staging area to match its state in the snapshot at a given commit. The HEAD and branch pointer remain where they are. In the special case where we have staged some changes to a file, and then use reset to set it to match its state in HEAD, we are effectively unstaging our changes. The file in the working directory will still have the changes, but they won't be in the staging area.

The modes soft, hard, mixed have no effect on the file level behavior.

2 Checkout

git checkout also differs between the file and commit levels.

2.1 commit level

git checkout moves the HEAD to the specified commit. The working directory will be changed to reflect that of the commit. If there are any uncommitted changes in your current working directory, git will ask you to commit them so they don't get overwritten.

Note that the staging area is set to match that of the snapshot in the specified commit

2.2 file level

This overwrites the file in your working directory with the file in the specified commit. Note that it also resets your staging area to reflect your current commit (see here).

In the special case where the commit is HEAD, this trashes all the changes you've made in the working directory for a file. We can also use git restore to accomplish the same effect.

3 helpful links

Created: 2021-09-14 Tue 21:44