Git reset
Git #gitOftentimes we commit some code and want to undo it for any reason (may be for retyping commit message or whatever). Git does not
leave us alone in this scenario and provides a reset
command for this purpose.
With
reset
command we can undo changes or we can totally destroy our commit. Second one is dangerous, so always think twice before resetting anything in git.
Background
Before proceeding I will briefly explain what happens when we commit. Git is all about taking snapshot of file with time. When we add file in index or staging area and commit, git takes the snapshot of staging area and stores it as blob in .git directory. With this, we have actually three place where a file can reside.
- In working directory
- In index/staging area
- In git repo
Scenarios
git-reset
has close relationship with these places. Possibly, we can do any of the following with reset command
- Move changes from git to index (
index <- git
) - Move changes from index to working directory (
working <- index
) - Move changes from git to working directory (
working <- git
) - Completely remove the changes (dangerous!)
Example
Let’s create a demo repo for this article.
Qazi@Geek MINGW64 /f/Sandbox
$ mkdir gitdemo && cd gitdemo
Qazi@Geek MINGW64 /f/Sandbox/gitdemo
$ git init # initialize git repo
Initialized empty Git repository in F:/Sandbox/gitdemo/.git/
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ touch post.txt # create a dummy file
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ echo "this is dummy text" >> post.txt # add dummy text
Now we have file post.txt
in our gitdemo
local repo. post.txt
is newly created file and is in working directory. Let’s
add/remove it to index
.
add post.txt
to index
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git status --short
?? post.txt
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git add post.txt
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: post.txt
Default Reset
By default, reset
will unstage changes or will move the changes from repo to working directory. Default reset
is same
as reset --mixed
working area <- staging
working area <- repo
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git reset post.txt
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git status --short
?? post.txt # back in working dir, see ?? in the start
Soft Reset
Soft reset moves the changes from git repo to staging area. git reset --soft commit-hash
stating area <- repo
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ cat post.txt
fist line
second line
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git status # nothing in staging area
On branch master
nothing to commit, working tree clean
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git log --oneline # there are 2 commits
f72f034 second commit
ff63370 first commit
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git reset --soft HEAD~1 # reset to first commit, but put changes in index
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: post.txt # changes back to staging area
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git log --oneline # moved to first commit
ff63370 first commit
Hard Reset
Hard reset completely removes the changes made by a commit. Once you hard reset a commit, you will not be able to recover changes.
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ cat post.txt # see what's in post.txt
fist line
second line
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ # first commit added first line, second commit added second line
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git log --oneline
fad109a second commit
ff63370 first commit
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git reset --hard ff63370 # reset to first commit, it will remove change from 2nd commit i.e second line
HEAD is now at ff63370 first commit
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ cat post.txt # changes removed
fist line
Qazi@Geek MINGW64 /f/Sandbox/gitdemo (master)
$ git log --oneline
ff63370 first commit