Basically a file can be in three different states. It can be untracked, unstaged or staged. Untracked files have never been added to the tree yet — meaning they are completely new. Unstaged files are files that have already been in the tree but have been modified. These modified changes can be added to the next state files that can be in, the staged files. Staged files are those which go into the next commit. If you type git status in your repository, you can also see those three states.

git status — different file states

Remove New Files from Staged Files

Staged files are those which go into your next commit. If you accidentally added files to the staged area, you can undo this by typing git restore --staged <file> , so in this case, it would be git restore --staged lib.c . The file lib.c would be moved again into the untracked area, because it is a completely new file. The changes that you made will still be there. If you do not need the made changes anymore, you can just delete the file.

Remove Existing Files from Staged Files

If the file was already in the tree, you can either keep the changes that you made or reset it to the last commit. git restore --staged <file> will again move the file from the staged to the unstaged area. If you want to reset the file to the latest commit, you first have to unstage your file, i.e., removing it from the staged area — and then you can restore the file to the latest commit typing git restore <file> .

Okay — moving files around between the untracked/unstaged area and staged area is easy. But what if you already committed the files, and you need to undo the latest commit? Let’s see how we can work this one out.

Undo a Commit

So let’s assume you want to undo the latest commit, but want to keep your changes. Your commits in your working tree basically look like this:

So your actual commit you are on right now is “Add superDuper.d”. Now you want to undo this commit but keep the changes. The changes will move from the commit to the unstaged/untracked area. git reset HEAD^ will reset your tree to the commit prior to the one you are on right now. HEAD^ is the short form for HEAD-1 . The HEAD is where your working directory is actually on right now.

If you want to discard the commit without keeping the changes, add --hard to the command: git reset --hard HEAD^ . Be careful, this deletes the change made in the commit.

Reverting a remote commit

The last thing that you need in your git toolbox is revert . Reverting means undoing the last commit. The problem here is, that the tree is already synced with your remote. So just removing the commit is not so easy. What we have to do is really undoing what we did within a separate commit. git revert HEAD does exactly this. It takes your latest commit and reverts all the changes made and commits these reverted changes into its own commit. So let's check our current git history.

So now we want to revert the latest commit where we added the database.md file. If we type git revert HEAD it reverts the latest commit made. Though our tree would look like this:

Now you can push the changes made to the remote and you successfully reverted the latest commit.

Further Reading

If you want to know more about git and how to improve your git skills in the command line, check out my article about Becoming a Git Terminal Pro.