1.HEAD概念
HEAD是一个指针,指向当前分支最新的commit,而branch指向一个commit
1-1.当前HEAD
HEAD文件指向当前分支
cat .git/HEAD
ref: refs/heads/master
1-2.查看HEAD执行的文件
文件指向了一个hash值
cat .git/refs/heads/master
7cc0ac8e656a95fe8f65ccbcbd7e9c0c8791e74a
1-3.查看hash值
git cat-file -t 7cc0ac8e656a95fe8f65ccbcbd7e9c0c8791e74a
commit
1-4.查看commit对象信息
git cat-file -p 7cc0ac8e656a95fe8f65ccbcbd7e9c0c8791e74a
tree 22f476fceb74f3f1e3547311f7d5e1271021229f
parent b9410841d7fa4cc8f8f29aab780b661d0f8dcf4f
author user-name <xxxxx@xxx.com> 1677307290 +0800
committer user-name <xxxxx@xxx.com> 1677307290 +0800
add c3.txt
1-5.查看日志
git log -1
commit 7cc0ac8e656a95fe8f65ccbcbd7e9c0c8791e74a (HEAD -> master)
Author: user_name <user_name@xxx.com>
Date: Sat Feb 25 14:41:30 2023 +0800
add c3.txt
2.HEAD~
HEAD~{n}
是用来在当前提交路径上回溯的修饰符
HEAD~{n} 表示当前所在的提交路径上的前 n 个提交(n >= 0):
HEAD = HEAD~0 # 当前的commit-id
HEAD~ = HEAD~1 # 前一个的commit-id
HEAD~~ = HEAD~2 # 前两个的commit-id
HEAD{n个~} = HEAD~n # 前N个的commit-id
3.HEAD^
3-1.说明
^
是用来切换父级提交路径
的修饰符。
<rev>^<n>
用来表示一个提交<rev>
的第 n 个父提交,如果不指定 n,那么默认为 1。比如,在一个提交引用C是由B合并到A中并产生的一个新提交(
git merge B
)
C
|\
A B
此时认为A是C的第一个父祖先提交B是C的第二个父祖先提交,因此通过提交引用C来获取B的表达式为:C^2。
注意:HEAD^^^ 并不等价于 HEAD^3,而是等价与 HEAD^1^1^1。
3-3.两级
以当前
HEAD(a422bf9)
开始计算,master
分支最后合并了fix
,所以只有两级
3-3-1.查看日志关系图
git log --oneline --graph --all
* a422bf9 (HEAD -> master) Merge branch 'fix'
|\
| * 3f2cb47 (fix) add fix
* | 080c24b Merge branch 'dev'
|\ \
| * | 0df0755 (dev) add dev_b.txt
| * | 1b60089 add dev_a.txt
* | | cc115c7 add d.txt
| |/
|/|
* | aa754c8 add c.txt
|/
* f8efdee add b.txt
* 40ee907 add a.txt
3-3-2.HEAD
的 第一个父级
a422bf9第一个父级是080c24b
git rev-parse HEAD^1
080c24bad3d95048f7e374ce576558f4eb94aac8
3-3-3.HEAD
的 第二个父级
a422bf9第一个父级是3f2cb47
git rev-parse HEAD^2
3f2cb4783ad0665c4d9992208b0e836e2dc6a302
3-4.三级
以当前
HEAD(bd9f951)
开始计算,master
一起合并了dev
和fix
,所以有三级
3-4-1.查看日志关系图
git log --graph --oneline --all
*-. bd9f951 (HEAD -> master) merge dev fix
|\ \
| | * 3f2cb47 (fix) add fix
| * | 0df0755 (dev) add dev_b.txt
| * | 1b60089 add dev_a.txt
* | | cc115c7 add d.txt
| |/
|/|
* | aa754c8 add c.txt
|/
* f8efdee add b.txt
* 40ee907 add a.txt
3-4-2.HEAD
的 第一个父级
cc115c7 add d.txt
git rev-parse HEAD^1
cc115c71947e4f3ea8c0f57db8cdfc415516dfd0
3-4-3.HEAD
的 第二个父级
0df0755 (dev) add dev_b.txt
git rev-parse HEAD^2
0df0755e32564efff21149e6c5a7dd46f3f8ff14
3-4-4.HEAD
的 第三个父级
3f2cb47 (fix) add fix
git rev-parse HEAD^3
3f2cb4783ad0665c4d9992208b0e836e2dc6a302
4.换算
# 当前提交
HEAD = HEAD~0 = HEAD^0
# 主线回溯
HEAD~1 = HEAD^ 主线的上一次提交
HEAD~2 = HEAD^^ 主线的上二次提交
HEAD~3 = HEAD^^^ 主线的上三次提交
# 如果某个节点有其他分支并入
HEAD^1 主线提交(第一个父提交)
HEAD^2 切换到了第2个并入的分支并得到最近一次的提交
HEAD^2~3 切换到了第2个并入的分支并得到最近第 4 次的提交
HEAD^3~2 切换到了第3个并入的分支并得到最近第 3 次的提交
# ^{n} 和 ^ 重复 n 次的区别
HEAD~1 = HEAD^
HEAD~2 = HEAD^^
HEAD~3 = HEAD^^^
# 切换父级
HEAD^1~3 = HEAD~4
HEAD^2~3 = HEAD^2^^^
HEAD^3~3 = HEAD^3^^^
5.两者关系
~
获取第一个祖先提交,^
可以获取第一个父提交。- 其实第一个祖先提交就是第一个父提交,反之亦然。
- 因此,当 n 为 1 时,
~
和^
其实是等价的。 譬如:HEAD~~~
和HEAD^^^
是等价的