Git背後的三個文件集合
Git默認有三個文件集合,第一個是工作目錄。也就是我們能看到的本地文件夾。第二個是索引(index)指向的緩衝區。第三個是HEAD指針指向的上一次成功commit後的文件集合狀態。具體如下表:
一切在本地的針對Git的操作,都是在這三個文件集合間發生的。工作流程如下
為了完全展示reset的功能,新建立一個空的倉庫作為示例
執行git init命令
$ git init
Initialized empty Git repository in C:/study/gitee/ResetTestRepository/.git/
確認狀態
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
添加一個文件file.txt,此時的三個文件及和的狀態如下
執行add命令,將file.txt文件添加到緩存區
$ git add file.txt
確認狀態
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage) /<file>
new file: file.txt
此時文件集合狀態如下
執行commit命令,提交文件
$ git commit file.txt -m "1st commit"
[master (root-commit) 8547f17] 1st commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file.txt
確認狀態
$ git status
On branch master
nothing to commit, working tree clean
文件集合狀態,8547f是第一次提交的SHA-1編碼
修改工作目錄的file.txt文件,看作v2版本
確認狀態
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed) /<file>
(use "git checkout -- <file>..." to discard changes in working directory) /<file>
modified: file.txt
no changes added to commit (use "git add" and/or "git commit -a")
再次添加進緩存
$ git add file.txt
確認狀態
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage) /<file>
modified: file.txt
文件集合
提交
$ git commit file.txt -m "2nd commit"
[master 86f4c3b] 2nd commit
1 file changed, 1 insertion(+)
確認狀態
$ git status
On branch master
nothing to commit, working tree clean
86f4c是第二次提交的SHA-1編碼
重複上述步驟,進行3次提交。之後的文件結合狀態如下
確認一下提交的狀態可知,現在HEAD指向了最新的提交
$ git log --oneline
0606a6e (HEAD -> master) 3rd commit
86f4c3b 2nd commit
8547f17 1st commit
到此位置,準備工作已經做完了。
第一步,移動HEAD指針
reset 命令所作的第一步是移動HEAD指針。和checkout命令不同,checkout命令是將HEAD指針移動到其他分支上。而reset是將HEAD指針移動到統一分支的其他版本上。
$ git reset --soft HEAD~
這裡的~表示上一個版本。如果想直接reset到其他版本可以使用SHA-1編碼
確認一下提交的狀態, 發現HEAD指向了第二次提交
$ git log --oneline
86f4c3b (HEAD -> master) 2nd commit
8547f17 1st commit
此時的文件集合
本質上,這個命令是撤銷了第三次提交。
第二步,更新索引
第一步執行之後,緩存區保存的信息還是第三次提交的。如果想把HEAD指針,和緩存區(索引)也返回到第二次提交的狀態可以使用如下命令
$ git reset HEAD~
Unstaged changes after reset:
M file.txt
執行之後,提示有一個文件沒有被add進緩存。
此時的文件集合
第三部,更新工作目錄
如果想把工作目錄也返回到第二次時的狀態,則需要使用如下命令。
$ git reset --hard HEAD~
HEAD is now at 86f4c3b 2nd commit
回顧
- 若指定了 --soft,則執行上述第一步
- 若指定了 --mixed或者不指定參數,則執行上述第一步和第二步
- 若指定了 --hard或者不指定參數,則執行上述三步都會被執行
帶有路徑的重置
reset也支持重置某一個文件或者目錄,可以使用如下命令
$ git reset 8547f17 -- file.txt
Unstaged changes after reset:
M file.txt
執行了這個命令,其實是從之前成功提交的版本中,將這個文件取回到了緩存區。這個命令和add命令正好是相反的。
reset某個文件之後,可以直接執行commit命令使其反映到最新的HEAD中。
合併提交
想把多次提交合併為一次提交,可以使用如下的命令組合。比如這時我添加了file2.txt文件,並且作為第五次提交。這時想把從第三次提交到第五次提交合併為一個新的提交
$ git reset --soft 86f4c3b
$ git commit -m "6th commit"
[master 376f50d] 6th commit
2 files changed, 1 deletion(-)
create mode 100644 file2.txt
確認狀態發現,第三次到第五次已經全都默認刪除了,只保留了合併後的第六次提交。
$ git log --oneline
376f50d (HEAD -> master) 6th commit
86f4c3b 2nd commit
8547f17 1st commit
閱讀更多 一個經驗用十年的碼農 的文章