從今天開始,一連三天,我們將快速複習 git 上層的「瓷器(porcelain)」指令,日後再一一拆解每個步驟,仔細觀察下完這些指令之後,git 內部發生哪些變化。
指令如下:
mkdir code
(創建一個名為 code 的資料夾)cd code
(進到 code 資料夾裡面)git init
(初始化 git 資料夾)這時終端機會顯示 git 倉儲已經被初始化,我們得以在裡面進行各種 git 的操作。
因為目前 git 主分支名稱已從 master
改 main
,若預設的分支仍顯示 master
,我自己會用 git branch -m master main
指令改成 main
。
Commit(git 官方譯名為「提交」)是一個版本的快照(snapshot),而在檔案透過 git commit
指令形成 commit 前,會先從我們編輯檔案的「工作目錄(working directory)」經 git add
指令先進入預存區(staging area):
現在讓我們以 touch
指令在剛剛創建的 git 資料夾新建一個檔案:
touch hello_world.txt
接著以 git add
指令把 hello_world.txt
放到預存區:
git add hello_world.txt
這時可以用 git status
檢查,可發現 hello_world.txt
變成綠色,代表該檔案已被放進預存區:
接著以 git commit
指令形成一組快照,commit 訊息為 "initial commit"
:
git commit -m "initial commit"
圖示如下,可發現建立了一個雜湊碼為 510100a...
的 commit:
日後也可以透過 git log
或 git log --oneline
觀察 commit 的歷程紀錄:
假設發現有 commit 做錯了,想要退版,可以用 git reset
或 git revert
處理,但兩者的效果並不相同。
現在我們先用 touch
再建立一個檔案(假設為 wrong_file.txt
),經 git add
與 git commit
形成第二個版本:
現在用 git log --oneline
可發現共有兩個 commit:
但 9f40842...
這個 commit 是錯的,我們想要退回 510100a...
的狀態,可以用以下指令:
git reset 510100a
就可以發現 510100a...
這個 commit 消失、在此 commit 才被加進去的檔案 wrong_file.txt
也被退出預存區,不過透過 ls
檢查會發現還在工作目錄:
如果使用 git revert
指令,則會產生新的 commit 回到先前狀態如下:
現在多了一個雜湊碼為 3b3082b...
的 commit,但跟剛剛 git reset
不同的是,若以 ls
檢查,wrong_file.txt
已經不在工作目錄了。
為什麼會有這樣的差別?待我們細看這些指令與其變形在 ./git
資料夾造成的變化,將能從 git 內部的運作機制一窺究竟。
使用上層的瓷器指令要將檔案加入或移出 commit 時,主要有下列四者:
git add
:把檔案從工作目錄放到預存區。git commit
:把預存區檔案放到 .git/
倉儲,形成一筆 commit 快照。git reset
:退回前面的 commit,把原新 commit 才出現的變化移出預存區,工作目錄不影響。git revert
:產生新 commit 變成欲退回原 commit 的狀態,工作目錄也會連帶影響。