Git 是分散式版本控制系統的代表,理解其核心概念是高效使用的基礎。本章涵蓋 Git 的三區模型、物件儲存機制、分支管理以及常見操作。
一、Git 三區模型#
Git 的工作流程圍繞三個核心區域運作:
工作區 (Working Directory)
↓ git add
暫存區 (Staging Area / Index)
↓ git commit
版本庫 (Repository / .git)工作區(Working Directory)#
你實際編輯檔案的地方,所有的修改都從這裡開始。
暫存區(Staging Area)#
暫存區是 Git 最具特色的設計。它提供了「緩衝」與「組織」變更的空間:
- 方案試錯:嘗試某種修改但未確定時,可先暫存。若後續方案不如預期,可用暫存區內容覆蓋回來。
- 原子化提交:若同時修改五個檔案但屬於兩個功能,可分批暫存並分開提交,保持版本歷史清晰。
版本庫(Repository)#
位於 .git 目錄中,儲存所有版本歷史與元資料。
二、基本操作#
建立倉庫#
# 在既有專案中初始化
cd my-project
git init
# 建立新專案
git init my-new-project組態使用者資訊#
# 全域設定
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
# 倉庫級設定(優先於全域)
git config user.name "Work Name"
git config user.email "work@company.com"當同時存在 global 與 local 設定時,Git 優先採用當前倉庫(local)的設定。這對於區分公司與個人專案的身份非常實用。
標準工作流程#
# 1. 查看狀態
git status
# 2. 將檔案加入暫存區
git add <file> # 單一檔案
git add . # 所有變更
git add -u # 僅已追蹤的檔案
# 3. 提交變更
git commit -m "描述這次變更"
# 4. 查看歷史
git log
git log --oneline --graph直接在工作目錄新增檔案後立刻
git commit不會成功,因為檔案未加入暫存區。請先git add再提交。
三、Git 物件模型#
Git 使用三種核心物件來管理版本:
Commit(提交物件)#
- 每次
git commit產生一個 commit 物件 - 包含作者資訊、提交訊息、時間戳
- 每個 commit 必定對應一棵 tree
Tree(樹物件)#
- 代表該次提交的檔案系統快照
- 記錄目錄結構、檔名與權限
- 可巢狀包含子樹(子目錄)或 blob(檔案)
Blob(檔案內容物件)#
- 儲存檔案的純內容(不含檔名)
- Git 以內容雜湊識別,相同內容只存一份
commit
└── tree (根目錄)
├── tree (子目錄)
│ └── blob (檔案內容)
└── blob (檔案內容)Git 的「內容可尋址」設計帶來高效儲存:相同內容的檔案無論檔名如何,只儲存一份 blob。
檢視物件內容#
# 查看物件類型
git cat-file -t <hash>
# 查看物件內容
git cat-file -p <hash>四、分支管理#
分支基本操作#
# 查看分支
git branch
# 建立分支
git branch <branch-name>
# 切換分支
git checkout <branch-name>
git switch <branch-name> # Git 2.23+ 推薦
# 建立並切換
git checkout -b <branch-name>
git switch -c <branch-name>
# 刪除分支
git branch -d <branch-name> # 安全刪除(已合併)
git branch -D <branch-name> # 強制刪除HEAD 指標#
HEAD 是指向當前工作位置的指標:
- 正常狀態:HEAD → 分支 → Commit
- 分離頭指標(Detached HEAD):HEAD 直接指向 Commit
在分離頭指標狀態下產生的 Commit,若沒有建立分支保存,切換離開後可能會遺失。
相對引用#
HEAD^ # 父節點(上一版)
HEAD^^ # 祖父節點(上上一版)
HEAD~n # 前 n 代祖先
# 範例:比較當前與前兩個版本的差異
git diff HEAD HEAD~2五、合併策略#
Merge(合併)#
# 將 feature 分支合併到當前分支
git merge feature產生一個合併節點,保留完整的分支歷史。
Rebase(變基)#
# 將當前分支變基到 main
git rebase main將提交「重新播放」到目標分支上,產生線性歷史。
選擇建議:
- 公共分支使用 Merge,保留歷史脈絡
- 個人分支使用 Rebase,保持歷史整潔
- 已推送到遠端的提交,避免 Rebase
六、衝突解決#
當兩個分支修改同一檔案的同一區域時,Git 無法自動合併:
# 嘗試合併
git merge feature-branch
# 發生衝突
CONFLICT (content): Merge conflict in file.txt衝突標記#
<<<<<<< HEAD
你的修改
=======
對方的修改
>>>>>>> feature-branch解決步驟#
- 開啟衝突檔案,決定保留哪些內容
- 刪除衝突標記(
<<<<<<<、=======、>>>>>>>) - 儲存檔案
- 標記為已解決並提交
git add <resolved-file>
git commit -m "resolved conflict"如果解決過程中發現搞砸了,可以放棄這次合併:
git merge --abort
七、版本回退#
git reset#
將分支指標移動到指定 commit,可選擇保留或捨棄變更:
# 軟重置:保留工作區與暫存區
git reset --soft <commit>
# 混合重置(預設):保留工作區,清空暫存區
git reset <commit>
git reset HEAD # 取消所有暫存
# 硬重置:捨棄所有變更
git reset --hard <commit>
git reset --hard是破壞性指令,會徹底丟失目標 commit 之後的所有變更。請確認不需要這些變更才使用。
git revert#
建立一個新的 commit 來「反轉」指定 commit 的變更:
git revert <commit>reset vs revert:
reset:修改歷史,適用於本地未推送的 commitrevert:新增歷史,適用於已推送的 commit
八、暫存工作(Stash)#
當需要臨時切換分支但當前工作未完成時:
# 暫存當前工作
git stash
# 查看暫存列表
git stash list
# 恢復工作(並刪除暫存)
git stash pop
# 恢復工作(保留暫存)
git stash applyPop vs Apply:
- 確定恢復後不再需要備份,使用
pop- 不確定是否會有衝突,或想應用到多個分支,使用
apply
九、.gitignore 組態#
定義哪些檔案應該被 Git 忽略:
# 忽略編譯產物
*.class
*.o
target/
# 忽略日誌
*.log
logs/
# 忽略環境組態
.env
.env.local
# 忽略 IDE 設定
.idea/
.vscode/
# 忽略系統檔案
.DS_Store
Thumbs.db路徑結尾斜槓的影響:
doc/(加斜槓):僅匹配目錄doc(不加斜槓):同時匹配檔案與目錄
取得範本#
GitHub 維護了各種語言的標準 .gitignore 範本:
- 在 GitHub 搜尋
gitignore專案 - 找到對應語言(如 Java、Node)
- 複製到專案中並依需求調整
十、修改歷史#
修改最近一次 Commit#
# 修改訊息
git commit --amend -m "新的訊息"
# 修改內容(先 add 新變更)
git add <file>
git commit --amend修改歷史中的 Commit#
使用互動式 rebase:
# 選擇要修改的 commit 的父節點
git rebase -i <parent-commit>在編輯器中,將 pick 改為:
reword(r):修改訊息squash(s):合併到前一個 commitedit(e):修改內容
已推送到遠端的 commit,請勿使用
--amend或rebase修改歷史。這會改變 commit hash,造成團隊協作問題。
合併多個 Commit (Squash)
將最近 4 個 commit 合併為一個:
# 找到第 5 個 commit 作為 base
git rebase -i HEAD~4在編輯器中:
pick abc1234 第一個 commit
squash def5678 第二個 commit
squash ghi9012 第三個 commit
squash jkl3456 第四個 commit儲存後,再編輯合併後的 commit 訊息。
常用指令速查#
| 操作 | 指令 |
|---|---|
| 初始化倉庫 | git init |
| 查看狀態 | git status |
| 加入暫存區 | git add <file> |
| 提交變更 | git commit -m "message" |
| 查看歷史 | git log --oneline --graph |
| 建立分支 | git branch <name> |
| 切換分支 | git switch <name> |
| 合併分支 | git merge <name> |
| 暫存工作 | git stash |
| 取消暫存 | git reset HEAD <file> |
| 捨棄修改 | git checkout -- <file> |
| 版本回退 | git reset --hard <commit> |