提交顺序由提交图表决定,而不是由日志中的时间戳决定。但是,git log 的输出可以按时间戳顺序显示,而不是按图形顺序显示。因此,您的问题的答案是“是”、“否”或mu,而不是真正有用的东西。这是棘手的部分。
首先请记住,每个提交都有一个唯一哈希ID。这个散列 ID,通常表示为一个大的 hexadecimal 数字,看起来是随机的,通常不被人类使用,实际上是提交内容的加密校验和,这意味着。它之所以独特,部分原因在于它会:理论告诉我们最终会发生哈希冲突,但它也不会在数十亿年内发生。1 即使有一个 发生,Git 对此的回答是“你不能添加那个提交”。2 所以哈希 ID 是在某种意义上的提交。
同时,每次提交都会记录两件事:
- 每次提交都有所有文件的完整快照。
- 每个提交都有一些元数据,例如提交的人员和时间:例如,
git log 输出中可见的时间戳来自此元数据。
任何给定提交中的元数据都包括上一个提交的哈希ID。所以这意味着提交实际上是根据一些后来的提交记录其哈希 ID 的事实来排序的。这个“后来提交记录早期提交的哈希 ID”提供了提交图。此提交图采用有向无环图的形式:较晚的提交指向较早的提交,并且循环被排除,因为较早的提交不能包含稍后提交的哈希 ID。3
这一切归结为 DAG 本身,而不是时间戳,决定了提交顺序。在您描述的场景中,用户 U1 和 U2 从同一个起始提交“同时”进行两次提交,我们最终在图中出现了分歧:
1
/
...--o--o--C
\
2
提交 1 的父节点是提交 C,提交 2 的父节点是提交 C。提交1 和2 相对于彼此无序:它们是图中的兄弟姐妹,因此它们之间没有父/子关系。两者都是C 的子级(两者都以C 作为父级),因此在图建立的偏序中,C ≺ 1 和C ≺ 2,但1 和@ 987654339@ 只是无序的。
现在,不可能定位提交 1 和 2,除非:
- 您知道他们的原始哈希 ID,或者
- 您有名字可以用来定位他们或他们的任何继任者。
也就是说,如果我们有两个分支名称,我们可以找到两个提交:
1 <-- user1
/
...--o--o--C
\
2 <-- user2
运行git log user1 会生成一个显示提交1 的日志,然后是提交C,然后是C 左侧的第一个提交(此处标记为o),依此类推:提交2 根本没有显示。运行git log user2 会生成一个日志,显示提交2,然后提交C,然后提交到图中C 的左侧。
但是,运行 git log user1 user2 会将 both 提交 1 和 2 插入到 to-be-shown 队列中。 此时git log 将选择“更高优先级”的提交来显示。
在此git log 优先级队列中,提交的优先级由以下各项控制:
- 默认的提交者日期戳,或者
- 如果使用
--author-date,则为作者日期戳,或
- 如果在
git log 时间指定,则按其他标准。
如果我们假设提交者和作者的日期戳相同,那么这两个提交在队列中具有相同的优先级,其中一个会先出来,但不能保证 哪个。他们只是出来,但是他们出来了。
我们无法通过一个名称找到两个提交,因此在两个用户都可以git push这些提交之前,至少一个必须做一些棘手的事情,例如如:
- 创建一个新的分支名称,或者
-
rebase 提交(将提交复制到新的改进提交),或
-
合并一些提交(添加一个具有两个或更多父级的新提交)。
我们已经知道创建新分支名称的效果,正如我们在上面看到的那样。如果一个用户rebase他或她的提交在另一个之上,结果是一个新的不同的提交在一个新的和不同的图表中:
...--o--o--C--1--2' <-- branch-name
例如。在这里,git log 将首先显示提交 2',然后提交 1,不管任何日期戳。
如果一个用户合并,我们可以得到这个:
1
/ \
...--o--o--C M <-- branch-name
\ /
2
现在,如果有人在此分支上运行 git log,他们将首先看到提交 M,然后按优先队列顺序提交 1 和 2 — 因为查看提交 M 会将两个提交都推送到优先队列——然后像以前一样提交C。优先级队列中的顺序取决于 git log 的参数,就像我们通过两个分支名称给它两个起始提交哈希 ID 的情况一样。但是,将--first-parent 添加到git log 将导致git log 仅将提交M 的first 父级推入队列,因此访问提交@987654377 后队列深度仅为1 @。因此,我们将只看到提交M,然后只看到第一个父级(无论是哪个父级),然后只提交C,依此类推:访问提交会将其父级推入队列,--first-parent 将其限制为它的第一个父母。
1实际经过的时间取决于我们生成哈希的速率,以及有人在破解密码学方面取得的任何进展,但在实践中它“足够长” .
2以“您无法添加新提交”为代价巧妙地解决潜在问题(旧的提交哈希 ID 保持唯一)。
3为了强制执行此操作, 较晚提交的加密校验和 包括较早提交的哈希 ID 的十六进制表示。这意味着您必须知道未来提交的哈希 ID 是什么,才能将该哈希 ID 包含到当前提交中;但是知道这一点并包含它会更改 this 提交的哈希 ID,这反过来会更改该未来提交的哈希 ID。除非你能找到一个固定点或小循环,否则你是做不到的。