Difference Between the Git Reset, Revert, and Checkout Commands
- Difference Between the Git Reset, Git Revert, and Git Checkout Commands
- Git Reset vs. Git Revert vs. Git Checkout
- Commit Level Operations
- File Level Operations
This article discusses the difference between the git reset
, git revert
, and git checkout
commands. These are some of the most useful Git utilities that allow us to undo some changes in our repositories.
It is easy to mix up the commands, but by the end of this article, you will have gained the confidence to use and navigate your repository with the above commands.
Difference Between the Git Reset, Git Revert, and Git Checkout Commands
It will be easier to understand these commands if we are clear on the effect of each command on the three main components of a Git repository.
- The working directory
- Staged snapshot
- Commit history
We can also call the above components the Three Trees
.
Git Checkout
What do we mean by checking out?
This operation relocates the HEAD
pointer to a specified commit.
The image above shows a sequence of commits in a Git repository. The HEAD
and main
branch pointers are currently at the commit d
.
We can move our HEAD
ref to any commit using the git checkout
command.
For example, to move our HEAD
ref to the commit b
, we will run:
$ git checkout -b
We can use the git checkout
command at the commit and file level. Checking out at the file level will update the file’s contents with the contents of the specified commit.
Git Revert
When reverting, we take a specific commit and create a new one that reverses the specified commit’s effect. The git revert
commit only takes effect at the commit level and does not have file-level functionality.
Git Reset
When resetting, we take a specific commit, reset the Three Trees
, and update a repository to match the state of the repo at the specified commit. We can reset at three different modes corresponding to the three trees
.
We normally use the git reset
and the git checkout
to undo local or private changes. They both modify the history of a repository and can lead to conflicts when pushing to the remote public or shared repositories.
Git Reset vs. Git Revert vs. Git Checkout
The table below gives some common use cases for the three commands.
Command | Scope | Common Use Cases |
---|---|---|
git reset |
Commit level | Delete commits in a branch locally or discard uncommitted changes. |
git reset |
File level | Unstage a file from the index. |
git checkout |
Commit level | Inspect old commits and switch between branches. |
git checkout |
File level | Throw away changes in the working directory. |
git revert |
Commit level | Reverse the effects of a commit in public branches. |
git revert |
File level | (N/A) |
Commit Level Operations
We pass parameters to the git reset
and git checkout
commands to invoke different levels of operation. If we fail to include a file parameter, the commands act on the commit as a whole.
Reset a Commit
Resetting on the commit level will move the HEAD
ref to a specified commit. We can use this command to delete commits from a branch.
Here is an example.
$ git reset HEAD~3
The command above will move the tip of our branch backward by three commits. We can refer to them as dangling
or orphaned
commits.
We have discarded the three commits. It is best to use the command to do away with commits that we have not published to a remote shared repository.
We can also use the git reset
command to change the staged snapshot and working directory by passing one of the following flags.
--soft
- Does not change the staged changes or the working directory.--mixed
- Does not affect the working directory but alters the staged snapshot to match the specified commit.--hard
- Alters both the working directory and staged snapshot to match the specified commit.
Checkout Old Commits
We can use the git checkout
command to inspect a repository’s state at a specified commit. We can also pass branch names to switch between branches.
Here is an example.
$ git checkout feature
The command above will switch to the feature
branch. It will not move branches around.
We can also inspect arbitrary commits by passing a commit hash or reference instead of a branch name. Here is an example.
$ git checkout HEAD~1
The command above will check out the parent of our current commit. Passing HEAD~2
will check out the grandparent.
The command above will switch us into the detached HEAD
mode because our current HEAD
does not have a branch reference.
All changes and commits done in detached HEAD
mode will not be reachable once you switch to another branch. Always create a new branch when you want to commit changes while in the detached HEAD
state.
Revert Shared Commits
When we revert commits, we create a new commit that reverses the effects of the specified commit. This way, we avoid re-writing the commit history of shared repositories.
For example, if we want to revert the most recent commit, we will run:
$ git revert HEAD
File Level Operations
The git checkout
and the git reset
commands accept a file path as an optional parameter. The effects of the commands are limited to a single file.
Reset a File
We can update the staged snapshot of a file to match the version of the specified commit, as shown below.
$ git reset HEAD~1 README.md
The command above will fetch the version of the README.md
file in the parent commit of the current commit and add it to the index for the next commit. We can run git reset HEAD README.md
to unstage the README.md
file.
Git Checkout File
Passing a file path to the git checkout
command updates the working directory rather than the staged snapshot. This will not move the HEAD
pointer between branches.
Here is an example.
$ git checkout HEAD~1 README.md
This will fetch the version of the README.md
file from the parent commit of our current commit and update the README.md
file in our working directory only. It simply means we have reverted to the file version in the old commit.
Unlike the git revert
command that reverses the changes introduced by the specified commit, this discards all subsequent changes. We can use it to discard unstaged changes to a single file, as shown below.
$ git checkout HEAD README.md
In conclusion, we can easily differentiate between the git reset
, git revert
, and the git checkout
commands by understanding the effects of each command on the commit history, staged snapshot, and the working directory.
John is a Git and PowerShell geek. He uses his expertise in the version control system to help businesses manage their source code. According to him, Shell scripting is the number one choice for automating the management of systems.
LinkedInRelated Article - Git Revert
- How to Revert Commit Local in Git
- How to Revert a Git Repository to a Previous Commit
- How to Restore a Reverted Git Commit
- How to Delete Local Commits in Git
- How to Revert Merge Commit in Git