Saturday, August 5, 2023

git reset [commit] [path]

  

Currently, I am curious to find out what Git will do for us behind the scene if we run the 'git reset [commit] [path]' command. Below are the logs coming from my experiment. 


Reference: Git Book


Preparation


Create a brand new folder and run the 'git init' command.


Step 1:


Run the following commands to keep changing a file and make three commits


    $ echo 'v1' > file.txt
$ git add .
$ git commit -m 'v1'
[master (root-commit) 1491536] v1 1 file changed, 1 insertion(+) create mode 100644 file.txt

    $ echo 'v2' > file.txt
$ git add .
$ git commit -m 'v2'
    [master 9a8fa1e] v2
     1 file changed, 1 insertion(+), 1 deletion(-)

    $ echo 'v3' > file.txt
$ git add .
$ git commit -m 'v3'
[master d0769a6] v3 1 file changed, 1 insertion(+), 1 deletion(-)



Check the git status.


    $ git status
On branch master nothing to commit, working tree clean


It is all synced (the three trees below keep the v3 version of file.txt).


Check the .git tree structure.


    $ tree .git/
.git/ ├── COMMIT_EDITMSG ├── HEAD ├── branches ├── config ├── description ├── hooks │   ├── applypatch-msg.sample │   ├── commit-msg.sample │   ├── fsmonitor-watchman.sample │   ├── post-update.sample │   ├── pre-applypatch.sample │   ├── pre-commit.sample │   ├── pre-merge-commit.sample │   ├── pre-push.sample │   ├── pre-rebase.sample │   ├── pre-receive.sample │   ├── prepare-commit-msg.sample │   ├── push-to-checkout.sample │   └── update.sample ├── index ├── info │   └── exclude ├── logs │   ├── HEAD │   └── refs │   └── heads
│   └── master ├── objects
│   ├── 14 │   │   └── 91536a26a35b6a0037cfa9ccbac70fecdb77d0 (git commit object for v1) │   ├── 25 │   │   └── 7330bfc3b1cce445c8bf7202d88eca9ffff025 (git tree object for v2) │   ├── 29 │   │   └── ef827e8a45b1039d908884aae4490157bcb2b4 (git blob object for v3) │   ├── 62 │   │   └── 6799f0f85326a8c1fc522db584e86cdfccd51f (git blob object for v1) │   ├── 8c │   │   └── 1384d825dbbe41309b7dc18ee7991a9085c46e (git blob object for v2) │   ├── 9a │   │   └── 8fa1eee2b0d2841ffa1e5515935421c3d419e1 (git commit object for v2) │   ├── a7 │   │   └── 949a02518883287c308f0b47e2a4934b111cc3 (git tree object for v3) │   ├── cc │   │   └── 5fda52eb3ed07cce6357ac11e392cd2dbf6d16 (git tree object for v1) │   ├── d0 │   │   └── 769a6fa5bcf4c05f667eb635dd84c1174be895 (git commit object for v3)
│   ├── info │   └── pack └── refs ├── heads
│   └── master └── tags 21 directories, 31 files


Check more info.


    $ cat .git/HEAD
ref: refs/heads/master

$ cat .git/refs/heads/master
d0769a6fa5bcf4c05f667eb635dd84c1174be895

$ git ls-files -s
100644 29ef827e8a45b1039d908884aae4490157bcb2b4 0 file.txt (v3 version)

$ git log --oneline --decorate --graph --all
* d0769a6 (HEAD -> master) v3 * 9a8fa1e v2 * 1491536 v1


Step 2:


Let's run the following commands to edit the file.txt as the v4 version and update the Index.


    $ echo 'v4' > file.txt
$ git add .


Check the git status.


    $ git status
On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: file.txt


Now, both the Index and the working directory keep the v4 version of file.txt.


Then run the 'git reset file.txt' command to reset the file.txt in the Index.

'git reset file.txt' quals to 'git reset --mixed HEAD file.txt'.

This command will not move HEAD pointer, and only update the [path] Index by the commit pointed by the HEAD pointer.


    $ git reset file.txt
    Unstaged changes after reset:
    M       file.txt


Check the git status.


    $ git status
On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: file.txt
no changes added to commit (use "git add" and/or "git commit -a")


The [path] Index is reset.


After running the 'git reset [commit] [path]' command, we revert the commands from


    $ echo 'v4' > file.txt
$ git add .

to


    $ echo 'v4' > file.txt


git reset --hard [commit]

 

Currently, I am curious to find out what Git will do for us behind the scene if we run the 'git reset --hard[commit]' command. Below are the logs coming from my experiment. 


