本文將會介紹 GIT 中 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 到該支點上。
這邊就不對 add 與 commit 多做介紹。
而 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 的內容移出。
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 了,所以使用時請三思。
詳細可參考 Difference between "git checkout <filename>" and "git checkout -- <filename>" - Stack Overflow
參考資料