本文主要來介紹一下 Git 的內部狀態管理系統。它利用基於節點和指針的數據結構來跟蹤及管理編輯操作的時間線。
對本地項目而言,任一時刻,Git 處於三種狀態中的一種:工作區狀態、暫存區狀態和提交區狀態。
下面利用新建項目來演示一下不同狀態及其轉換。
1. Initialize the project
$ mkdir git_tree_test && cd git_tree_test
$ git init
提示:使用 'master' 作為初始分支的名稱。這個默認分支名稱可能會更改。要在新倉庫中
提示:配置使用初始分支名,並消除這條警告,請執行:
提示:
提示: git config --global init.defaultBranch <名稱>
提示:
提示:除了 'master' 之外,通常選定的名字有 'main'、'trunk' 和 'development'。
提示:可以通過以下命令重命名剛創建的分支:
提示:
提示: git branch -m <name>
已初始化空的 Git 倉庫於 /Users/phillee/git_tree_test/.git/
$ git status
位於分支 master
尚無提交
無文件要提交(創建/拷貝文件並使用 "git add" 建立跟蹤)
這時我們初始化了一個本地項目,默認創建 master 分支,尚無文件跟蹤及提交。
2. The Working Directory
$ touch reset_lifecycle_file
$ git status
位於分支 master
尚無提交
未跟蹤的文件:
(使用 "git add <文件>..." 以包含要提交的內容)
reset_lifecycle_file
提交為空,但是存在尚未跟蹤的文件(使用 "git add" 建立跟蹤)
現在我們為項目新增了文件 reset_lifecycle_file ,尚未提交,當前位於工作區(Working directory)。博客園代碼顯示系統太垃圾了,這時的
3. Staging Index
$ git add reset_lifecycle_file
$ git status
位於分支 master
尚無提交
要提交的變更:
(使用 "git rm --cached <文件>..." 以取消暫存)
新文件: reset_lifecycle_file
所有變動的文件,Git 都記錄在一個區域,叫做"暫存區"(Staging index)。我們通過 git add
指令將工作區中的內容保存到暫存區,這時已經實現了對文件的跟蹤,但還沒有請求提交。這時候的文件已經被跟蹤了,
4. Commit History
$ git commit -m "init commit"
[master(根提交) 88b5382] init commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 reset_lifecycle_file
$ git status
位於分支 master
無文件要提交,干凈的工作區
暫存區保留變動的文件信息,等到修改結束添加到"提交歷史"(Commit history)中,這就相當於當前項目的一個快照(snapshot)。
項目提交歷史就是由不同時間的快照構成。Git 可以根據此提交信息將項目恢復到任意一個快照狀態。
5. Reverse state switching
前面敘述並展示了三種狀態之間的前向轉換,現在我們反過來看一下,如何將當前狀態轉換成其父狀態。
$ touch gitadd_test_file
$ vim gitadd_test_file
新建一個測試文件並利用該文件進行不同狀態之間轉換的實驗。
- 按
i
鍵進入編輯模式; - 鍵入
Hello world!
; - 按
esc
退出編輯模式; shift+;
進入命令編輯模式;- 鍵入
x
回車即可保存到文件並退出vim
。
$ git status
位於分支 master
未跟蹤的文件:
(使用 "git add <文件>..." 以包含要提交的內容)
gitadd_test_file
提交為空,但是存在尚未跟蹤的文件(使用 "git add" 建立跟蹤)
$ git add gitadd_test_file
$ git commit -m "add one file for test"
[master d97ee77] add one file for test
1 file changed, 1 insertion(+)
create mode 100644 gitadd_test_file
$ git log --oneline
d97ee77 (HEAD -> master) add one file for test
88b5382 init commit
按步驟2-4的方式將新創建的文件添加到提交歷史中。現在我們嘗試將已經提交 commit
但尚未 push
到遠端倉庫的狀態返回到暫存區狀態。此時的
$ git reset --soft 88b538
$ git status
位於分支 master
要提交的變更:
(使用 "git restore --staged <文件>..." 以取消暫存)
新文件: gitadd_test_file
如上結果所示,這時已經處於 git commit
命令之前的狀態,達到此結果使用的是 git reset --soft
指令。
該操作會保留文件的改動及索引狀態,撤銷完成后將回到添加改動的狀態。注意與接下來要使用的 git reset --hard
之間的區別。此時的
$ git restore --staged gitadd_test_file
$ git status
位於分支 master
未跟蹤的文件:
(使用 "git add <文件>..." 以包含要提交的內容)
gitadd_test_file
提交為空,但是存在尚未跟蹤的文件(使用 "git add" 建立跟蹤)
通過 git restore --staged
指令,我們得以將暫存區狀態返回到工作區狀態,也就是 git add
之前的狀態。此時的
$ git add gitadd_test_file
$ git commit -m "add test file for git add test"
[master d535a57] add test file for git add test
1 file changed, 1 insertion(+)
create mode 100644 gitadd_test_file
$ git log --oneline
d535a57 (HEAD -> master) add test file for git add test
88b5382 init commit
$ git reset --hard 88b538
HEAD 現在位於 88b5382 init commit
$ git status
位於分支 master
無文件要提交,干凈的工作區
注意這里是將 gitadd_test_file
重新添加到暫存區,然后保存到提交歷史中。從提交歷史中的狀態直接返回到 git add
之前的狀態使用的指令是 git reset --hard
,該指令強制將 HEAD
指針指向提交歷史線中的前一個提交狀態,會連同我們剛才新建的文件一起全部撤銷。這是一個比較危險的舉動,使用的時候要注意場合。當然即使這么操作了也並非就不能復原了,只是會多幾步操作而已。
(全文完)
本文作者 :phillee
發表日期 :2021年3月30日
本文鏈接 :https://www.cnblogs.com/phillee/p/14598437.html
版權聲明 :自由轉載-非商用-非衍生-保持署名(創意共享3.0許可協議/CC BY-NC-SA 3.0)。轉載請注明出處!
限於本人水平,如果文章和代碼有表述不當之處,還請不吝賜教。
感謝您的支持
微信支付