Reference: Git Book


Preparation


Create a brand new folder and run the 'git init' command.


Step 1:


Run the following commands to keep changing a file and make three commits


    $ echo 'v1' > file.txt
$ git add .
$ git commit -m 'v1'
[master (root-commit) 1491536] v1 1 file changed, 1 insertion(+) create mode 100644 file.txt

    $ echo 'v2' > file.txt
$ git add .
$ git commit -m 'v2'
    [master 9a8fa1e] v2
     1 file changed, 1 insertion(+), 1 deletion(-)

    $ echo 'v3' > file.txt
$ git add .
$ git commit -m 'v3'
[master d0769a6] v3 1 file changed, 1 insertion(+), 1 deletion(-)



Check the git status.


    $ git status
On branch master nothing to commit, working tree clean


It is all synced (the three trees below keep the v3 version of file.txt).


Check the .git tree structure.


    $ tree .git/
.git/ ├── COMMIT_EDITMSG ├── HEAD ├── branches ├── config ├── description ├── hooks │   ├── applypatch-msg.sample │   ├── commit-msg.sample │   ├── fsmonitor-watchman.sample │   ├── post-update.sample │   ├── pre-applypatch.sample │   ├── pre-commit.sample │   ├── pre-merge-commit.sample │   ├── pre-push.sample │   ├── pre-rebase.sample │   ├── pre-receive.sample │   ├── prepare-commit-msg.sample │   ├── push-to-checkout.sample │   └── update.sample ├── index ├── info │   └── exclude ├── logs │   ├── HEAD │   └── refs │   └── heads
│   └── master ├── objects
│   ├── 14 │   │   └── 91536a26a35b6a0037cfa9ccbac70fecdb77d0 (git commit object for v1) │   ├── 25 │   │   └── 7330bfc3b1cce445c8bf7202d88eca9ffff025 (git tree object for v2) │   ├── 29 │   │   └── ef827e8a45b1039d908884aae4490157bcb2b4 (git blob object for v3) │   ├── 62 │   │   └── 6799f0f85326a8c1fc522db584e86cdfccd51f (git blob object for v1) │   ├── 8c │   │   └── 1384d825dbbe41309b7dc18ee7991a9085c46e (git blob object for v2) │   ├── 9a │   │   └── 8fa1eee2b0d2841ffa1e5515935421c3d419e1 (git commit object for v2) │   ├── a7 │   │   └── 949a02518883287c308f0b47e2a4934b111cc3 (git tree object for v3) │   ├── cc │   │   └── 5fda52eb3ed07cce6357ac11e392cd2dbf6d16 (git tree object for v1) │   ├── d0 │   │   └── 769a6fa5bcf4c05f667eb635dd84c1174be895 (git commit object for v3)
│   ├── info │   └── pack └── refs ├── heads
│   └── master └── tags 21 directories, 31 files


Check more info.


    $ cat .git/HEAD
ref: refs/heads/master

$ cat .git/refs/heads/master
d0769a6fa5bcf4c05f667eb635dd84c1174be895

$ git ls-files -s
100644 29ef827e8a45b1039d908884aae4490157bcb2b4 0 file.txt (v3 version)

$ git log --oneline --decorate --graph --all
* d0769a6 (HEAD -> master) v3 * 9a8fa1e v2 * 1491536 v1


Step 2:


Run the 'git reset --hard HEAD~' command to reset everything including the working directory, the Index, and the HEAD pointer.


    $ git reset --hard HEAD~
HEAD is now at 9a8fa1e v2


Check the git status.


    $ git status
On branch master nothing to commit, working tree clean


None of them below keep the v3 of file.txt.



Check the .git tree structure.

Only a new file ORIG_HEAD was created.


    $ tree .git/
