Git基礎知識之內部狀態管理系統

coffee_tea_or_me發表於2021-03-30

本文主要來介紹一下 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)。部落格園程式碼顯示系統太垃圾了,這時的 reset_lifecycle_file 應該是紅色的,表示還沒有被跟蹤。

3. Staging Index

$ git add reset_lifecycle_file 

$ git status
位於分支 master
尚無提交
要提交的變更:
  (使用 "git rm --cached <檔案>..." 以取消暫存)
        新檔案:   reset_lifecycle_file

所有變動的檔案,Git 都記錄在一個區域,叫做"暫存區"(Staging index)。我們通過 git add 指令將工作區中的內容儲存到暫存區,這時已經實現了對檔案的跟蹤,但還沒有請求提交。這時候的檔案已經被跟蹤了,reset_lifecycle_file 應該是綠色的。

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 到遠端倉庫的狀態返回到暫存區狀態。此時的gitadd_test_file綠色

$ git reset --soft 88b538
$ git status
位於分支 master
要提交的變更:
  (使用 "git restore --staged <檔案>..." 以取消暫存)
        新檔案:   gitadd_test_file

如上結果所示,這時已經處於 git commit 命令之前的狀態,達到此結果使用的是 git reset --soft 指令。
該操作會保留檔案的改動及索引狀態,撤銷完成後將回到新增改動的狀態。注意與接下來要使用的 git reset --hard 之間的區別。此時的gitadd_test_file綠色

$ git restore --staged gitadd_test_file 
$ git status
位於分支 master
未跟蹤的檔案:
  (使用 "git add <檔案>..." 以包含要提交的內容)
        gitadd_test_file

提交為空,但是存在尚未跟蹤的檔案(使用 "git add" 建立跟蹤)

通過 git restore --staged 指令,我們得以將暫存區狀態返回到工作區狀態,也就是 git add 之前的狀態。此時的gitadd_test_file紅色

$ 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)。轉載請註明出處!
限於本人水平,如果文章和程式碼有表述不當之處,還請不吝賜教。

感謝您的支援

¥ 打賞

Git基礎知識之內部狀態管理系統

微信支付

相關文章