Git reset

07 Feb 2017

Contents

last modified: 17-feb-2017 (16:07)

Usage

Oftentimes 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.

Scenarios

git-reset has close relationship with these places. Possibly, we can do any of the following with reset command

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

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

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