Git 之 reset 命令解析

1、master 分支

    咱們知道git在初始化時,會爲咱們默認建立一個master分支,那這個master究竟是什麼呢?其實它在.git目錄下對應了一個引用文件-----.git/refs/heads/master文件,而該文件的內容即是該分支中最新的一次提交的ID:git

$ cat .git/refs/heads/master
22f8aae534916e1174711f138573acfbb47e489c

$ git cat-file -t 22f8aae
commit

$ git log --oneline
22f8aae git ignore file added.
4e79a0b Rename third to third.txt
46ae7e3 remove branch_first.txt file from master branch
55d1e70 branch first file
545a382 Merge commit '35bbd32'

   當咱們用以上查看master文件內容時,發現它果真記錄了最新一次的提交。瞭解了這個前提,那咱們來分析下git reset到底作了什麼?shell

2、reset命令

    以上面的例子爲基礎咱們來探討reset命令的魔力,首先咱們來執行一個reset命令,reset到上一次提交3d

$ git reset --hard HEAD^
HEAD is now at 4e79a0b Rename third to third.txt

Quadrangle@QUADRANGLE-PC /d/GitRepo/GitOne (master)
$ git log --oneline
4e79a0b Rename third to third.txt
46ae7e3 remove branch_first.txt file from master branch
55d1e70 branch first file
545a382 Merge commit '35bbd32'

   HEAD^的意思就是最新一次提交的父提交,reset後,咱們看一下提交日誌,發現最新一次提交沒了。到底git作了什麼呢?咱們還能找回最新的一次提交嗎?日誌

    回答上面兩個問題,就用到上面就到的master引用文件了,這是咱們再看一下這個文件的內容有什麼變化?code

$ cat .git/refs/heads/master
4e79a0ba92f1ae63dc661e29343fa0c369ca480d

   發現了吧,裏面記錄了reset後的最後一次提交。這時或許咱們有所覺察了。先不急着下結論,咱們看怎麼回到最新的提交呢?其實reset後,git沒有刪除最新提交的相關信息,包括目錄樹,所以只要咱們記住提交ID,即可以從新reset回來:圖片

$ git reset --hard 22f8aae
HEAD is now at 22f8aae git ignore file added.

$ git log --oneline
22f8aae git ignore file added.
4e79a0b Rename third to third.txt
46ae7e3 remove branch_first.txt file from master branch
55d1e70 branch first file
545a382 Merge commit '35bbd32'

   這樣查看log,發現最新提交又回來了。可是若是咱們忘了最新提交ID 怎麼辦呢?好辦,reflog命令能夠最總引用變動的記錄:rem

Quadrangle@QUADRANGLE-PC /d/GitRepo/GitOne (master)
$ git reflog
22f8aae HEAD@{0}: reset: moving to 22f8aae
4e79a0b HEAD@{1}: reset: moving to HEAD^
22f8aae HEAD@{2}: reset: moving to 22f8aae
4e79a0b HEAD@{3}: reset: moving to HEAD^

   咱們能夠找到前面任意操做的記錄,而且能夠reset到任意提交。it

3、揭祕

    以前咱們看到了reset後master文件的內容發生了變化,其實這就是reset命令的本質,但結合不一樣的參數,會有額外的工做:如--hard --soft --mixed等,他們決定了是否重置暫存區或工做區。ast

咱們來看下面圖片class

其實reset命令有兩種用法:

  1. git reset [-q] [commit] [--] <paths>

  2. git reset [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]

第一種用法是不會重置引用的,即不會修改master文件。只是用某一次提交的文件提交暫存區的文件

第二種用法不使用<paths> 則會重置引用,而且參數不一樣決定是否覆蓋暫存區和工做區:

  • --hard參數會執行途中1,2,3 所有動做,即暫存區,工做區所有用指定提交版本的目錄樹替換掉

  • --soft 參數只執行1, 不進行暫存區和工做區的覆蓋

  • --mixed或不使用參數,執行1,2覆蓋暫存區,但不覆蓋工做區


這樣一來相信對reset的理解會用更深入的理解了吧。


4、參考

    圖片來源:機械工業出版社,蔣鑫 《Git權威指南》

相關文章
相關標籤/搜索