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


本文主要來介紹一下 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)。轉載請注明出處!
限於本人水平,如果文章和代碼有表述不當之處,還請不吝賜教。

感謝您的支持

¥ 打賞

微信支付


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM