開發(fā)者必看的 15 個困惑的 Git 術語(以及它們的真正含義)
PHP 開發(fā)者必看的 15 個困惑的 Git 術語(以及它們的真正含義)
做了多年開發(fā), 自 2015 年開始使用 Git, 我審過數(shù)百個 Pull Request,收拾過無數(shù)混亂的代碼倉庫,也帶過不少在 Git 命令里打轉的新人。
老實說,我完全理解他們的困惑。Git 確實強大,但它的術語系統(tǒng)就像一個迷宮——很多詞看著相似,實際用法卻天差地別。
今天就來聊聊這些連老手都可能搞混的 Git 術語。如果你是新手,這篇文章能幫你少走很多彎路。
原文 開發(fā)者必看的 15 個困惑的 Git 術語(以及它們的真正含義)
HEAD vs head vs Detached HEAD
開發(fā)者常犯的錯誤:
把 HEAD 當成又一個分支名。
它的真實身份:
HEAD 是一個指針,指向你當前所在的 commit —— 通常是你所在分支的最新提交。
每次你提交代碼,HEAD 就會移動到那個新 commit 上。
# 查看 HEAD 指向哪里
git log --oneline --decorate -n 3
# --oneline 把每個 commit 壓縮成一行顯示:
# commit hash 的前 7 個字符 + commit 信息
# --decorate
# 在 commit 旁邊顯示分支和標簽引用
# 這樣你就能看到 HEAD、main、origin/main 或 v1.0.0 這些指針當前在哪
# -n 3
# 只顯示最近 3 個 commit
你會看到類似這樣的輸出:
a3c4d5e (HEAD -> main, origin/main) Add user API
如果你直接 checkout 到某個舊 commit:
git checkout a3c4d5e
你會看到這樣的提示:You are in 'detached HEAD' state.
這只是說你現(xiàn)在不在任何分支上——你在查看歷史快照。沒什么壞事發(fā)生。
如果你想保存在這里做的工作:
git switch -c hotfix/legacy-bug
至于 head(小寫),它不是 Git 的關鍵字——通常只是非正式用法或復數(shù)形式,比如"分支的 heads"。
Git 把分支的最新提交存在 .git/refs/heads/ 下,所以你可能會在內部引用中看到這個詞。
比如:
.git/refs/heads/main
.git/refs/heads/feature/login
所以當你看到"所有 heads"時,意思是"每個分支的最新 commit",而不是那個特殊的 HEAD 指針。
后綴的含義:
Git 提供了一些方式讓你從 HEAD 開始往回追溯歷史。
HEAD~1
表示"HEAD 之前的一個 commit"。
HEAD~2 表示"之前的兩個 commit",以此類推。
git show HEAD~1
顯示你當前 commit 的上一個。
HEAD^1 和 HEAD^2
這些是父指針。它們在處理 merge commit 時最有用。
一個 merge commit 有兩個父節(jié)點——一個來自你所在的分支,另一個來自你合并進來的分支。
git diff HEAD^1 HEAD^2
對比合并時兩邊各自貢獻了什么。
^1 表示"第一個父節(jié)點",^2 表示"第二個父節(jié)點"。
經(jīng)驗法則:
- 用
~線性地往回走 - 用
^處理 merge commit 的父節(jié)點
如下圖演示

把 feature 合并到 main 后,merge commit (M) 有兩個父節(jié)點:
- HEAD^1 → commit C(合并前的 main)
- HEAD^2 → commit E(feature 分支的末端)
一旦你把 HEAD 想象成"你在這里",Git 的導航模型就瞬間清晰了。
Commit vs Changeset
很多開發(fā)者以為 commit 就是 diff——其實不是。
- commit = 倉庫的完整快照 + 元數(shù)據(jù) + 父節(jié)點鏈接
- changeset = 兩個 commit 之間的差異
git show HEAD # 顯示 commit 及其 diff(changeset 視圖)
git diff HEAD~1 HEAD # 只顯示兩個 commit 之間的原始 diff
git add -p # 選擇性暫存變更(構建你的 changeset)
git commit -m "Fix NPE in user lookup"
理解這個區(qū)別能幫你打造原子化 commit——每個 commit 只包含一個邏輯變更——而不是一股腦全扔進去。
Branch ≠ Copy
創(chuàng)建分支不會克隆代碼庫。
它只是創(chuàng)建一個指向 commit 的新指針。
git branch feature/login
git switch feature/login
現(xiàn)在你有了一個從 main 分叉出去的輕量級指針。沒有額外文件,沒有復制。
Tags
Tags 標記特定的 commit——通常用于發(fā)布版本,而且不會移動。
git tag v1.0.0
git push origin v1.0.0
和分支不同,tags 是不可變的。一旦設置,它們永遠指向同一個 commit。
Fast-Forward Merge
Fast-forward 不是什么特殊操作——它只是沒有分叉的合并。
無分叉 -> 可以 Fast-forward

