第六章:提交
1】提交(commit)是用来记录版本库的变更的。(一一对应关系)
2】提交时,Git会记录索引的快照并把快照放进对象库中。
3】提交是将变更引入版本库的唯一方法。
一、原子变更集
1】每一个Git提交都代表一个相对于之前状态的单个原子变更集。
2】对于一个提交中所有做过的变动,相当于一个原子。要么全部应用,要么全部拒绝。
3】在底层模型,原子性是有意义的。一张提交快照代表所有文件和目录的变更。
它代表一棵树的状态,而两张提交快照之间的变更集就代表一个完整的树到树的转换。
二、识别提交
1】在Git中,可以通过显式或隐式的引用指代每一个提交。
2】唯一的40位十六进制SHA1提交ID是显式引用。
3】始终指向最新提交的HEAD则是隐式引用。
1、绝对提交名
1】散列标识符(散列ID)就是绝对名,它只能代表唯一确定的一个提交。
2】散列ID是全局唯一的,而且是对任意版本库都是唯一的。
3】标签名不是全局唯一,但标签名会明确指向一个唯一的提交。
2、引用和引用符号
1】引用是一个SHA1散列值,指向Git对象库中的对象。
2】一个引用通常指向提交对象。(引用可以指向任何Git对象)
3】符号引用:间接的指向Git对象。(它仍然只是一个引用)
4】本地特性分支名称、 远程跟踪分支名称和标签名都是引用。
5】每一个符号引用都有一个以 ref/ 开始的明确全称,并且都分层存储在版本库的 .git/refs/目录中。
6】.git/refs/ 目录有三种不同的命名空间代表不同的引用。
7】如果 一个分支和一个标签使用相同的名字,Git会应用消除二义性的启发式算法,。
根据git rev-parse手册上的列表选取第一个匹配项。
8】Git自动维护几个用于特定目的的特殊符号引用。(这些引用可以在使用提交的任何地方使用)
9】Git中有一个特殊符号集来指代引用名。冒号 ":"可以用来指向一个产生合并冲突的文件的替代版本。
3、相对提交名
1】Git的另一种(确定相对于另一个引用的提交)的机制,分支的头。
2】同一代提交中,^符号选择不同的父提交。
3】波浪线 ~ 用于返回父提交之前并选择上一代提交。
4】master~10^2~2^2复杂的名字。
5、git rev-parse + 提交名。把任何形式的提交名(标签、相对、简写绝对或者绝对名)都能转化为提交ID。
6】git show-branch 。查看提交的相对名和提交日志消息。
三、提交历史记录
1、查看旧提交
1】显示提交历史记录的主要命令是 git log。(更多的选项、参数、选择器、格式化器等)
2】git log = git log HEAD,输出可从HEAD找到的历史记录中的提交日志。
3】注意: 回溯历史记录的时候,Git依附于提交图,而不是时间。
4】git log 提交名,从指定的提交进行回溯。(对于查看某个分支的历史记录很有用)
5】无需查看版本库所有历史记录。我们要限制历史记录: since...until指定提交范围。
(没有since,有until)
6】--pretty选项: 调整提交的信息数量。(有 oneline、short、full三种)
7】--abbrev-commit:只是请求缩写散列ID。
8】-p 选项: 输出提交引进的补丁或变更。(查看某个提交修改的内容)
9】-n 选项,指定查看的提交日志的数量。
10】--stat选项,查看提交中变更的文件以及每个变更文件的改动行数。(可以与上图对应)
11】git show 命令,查看对象库对象的命令。也可以用来查看提交或某个对象。
2、提交图
1】图1、一幅完整但稍稍简化的提交图。
2】图2、极大地简化蓝图:每一个提交都引入一个树对象来表示整个版本库。
3】Git通过DAG(有向无环图)实现版本库的提交历史记录。
(提交图中,每一个节点代表一个单独的提交,所有边都从子节点指向父节点,形成祖先关系)
4】图3、标记提交图。将每一个提交做一个标记。
5】gitk命令,可以画出版本库的DAG。
6】理解DAG: (a)一般提交只有一个父提交、 (b)只有初始提交没有父提交、 (c)合并提交有多个父提交、
(d)多个子提交的提交是出现分支的地方。
7】git merge-base命令,可以查看分支的起点。
3、提交范围
1】很多Git命令都允许指定提交范围。(提交范围: 一系列提交的简写)
2】双句点(..)形式就表示一个范围。(开始..结束)【结束可达,开始不可达】
3】不可达原因: git:log X..Y == git log ^XY。
"要从Y提交可到达的所有提交, 但是不要任包括X提交及其之前的提交"。
4】图4: 不可达。 ( M~12..M10 )
5】图5、范围是两个分支,topic..master表示在master分支而不再topic分支的提交。
6】图6、三个句点(...):对称差。 A...B: A和B之间的对称差。(A...B == B...A)
也就是A或B可达但又不是A和B同时可达的提交集合。
四、查看提交
1、使用git bisect 命令
1】git bisect, 基于任意搜索条件查找特定的错误提交。
2】前提条件: 要知道一个"好"状态版本和一个"坏"状态版本,以便搜索可以界定范围。
3】采取的是二分查找模式。(尽量让"好" 和 "坏" 离得近一些)
4】第一步: git bisect start 表示开始进行查找。
第二步: git bisect bad 指定提交 表示已知的"坏"状态版本。
第三步: git bisect good 指定提交 表示已经的"好"状态版本。
第四步: 会定位到两个提交的中间提交。 用 git bisect bad 或者 git bisect good标记该提交。
第五步: 会定位到新的 good 和 bad的中间。再次指定好坏(递归下去,可以得到错误提交)
5】git bisect log 命令,查看 good 和 bad对应提交ID的问答日志。
6】git bisect replay 日志文件。可以重新开始:
7】git bisect visualize --pretty=oneline,可视化的检查提交范围内的内容。
8】git bisect reset,退出bisect debug的状态。(注意: 问答的过程中。HEAD会发生改变)
2、使用git blame
1】git blame, 也有助于识别特定提交。某个文件, 每一行最后修改的作者,修改的提交ID。
3、使用Pickaxe
1】git blame命令,查看文件的状态,git log -Sstring,会根据string沿着文件差异历史搜索。
2】通过搜索修订版本间的实际差异,可以找到执行改变的提交。
3】带有-S选项的 git log 命令称为pickaxe。