本文將會介紹 reset 與 checkout 的運作方式與差別。
在開始前需要了結的 Git 小觀念。
Git 小觀念
HEAD
Role: Last commit snapshot, next parent
一般指向一個 Branch
的最新一個 Commit
,也是使用者目前所能看到的 Git 內容。
新增的 Commit
必定接在目前 HEAD 後面。
Index
Role: Proposed next commit snapshot
又稱為 Staging area
暫存區,算是 Commit
前的過渡區,告知 Git 哪些檔案需要包含在此次 Commit
內。
Working Directory
Role: Sandbox
對目前內容 HEAD
進行的修改,都會存放在此沙盒中。
了解 GIT 這三個部分後,在 GIT 建立支點過程中,首先我們會在 Working Directory
中進行文件的新增、編輯或刪除,之後在需要納入此次支點的文件 add
,使沙盒中的修改進入到暫存區中,再透過 commit
指令使在暫存區的內容全部包含在一個新的支點,然後移動 HEAD
到該支點上。
而 Reset
與 Checkout
則可以幫助我們移動 HEAD
、將暫存區的內容移出等等。
Reset
移動 HEAD
指向的 Branch
,有三種模式可以使用。
Soft
reset --soft [commit]
單純移動 HEAD
與其 Branch
。
Mixed (預設指令)
reset [commit]
除了移動 HEAD
與其 Branch
外,也將 Index
的內容移出。
Hard
reset --hard [commit]
除了移動 HEAD
與其 Branch
外,也將 Working Directory
與 Index
的內容移出。
如果不加任何的 CommitID 則會以 HEAD 為移動的目的地。
Checkout
checkout <commit>
checkout is working-directory safe - it will check to make sure it’s not blowing away files that have changes to them.
也就是說在進行 checkout
時,會檢查你的沙盒是否有更改,如果有且此更改會因為 checkout
而失去,便會阻止你。
checkout
移動的是 HEAD
本身,並不會連其 Branch
一起移動,一般使用在切換分支。
雖然使用上看起來像 reset --hard
,但 reset --hard
並不會檢查你的沙盒並且會移動你的分支。
對檔案進行操作
兩者皆可以針對單一檔案進行內容移動。
reset [commit] <paths>
git reset -- xxx.html
將 xxx.html
的 Index
的內容移出。
checkout [commit] <paths>
git checkout -- xxx.html
將 xxx.html
的 Working Directory
與 Index
的內容移出。
checkout
如上所說如同 reset --hard
,但在進行檔案操作時,就不是 working-directory
safe 了,所以使用時請三思。
對 file 操作時,無論是 reset 或者 checkout 建議在檔案名稱前面加上--
來標示
詳細可參考 Difference between “git checkout
參考資料
Git - Reset Demystified
【狀況題】剛才的 Commit 後悔了,想要拆掉重做… - 為你自己學 Git 高見龍