本节作为一个杂烩,介绍Git的一些零散但有用的技能知识。
1. 祖先引用(^和~区别)
符号 | 作用 | 特殊缩写 |
---|---|---|
^n |
代表当前提交的第n父提交,结果为某一父辈提交 |
^ 是^1 的简写 |
~n |
代表当前提交的n次父提交,结果为某一祖先提交 |
~ 是~1 的简写 |
关于^和~的区别,stackoverflow的What's the difference between HEAD^ and HEAD~ in Git?下的回答很好,此处引用高票答案的图如下。


2. 提交范围
通过祖先引用可以指明单次提交,此外通过特定语法我们还可以指定一定范围的提交。这常常是有用的,例如有时我们需要查看“这个分支的哪些提交还没有合并到主分支?”。
类别 | 表示 | 作用 | 数学概念 |
---|---|---|---|
两点提交 | before..after | 隶属于after分支,但不隶属于before的提交 | 差集 (after-before) |
三点提交 | before...after | 两分支中除去共同拥有的提交外的提交 | 并集-交集 (before∪after - before∩after) |
多点提交 | ^或--not | 不包含指定分支的所有提交 | 差集 |
3.补丁
- 多用于公开的大型项目。
- 当前不做介绍,只需了解可以创建补丁和应用补丁来实现代码更新。
4. 挑拣(cherry-pick)
挑拣类似针对某次特定提交的衍合。它首先提取某次提交的补丁,然后试着应用在当前分支上。
应用场景:
1)如果某特性分支上有多个commits,你只想引入其中一个,就可使用挑拣。
2)或者个人偏好挑拣胜于衍合。
-
示例(来自proGit)
当前有两个分支,若master分支只想引入e43a6的快照内容,则可进行如下操作。
初始状态
git cherry-pick e43a6 # 在当前状态执行挑拣

5. Git调试
5.1 文件标注
可使用git blame
来标注文件,查看文件中某一行是谁在哪一天修改的。其实该命令从名称可以看出来,就是出事后来问责的:)。
git blame -L <range> filename
# 若指定12行到20行,则range可表示为12,20或12,+9,此外还支持正则表达式
5.2 二分查找
git通过二分查找为在大量提交中找出引发系统错误的提交提供了高效的解决方案。
git bisect start <bad> <good>
指定问题区间,等同于以下三条命令
1. git bisect start
2. git bisect bad <bad>
3. git bisect good <good>
git bisect bad # 标注当前为bad
git bisect good # 标注当前为good
6. 重写历史
6.1 修改最后一次提交
git commit --amend
6.2 修改多个历史
通过rebase当前分支,可达到修改多个提交的目的。
git rebase -i <newbase> # 进入rebase交互模式,从newbase处开始进行多个提交的修改
-
示例
git rebase
git rebase交互界面
- 命令解释
命令 | 含义 | 使用场景 |
---|---|---|
pick | 提交 | 保持原样 |
reword | 先编辑提交信息,然后再提交 | 可编辑多个历史提交信息 |
edit | 提交后中断,可通过git rebase --continue继续下面操作 | 1)可编辑多个历史提交信息; 2)一个拆分为多个提交(结合命令 git reset HEAD~ 、git add 和git commit ) |
squash | 把本次提交整合进上一次提交,需编辑的合并的提交信息 | 把多个提交压缩为一个提交 |
drop | 删除提交 | 删除提交 |
7.子模块
- 若出现项目引用一个公共库的情况,可把公共库以子模块的方式导入到当前项目。
- 当前项目库中只保存子模块的url、路径和最新commit的引用。
具体使用可参考:姜家志老师写的文章《使用Git Submodule管理子模块》,本节不在赘述。
8.写在后面的话
本节终了也意味着以《ProGit》为纲要的Git学习内容的结束,本系列内容也会暂告一段落。此后,若使用Git遇到值得记录的问题和实例,本人将再来续尾。
最后,本人水平有限,仓促写作;若有不足,万望赐教,不胜感激。
网友评论