Getting started with git reset hard vs soft vs mixed
In-depth knowledge of git reset hard vs soft vs mixed enables you to speed up file tracking. You can comfortably undo changes in the working area, staging area, or history.
You do the three git reset types by running the respective commands as follows:
git reset --hard <destination> git reset --soft <destination> git reset --mixed <destination>
You can ignore the --mixed
flag when doing git reset mixed because it is the default reset command.
The destination can be in the form of HEAD, such as
git reset --hard HEAD~1 git reset --soft HEAD~3 git reset HEAD~2
or a commit hash like
git reset --hard <commit hash> git reset --soft <commit hash> git reset <commit hash>
Mastering git reset hard vs soft vs mixed starts by defining crucial git terms and practicing each reset type with the exact workspace scenario. You will then discover the drawbacks and alternatives to git reset hard vs soft vs mixed, as explained below.
Terms to know before learning git reset hard vs soft vs mixed
You should be familiar with the git workflow, understanding the working area or directory, index, staging area, commit history, and HEAD
simplifies the visualization of the impact of git reset hard vs soft vs mixed.
Tracking a file entails three key stages: a working area, index, commit history. You edit the file to be tracked in the working area, and the working directory contains the target file.
Doing git add takes a snapshot of the target file(s). The files are said to be in the staging area, and the index is another name for the staging area.
Finally, the files get stored in the git database. Then, the files get a unique identifier called commit hash, helping to reference the files' history. The last commit forms the HEAD
of the history.
Let us see how the terms help differentiate git reset hard vs soft vs mixed.
Lab setup to explain git reset hard vs soft vs mixed
To fully understand the power and weaknesses of git reset hard vs soft vs mixed, we work with two environments: local and remote repos.
The local repo helps to analyze the differences among the three reset types. On the other hand, the remote repo clarifies conflict errors resulting from using git reset --hard on the remote repo.
Let us create the two workspaces right away.
Cloning a remote repo
I am creating a repo called git_reset_types
on Github.
Grab the repo URL.
then move to your command line and clone the remote repo locally
Building a local commit history
Navigate into git_reset_types
folder where we cloned the repo.
If you created a README.md
file on Github, you initialized a repo with an initial commit because Github did it for you. Otherwise, initialize an empty local git repo:
git init
Create two files file1.txt
and file2.txt
, in the git_reset_types
directory.
touch file1.txt file2.txt
Check the status.
git status
We have two untracked files.
Let us stage and commit the files.
Run
git add .
or
git add *
to stage the files.
Running
git status
we see the file changed from red to green, meaning git tracks the files.
Commit the changes using the message:
git commit -m "track file1 and file2"
Now we can view the commit history by running
git log
to view the full commit hash and history,
git log --graph --decorate
to have a better view of the HEAD or
git log --oneline
to have a summarized commit hash and history
We have two commits in the history to practice git reset hard vs soft vs mixed.
So our lab setup is ready to test and compare the different between git reset hard vs soft vs mixed using examples.
Example-1: Using git reset soft
Doing git reset --soft <destination>
returns the tracked changes to the staging area. To see this action, reset the head by running
git reset --soft HEAD~1
Resetting the HEAD ~1
means undoing the last commit.
Running
git status
shows git reset soft redirected the changes to the index.
Another way to undo changes using git reset soft is to specify the target commit hash.
For example, let us track the changes again:
git commit -m "track file1 and file2"
and log the history
git log --oneline
Let us undo the head changes again. This time around, we shall use the commit hash 95f3d48
instead of sequentially untracking the changes backward from the head.
git reset --soft 95f3d48
Using git reset soft enables you to undo changes to the staging area. Use git reset mixed to move a more profound level from the history.
Example-2: Using git reset mixed
You can use git reset mixed to entirely untrack the files without deleting them from the working directory.
Let us commit the above changes made on file1.txt
and file2.txt
to the history.
git commit -m "track file1 and file2"
Run the command
git log --graph --decorate
to have an aesthetic view of the commit HEAD
.
git reset --mixed HEAD~1
undoes one commit history.
git status
reveals the files are untracked.
Likewise, we can specify a commit hash when untracking changes using git reset soft. First, let us track the files again.
git add *
git commit -m "track file1 and file2"
Let us introduce another commit history by adding and committing more changes.
touch file3.txt file4.txt
git add *
git commit -m "track file3 and file4"
View the commit history again.
git log --oneline
and reset the second commit using the hash 0348176
git reset --mixed 0348176
Again, the changes get undone to the working area.
git status
What if you want to altogether remove the changes from the working tree? That is where git reset hard comes in.
Example-3: Using git reset hard
Git reset hard is one of the most disruptive commands to undo code changes. It untracks all (apart from unstaged) files from the specified commit hash and deletes them from the working directory. If you decide to go this route, ensure you don't push the changes to a remote repo after git hard reset.
Let us track the files we untracked in example-2 above.
git add *
git commit -m "track file3 and file4"
We can undo changes by specifying the number of commits from the HEAD
or using the commit hash.
Log the history.
git log --oneline
Running
git reset --hard 95f3d48
untracks the files committed after 95f3d48
and deletes them from the working directory.
Let us confirm the change at the history, index, or working directory levels.
git log
shows the previous two commit hashes do not exist.
git ls-files
We don't track the files.
git status
proves we neither track nor have pending changes.
Lastly,
ls
shows the files don't exist in the current directory.
Now that you know how to distinguish git reset hard vs soft vs mixed, let us focus on the drawbacks of the reset types.
Drawbacks of git reset hard vs soft vs mixed
Git reset is limited to file tracking at the local repo. Since git reset hard deletes files from the working directory, you should not use it on already pushed files because a conflict error will occur on subsequent pushes.
Let us confirm the conflict error.
Introduce another commit history by adding and committing more changes, then push them.
touch file1.txt file2.txt git add * git commit -m "track file1 and file2" git push
Refresh the remote repo to view the pushed commits.
Clicking on the icon labelled two commits gives a better picture of the changes.
git log --oneline
and do a hard reset on commit 95f3d48
git reset --hard 95f3d48
Add another file, commit and push the changes.
touch f1.txt f2.txt git add . git commit -m "track f1 and f2" git push
We find a conflict error
because the hard reset created a missing link in the commit history.
What should you do if you want to undo changes that affect both local and remote histories? Check these alternatives:
Bonus commands
Use below command to to undo changes to a file before staging it.
git checkout <filename>
Use below command to untrack files beyond the local repo, then add, commit, and push the changes.
git revert <commit hash>
Summary
Understanding git reset hard vs soft vs mixed enables you to undo changes at every level of the tracking tree.
Git reset hard undoes changes and removes the associated files from the working directory, staging area, and commit history. Git reset soft undoes the changes to the index. Git reset mixed untracks files without deleting them from the working area.
Use git checkout and revert to untrack files in situations when git reset is least favoured.