.git/ ├── COMMIT_EDITMSG ├── HEAD 
├── ORIG_HEAD
├── branches ├── config ├── description ├── hooks │   ├── applypatch-msg.sample │   ├── commit-msg.sample │   ├── fsmonitor-watchman.sample │   ├── post-update.sample │   ├── pre-applypatch.sample │   ├── pre-commit.sample │   ├── pre-merge-commit.sample │   ├── pre-push.sample │   ├── pre-rebase.sample │   ├── pre-receive.sample │   ├── prepare-commit-msg.sample │   ├── push-to-checkout.sample │   └── update.sample ├── index ├── info │   └── exclude ├── logs │   ├── HEAD │   └── refs │   └── heads
│   └── master ├── objects
│   ├── 14 │   │   └── 91536a26a35b6a0037cfa9ccbac70fecdb77d0 (git commit object for v1) │   ├── 25 │   │   └── 7330bfc3b1cce445c8bf7202d88eca9ffff025 (git tree object for v2) │   ├── 29 │   │   └── ef827e8a45b1039d908884aae4490157bcb2b4 (git blob object for v3) │   ├── 62 │   │   └── 6799f0f85326a8c1fc522db584e86cdfccd51f (git blob object for v1) │   ├── 8c │   │   └── 1384d825dbbe41309b7dc18ee7991a9085c46e (git blob object for v2) │   ├── 9a │   │   └── 8fa1eee2b0d2841ffa1e5515935421c3d419e1 (git commit object for v2) │   ├── a7 │   │   └── 949a02518883287c308f0b47e2a4934b111cc3 (git tree object for v3) │   ├── cc │   │   └── 5fda52eb3ed07cce6357ac11e392cd2dbf6d16 (git tree object for v1) │   ├── d0 │   │   └── 769a6fa5bcf4c05f667eb635dd84c1174be895 (git commit object for v3)
│   ├── info │   └── pack └── refs ├── heads
│   └── master └── tags 21 directories, 32 files


Check more info.

The current branch points to its previous commit v2, not v3 anymore.

And the index points to v2 git blob object, not the v3 git blob object.


    $ cat .git/HEAD
ref: refs/heads/master

    $ cat .git/ORIG_HEAD
d0769a6fa5bcf4c05f667eb635dd84c1174be895 (this is git commit object for v3)

$ cat .git/refs/heads/master
9a8fa1eee2b0d2841ffa1e5515935421c3d419e1 (this is git commit object for v2)

$ git ls-files -s
100644 8c1384d825dbbe41309b7dc18ee7991a9085c46e 0 file.txt (v2 version)

$ git log --oneline --decorate --graph --all
* 9a8fa1e (HEAD -> master) v2 * 1491536 v1


After running the 'git reset --hard [commit]' command, we revert the commands from


    $ echo 'v3' > file.txt
$ git add .
$ git commit -m 'v3'
[master d0769a6] v3 1 file changed, 1 insertion(+), 1 deletion(-)

to


None


git reset --mixed [commit]


Currently, I am curious to find out what Git will do for us behind the scene if we run the 'git reset --mixed [commit]' command. Below are the logs coming from my experiment. 


Reference: Git Book


Preparation


Create a brand new folder and run the 'git init' command.


Step 1:


Run the following commands to keep changing a file and make three commits


    $ echo 'v1' > file.txt
$ git add .
$ git commit -m 'v1'
[master (root-commit) 1491536] v1 1 file changed, 1 insertion(+) create mode 100644 file.txt

    $ echo 'v2' > file.txt
$ git add .
$ git commit -m 'v2'
    [master 9a8fa1e] v2
     1 file changed, 1 insertion(+), 1 deletion(-)

    $ echo 'v3' > file.txt
$ git add .
$ git commit -m 'v3'
[master d0769a6] v3 1 file changed, 1 insertion(+), 1 deletion(-)



Check the git status.


    $ git status
On branch master nothing to commit, working tree clean


It is all synced (the three trees below keep the v3 version of file.txt).


Check the .git tree structure.


    $ tree .git/
.git/ ├── COMMIT_EDITMSG ├── HEAD ├── branches ├── config ├── description ├── hooks │   ├── applypatch-msg.sample │   ├── commit-msg.sample │   ├── fsmonitor-watchman.sample │   ├── post-update.sample │   ├── pre-applypatch.sample │   ├── pre-commit.sample │   ├── pre-merge-commit.sample │   ├── pre-push.sample │   ├── pre-rebase.sample │   ├── pre-receive.sample │   ├── prepare-commit-msg.sample │   ├── push-to-checkout.sample │   └── update.sample ├── index ├── info │   └── exclude ├── logs │   ├── HEAD │   └── refs │   └── heads
│   └── master ├── objects
│   ├── 14 │   │   └── 91536a26a35b6a0037cfa9ccbac70fecdb77d0 (git commit object for v1) │   ├── 25 │   │   └── 7330bfc3b1cce445c8bf7202d88eca9ffff025 (git tree object for v2) │   ├── 29 │   │   └── ef827e8a45b1039d908884aae4490157bcb2b4 (git blob object for v3) │   ├── 62 │   │   └── 6799f0f85326a8c1fc522db584e86cdfccd51f (git blob object for v1) │   ├── 8c │   │   └── 1384d825dbbe41309b7dc18ee7991a9085c46e (git blob object for v2) │   ├── 9a │   │   └── 8fa1eee2b0d2841ffa1e5515935421c3d419e1 (git commit object for v2) │   ├── a7 │   │   └── 949a02518883287c308f0b47e2a4934b111cc3 (git tree object for v3) │   ├── cc │   │   └── 5fda52eb3ed07cce6357ac11e392cd2dbf6d16 (git tree object for v1) │   ├── d0 │   │   └── 769a6fa5bcf4c05f667eb635dd84c1174be895 (git commit object for v3)
│   ├── info │   └── pack └── refs ├── heads
│   └── master └── tags 21 directories, 31 files


