第 01 章

Repository 概念與原理

在學任何 Git 指令之前,先搞清楚「Repository」到底是什麼——它不只是一個資料夾,而是 Git 記錄所有版本歷史的核心資料庫。

為什麼需要版本控制?

想像你正在寫一份報告,你可能會這樣做:

報告_v1.docx 報告_v2_修正.docx 報告_v3_老師回饋.docx 報告_final.docx 報告_final_真的最終版.docx 報告_final_final_交出去的.docx

這種「手動版本管理」有幾個致命問題:

❌ 無法追蹤差異

你無法快速知道 v2 和 v3 之間到底改了哪幾行。

❌ 無法安全回溯

刪錯東西後,如果沒有備份就永遠找不回來。

❌ 無法多人協作

兩個人同時修改同一份檔案時,誰的版本為準?

版本控制系統(VCS, Version Control System)就是為了解決這些問題而誕生的工具。Git 是目前最流行的分散式版本控制系統,由 Linux 之父 Linus Torvalds 在 2005 年開發。

Repository 的定義與用途

Repository(版本庫,簡稱 Repo)是 Git 用來儲存專案所有檔案與版本歷史的地方。一個 Repo 包含:

工作目錄 Working Directory

你實際看到、編輯的檔案所在的資料夾。這是你日常操作的地方。

.git 目錄

隱藏在專案根目錄下的資料夾,存放了 Git 的所有版本資料、設定與物件資料庫。這才是 Repo 的「本體」。

flowchart TB subgraph "你的專案資料夾 (my-project/)" WD["📁 工作目錄
index.html
style.css
app.js"] GIT["📁 .git/
(版本庫本體)
objects/
refs/
HEAD"] end WD -.- GIT style GIT fill:#fde8e4,stroke:#f05033
關鍵觀念:如果你刪除了 .git 資料夾,所有的版本歷史都會消失,但工作目錄中的檔案不會受影響。反過來說,只要 .git 還在,你就能還原任何一個歷史版本。

Git 的物件資料庫

Git 在 .git/objects/ 中儲存了所有版本資料。這個資料庫由三種基本物件組成:

Blob 物件

儲存單一檔案的內容(不含檔名)。每個不同版本的檔案內容都會產生一個新的 blob。

檔案內容 二進位儲存

Tree 物件

類似資料夾,記錄了檔名與對應的 blob 或子 tree 的關聯。一個 tree 代表某一時刻的目錄結構。

目錄結構 檔名對應

Commit 物件

記錄一次提交,指向一個 tree(專案快照)、作者資訊、時間戳記與提交訊息,以及父 commit 的指標。

版本快照 歷史鏈結

物件之間的關係

flowchart TD C1["Commit c3a2f...
author: Alice
date: 2026-03-19
message: 'init project'"] --> T1["Tree a1b2c..."] T1 --> B1["Blob e4f5g...
index.html 的內容"] T1 --> B2["Blob h6i7j...
style.css 的內容"] T1 --> T2["Tree k8l9m...
(子目錄 src/)"] T2 --> B3["Blob n0o1p...
app.js 的內容"]

SHA-1 雜湊與物件 ID

Git 中的每一個物件都有一個唯一的身份標識——SHA-1 雜湊值,這是一個 40 字元的十六進位字串。

SHA-1 如何產生?

Git 會對物件的「類型 + 大小 + 內容」進行 SHA-1 雜湊運算。

flowchart LR A["檔案內容
'hello world'"] --> B["SHA-1 運算"] B --> C["95d09f2b10...
(40字元)"]

相同的內容永遠產生相同的雜湊值;內容只要差一個字元,雜湊值就完全不同。

你可以用以下指令驗證 Git 的雜湊運算:

$ echo "hello world" | git hash-object --stdin
95d09f2b10159347eece71399a7e2e907ea3df4f

$ echo "hello world!" | git hash-object --stdin
cd0875583aabe89ee197ea133980a9085d08e497

只多了一個驚嘆號,雜湊值就完全改變了。

為什麼用 SHA-1?

  • 唯一性:不同的內容幾乎不可能產生相同的雜湊值(碰撞機率極低)。
  • 完整性:如果檔案被竄改,雜湊值會改變,Git 馬上就能偵測到。
  • 效率:只需比對 40 字元的字串,就能判斷兩個物件是否相同。
補充:在日常使用中,你通常只需要看 SHA-1 的前 7 個字元(短 ID),例如 c3a2f1b,Git 會自動找到對應的完整 ID。

Index(暫存區 / Staging Area)

在工作目錄和版本庫之間,Git 還有一個中間層——Index(暫存區)。它扮演「打包區」的角色:你先選擇要提交哪些變更,然後再一次 commit。

Git 的三層架構

flowchart LR WD["📂 工作目錄
Working Directory
(你編輯檔案的地方)"] IDX["📋 暫存區
Index / Staging Area
(準備要 commit 的內容)"] REPO["🗄️ 版本庫
Repository (.git)
(永久保存的歷史紀錄)"] WD -->|"git add"| IDX IDX -->|"git commit"| REPO
層級 位置 說明 對應指令
工作目錄 你看到的檔案 你平常編輯、新增、刪除檔案的地方 一般檔案操作
暫存區(Index) .git/index 暫時存放「這次要 commit」的變更清單 git add
版本庫 .git/objects/ 所有已提交的版本快照,永久保存 git commit
為什麼需要暫存區?因為你可能同時改了 5 個檔案,但只想先提交其中 2 個。暫存區讓你可以精確控制「這次 commit 包含哪些變更」。

Local Repository vs Remote Repository

Git 是分散式版本控制,每個開發者的電腦上都有一份完整的版本庫。

Local Repository(本地版本庫)

存在你自己電腦上的 .git 目錄。你可以在完全離線的情況下進行 commit、查閱歷史、建立分支。

Remote Repository(遠端版本庫)

存在伺服器上(例如 GitHub)的版本庫。用來同步團隊成員的工作成果,透過 pushpull 進行交換。

flowchart TB subgraph "你的電腦" L["Local Repo
.git/"] end subgraph "GitHub 伺服器" R["Remote Repo
github.com/user/project"] end L -->|"git push"| R R -->|"git pull"| L R -->|"git clone"| L

🔧 動手練習

練習 1:觀察 .git 目錄

建立一個新資料夾,執行 git init,然後觀察 .git 目錄中有哪些東西。

$ mkdir my-first-repo
$ cd my-first-repo
$ git init
$ ls -la .git/

練習 2:測試 SHA-1 雜湊

git hash-object 測試不同內容產生的雜湊值,驗證「相同內容 = 相同 ID」。

$ echo "test" | git hash-object --stdin
$ echo "test" | git hash-object --stdin
$ echo "test2" | git hash-object --stdin

本章小結

知識重點

  • Repository 是 Git 儲存版本歷史的核心單位。
  • Git 使用三種物件(blob、tree、commit)組成物件資料庫。
  • SHA-1 雜湊值是每個物件的唯一 ID。
  • Git 的三層架構:工作目錄 → 暫存區 → 版本庫。
  • Git 是分散式系統,本地與遠端各有一份完整的版本庫。

下一章預告

  • 了解 git init 指令背後做了什麼。
  • 深入探索 .git 目錄的每一個子目錄與檔案。
  • 理解 HEAD、refs、config 等設定檔的用途。
學習提示: 這一章的概念是後續所有操作的基礎。如果你能理解「Git 是用物件資料庫記錄快照」這個核心觀念,後面的指令學起來會非常順暢。