Git 中 HEAD^ 与 HEAD~ 有什么区别
HEAD^ 选"第几个父提交"(用于合并提交的多父场景),HEAD~ 表示"向上数第几代"。HEAD~1 与 HEAD^ 等价,但 HEAD^2 是合并提交的第二个父,HEAD~2 是向上两代——含义完全不同。
一句话回答:^(尖角)回答的是"哪个父提交":HEAD^ 即 HEAD^1 指第一个父提交,HEAD^2 指合并提交的第二个父;~(波浪号)回答的是"往上几代":HEAD~2 指沿第一父链向上两代。HEAD^ 与 HEAD~1 在有父提交时始终等价;HEAD^2 和 HEAD~2 则不是同一回事,线性提交的 HEAD^2 根本不存在。
逐个讲清楚
HEAD^(caret,选父提交)
HEAD^=HEAD^1:HEAD 的第一个父提交HEAD^2:HEAD 的第二个父——只有合并提交(merge commit)才有第二个父,指被合并进来的那条分支的顶端HEAD^3:章鱼合并(octopus merge)的第三个父,极少见
HEAD~(tilde,数代数)
HEAD~1:沿第一父链向上一代(等价HEAD^)HEAD~2:向上两代(等价HEAD^^)HEAD~5:向上五代(等价HEAD^^^^^——显然波浪号更适合大数字)
图解合并提交
A---B---C-------M main(HEAD)
\ /
D-------E feature
对合并提交 M(假设 M 是 HEAD):
HEAD^1= C(合并前 main 上的提交,"主线"父)HEAD^2= E(被合并的 feature 分支顶端)HEAD~1= C(沿第一父链向上一辈,同^1)HEAD~2= B(向上一辈再上一辈)
记忆法:~ 纵向数层数,^ 横向选父母。
组合使用
HEAD~2^2:向上两代后的提交,取其第二个父git revert -m 1 HEAD:撤销合并时的-m 1就是"以第一父为主线",用的正是^的概念
常用场景
git show HEAD^ # 看上一个提交
git diff HEAD~3 HEAD # 最近三次提交的总改动
git reset --soft HEAD~1 # 撤销最近一次提交,改动回暂存区
git log HEAD~10..HEAD # 第一父链10代以来的可达提交,含合并进来的分支,可能超过10条
# 只要最多10条:git log -10
常见问题(FAQ)
Q:HEAD^^ 和 HEAD~2 一样吗?
A:一样。^ 不带数字时默认 ^1,HEAD^^ = HEAD^1^1 = 沿第一父链两代 = HEAD~2。写 ~2 更简洁。
Q:Windows 下 ^ 有问题?
A:cmd 把 ^ 当转义符,git log HEAD^ 会被吃掉。解决:用 HEAD~1 代替,或用双引号 "HEAD^",或改用 PowerShell/Git Bash。
Q:怎么引用"第二个父向上两代"?
A:HEAD^2~2——先取第二个父,再沿它的第一父链向上两代。尖角和波浪号可以自由拼接。
核查依据
本文依据官方文档核对,示例未在实际业务环境运行;上线前请按部署版本、权限与数据范围验证。