main 從 B 之后就沒動過。
git switch main
git merge --ff-only feature
結果:

沒有創(chuàng)建 merge commit -> Git 只是把 main 的指針往前移了。
分支已分叉 -> 無法 Fast-forward

兩邊都在 B 之后有了新提交。
git switch main
git merge feature
現(xiàn)在 Git 必須創(chuàng)建一個 merge commit 來合并 E 和 D。
如果你堅持要 fast-forward:
git merge --ff-only feature
# error: Not possible to fast-forward
規(guī)則:
如果雙方在分叉后都有新 commit,就無法 fast-forward。
Squash
Squash 在合并前把多個 commit 壓扁成一個——適合清理混亂的 feature 分支歷史。
git merge --squash feature/login
git commit -m "Add login feature"
你的分支歷史保持干凈,同時在 PR 里不會丟失工作上下文。
origin vs upstream
這個挺有意思的……我?guī)滋烨霸谔幚硪粋€ fork 項目時才搞清楚區(qū)別。之前我一直以為它倆是一回事 ??
origin 是你克隆倉庫時默認的遠程倉庫名稱。
如果你 fork 了一個倉庫,原始倉庫叫做 upstream。
git remote -v
你可能會看到:
origin git@github.com:yourname/project.git
upstream git@github.com:org/project.git
用 upstream 從原始源拉取變更:
git fetch upstream
Remote-Tracking Branches
origin/main 和 main 不是一回事。
main= 你的本地分支origin/main= Git 對遠程 main 的最后已知快照
git fetch
git diff main origin/main
這能告訴你上游有什么變化,而不用立即合并。
Fetch vs Pull
git fetch 只更新你對遠程倉庫的本地認知。
git pull 做了這個,然后自動合并(或 rebase)。
git fetch origin
git merge origin/main
這比盲目 git pull 更安全、更明確。
The Staging Area (Index)
暫存區(qū)是 Git 的"候車室"。
你決定哪些變更進入下一個 commit。
git add src/App.java
git status
git commit -m "Fix null check"
你可以暫存特定的代碼塊:
git add -p
就像在結賬前往購物車里放東西。
Working Directory
你的工作目錄就是你正在編輯的文件——不是倉庫本身。
真正的倉庫在 .git/ 里。
git status
# "working tree clean" 意思是你的文件和 HEAD 一致
Tracked vs Untracked Files
你添加過一次的文件是"已跟蹤"的。
新文件在你暫存它們之前不會被跟蹤。
git status
# Untracked files: (use "git add <file>")
提交前一定要檢查這個——未跟蹤的文件不會出現(xiàn)在 commit 里。
Dirty Tree
"Dirty tree" 只是說你的工作目錄有未提交的變更。
git status
# modified: src/App.java
切換分支前先提交或 stash 它們,避免沖突。
Reset vs Revert
Git 里最容易被誤解的兩個命令。
- reset 移動 HEAD,可能會丟棄 commit(危險)
- revert 創(chuàng)建一個新 commit 來撤銷之前的變更(安全)
git reset --hard HEAD~1 # 刪除最后一個 commit
git revert HEAD # 通過添加新 commit 安全地撤銷
如果你在共享分支上工作,永遠用 revert。
總結
從本質上講,Git 就是一個由 commit 和 指針 組成的圖。
一旦你理解了 HEAD、分支 和 快照 的工作原理,其他一切都會變得合乎邏輯。

浙公網(wǎng)安備 33010602011771號