View on GitHub

example-git-commands

git-reset

There are cases when a changed is commited, yet not pushed, but later becomes undesired.

In such cases, there are two common approaches:

The first thing reset will do is move what HEAD points to, it moves the current working branch to a commit point, but without changing the git Index or Working Directory.

Not like git chckout, with which the branch ref is not changed and only the HEAD ref has been moved to the target commit (HEAD if not specified), git reset moves both HEAD and branch ref to the target commit, thus changes all three git trees (workspace, staging index, and commit tree HEAD).

The command line arguments --soft, --mixed, and --hard define how to modify the Staging Index, and Working Directory trees.

default –mixed HEAD

git reset: the default invocation of git reset has implicit arguments of –mixed and HEAD, same as git reset --mixed HEAD. In this form HEAD is the specified commit.

for example git status returns the following:

On branch master
Changes to be committed:
  (use "git reset HEAD ..." to unstage)
    new file: new_file
    modified: reset_lifecycle_file

We have added a new_file and modified the contents of reset_lifecycle_file. These changes are then applied to the Staging Index.

After running git reset --mixed, the output is:

Unstaged changes after reset:
M	reset_lifecycle_file

And running git status, the output is:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
	modified:   reset_lifecycle_file
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	new_file

This shows that the Staging Index has been reset to a HEAD commit state where reset_lifecycle_file is the only file in the index, and it’s staged content has been reset to the version of HEAD.

Note that after mixed reset, there are modifications to reset_lifecycle_file and there is an untracked file new_file remaining in Working Directory.

–hard

This is the most direct, DANGEROUS, and most used option. When passed --hard the Commit History ref pointers are updated to the specified commit. Then, the Staging Index and Working Directory are reset to match that of the specified commit.

for example, a branch git status returns following:

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
	new file:   new_file
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
	modified:   reset_lifecycle_file

We can see that there are now pending changes. The Staging Index tree has a pending change for the addition of new_file and the Working Directory has a pending change for the modifications to reset_lifecycle_file.

After runnign git reset --hard, with git status, git indicates there are no pending changes. This data loss cannot be undone.

–soft

A git soft reset only changes commit history. Neither the Index or Working Directory is touched by a soft reset.

for example, by running git log, commit history is shown

commit 17df60e096204d40066a44d438f1d7f55d73ca5b (HEAD -> master)
Author: ...
Date:   ...
    another change to reset_lifecycle_file
commit ef08b694cc229e08283465f2965a813d081146f4
Author: ...
Date:   ...
    revise reset_lifecycle_file
commit 3c0763b1e3b4a96e89bc934dff502b0277c129e3
Author: ...
Date:   ...
    initial commit

We would like to reset to first commit 3c0763b1e... by running

git reset --soft 3c0763b1e

Here is the interesting output. Running git status shows:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
	modified:   reset_lifecycle_file
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	new_file

While git log now shows:

commit 3c0763b1e3b4a96e89bc934dff502b0277c129e3 (HEAD -> master)
Author: ...
Date:   ...
    initial commit

The log output now shows that there is a single commit in the Commit History. This helps to illustrate what --soft has done. As with all git reset invocations, the first action, by --soft, that git reset takes is to reset the commit tree. Our previous examples with --hard and --mixed continous beyond this step. --mixed resets the HEAD ref, while --hard continous further and resets the Working Directory.

reset between branches

Basically it is the same as using reset within the branch, with only the target commit being another branch

git checkout test-branch
git reset --hard master

The hard reset above is reseting the test-branch to the HEAD commit of master branch. All the rules abut hard, mixed, or soft options are the same.