Check more info.


    $ cat .git/HEAD
ref: refs/heads/master

$ cat .git/refs/heads/master
d0769a6fa5bcf4c05f667eb635dd84c1174be895

$ git ls-files -s
100644 29ef827e8a45b1039d908884aae4490157bcb2b4 0 file.txt (v3 version)

$ git log --oneline --decorate --graph --all
* d0769a6 (HEAD -> master) v3 * 9a8fa1e v2 * 1491536 v1


Step 2:


Run the 'git reset --mixed HEAD~' command to move the current branch pointer to its previous commit, and also reset the Index to its previous commit.


    $ git reset --mixed HEAD~
Unstaged changes after reset: M file.txt


Check the git status.


    $ git status
On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: file.txt
no changes added to commit (use "git add" and/or "git commit -a")


Only the working directory still keeps the v3 version of file.txt.

Both the HEAD pointer and the Index track the file.txt in the v2 version.



Check the .git tree structure.

Only a new file ORIG_HEAD was created.


    $ tree .git/
.git/ ├── COMMIT_EDITMSG ├── HEAD 
├── ORIG_HEAD
├── branches ├── config ├── description ├── hooks │   ├── applypatch-msg.sample │   ├── commit-msg.sample │   ├── fsmonitor-watchman.sample │   ├── post-update.sample │   ├── pre-applypatch.sample │   ├── pre-commit.sample │   ├── pre-merge-commit.sample │   ├── pre-push.sample │   ├── pre-rebase.sample │   ├── pre-receive.sample │   ├── prepare-commit-msg.sample │   ├── push-to-checkout.sample │   └── update.sample ├── index ├── info │   └── exclude ├── logs │   ├── HEAD │   └── refs │   └── heads
│   └── master ├── objects
│   ├── 14 │   │   └── 91536a26a35b6a0037cfa9ccbac70fecdb77d0 (git commit object for v1) │   ├── 25 │   │   └── 7330bfc3b1cce445c8bf7202d88eca9ffff025 (git tree object for v2) │   ├── 29 │   │   └── ef827e8a45b1039d908884aae4490157bcb2b4 (git blob object for v3) │   ├── 62 │   │   └── 6799f0f85326a8c1fc522db584e86cdfccd51f (git blob object for v1) │   ├── 8c │   │   └── 1384d825dbbe41309b7dc18ee7991a9085c46e (git blob object for v2) │   ├── 9a │   │   └── 8fa1eee2b0d2841ffa1e5515935421c3d419e1 (git commit object for v2) │   ├── a7 │   │   └── 949a02518883287c308f0b47e2a4934b111cc3 (git tree object for v3) │   ├── cc │   │   └── 5fda52eb3ed07cce6357ac11e392cd2dbf6d16 (git tree object for v1) │   ├── d0 │   │   └── 769a6fa5bcf4c05f667eb635dd84c1174be895 (git commit object for v3)
│   ├── info │   └── pack └── refs ├── heads
│   └── master └── tags 21 directories, 32 files


Check more info.

The current branch points to its previous commit v2, not v3 anymore.

And the index points to v2 git blob object, not the v3 git blob object.


    $ cat .git/HEAD
ref: refs/heads/master

    $ cat .git/ORIG_HEAD
d0769a6fa5bcf4c05f667eb635dd84c1174be895 (this is git commit object for v3)

$ cat .git/refs/heads/master
9a8fa1eee2b0d2841ffa1e5515935421c3d419e1 (this is git commit object for v2)

$ git ls-files -s
100644 8c1384d825dbbe41309b7dc18ee7991a9085c46e 0 file.txt (v2 version)

$ git log --oneline --decorate --graph --all
* 9a8fa1e (HEAD -> master) v2 * 1491536 v1


After running the 'git reset --mixed [commit]' command, we revert the commands from


    $ echo 'v3' > file.txt
$ git add .
$ git commit -m 'v3'
[master d0769a6] v3 1 file changed, 1 insertion(+), 1 deletion(-)

to


    $ echo 'v3' > file.txt