Git Resets

21 March 2019

What happens when you do a reset in Git?

I had a conversation with a colleague today about the git reset command.

I realised that while I use git reset --hard reasonably regularly (e.g. in order to move a branch when I've committed on the wrong one), I didn't know much about the --mixed or --soft modes.

The documentation on each of them is a little vague, so I thought I'd just try them out and see what happens. I hope this will serve as a useful reference.

Suppose I create a repository which looks as follows.

Initial Commit Commit A Commit B Staged Unstaged
A1.txt
A2.txt
B1.txt
B2.txt
C1.txt
C2.txt
D1.txt
D2.txt
A1.txt
A2.txt
A3.txt
B1.txt
B2.txt
B3.txt
C1.txt
C2.txt
C3.txt
D1.txt
D2.txt
D3.txt

(Hopefully it's clear what I mean by each of these icons.)

Here's the result of performing different types of resets.

Commit A Commit B Staged Unstaged
Soft, commit B A1.txt
A2.txt
A3.txt
B1.txt
B2.txt
B3.txt
C1.txt
C2.txt
C3.txt
D1.txt
D2.txt
D3.txt
Mixed, commit B A1.txt
A2.txt
A3.txt
B1.txt
B2.txt
B3.txt
C1.txt
C2.txt
C3.txt
D1.txt
D2.txt
D3.txt
Hard, commit B A1.txt
A2.txt
A3.txt
B1.txt
B2.txt
B3.txt
D3.txt
Soft, commit A A1.txt
A2.txt
A3.txt
N/A B1.txt
B2.txt
B3.txt
C1.txt
C2.txt
C3.txt
D1.txt
D2.txt
D3.txt
Mixed, commit A A1.txt
A2.txt
A3.txt
N/A B1.txt
B2.txt
B3.txt
C1.txt
C2.txt
C3.txt
D1.txt
D2.txt
D3.txt
Hard, commit A A1.txt
A2.txt
A3.txt
N/A D3.txt

The thing that surprised me most about this is what happens when you do a hard reset. Because the index only contains tracked files, the unstaged addition of D3.txt remains after the hard reset. Personally I think it would make more sense for Git to remove this file, but that's not what happens!