为什么 mercurial 中的这些命令会创建一个新的头部?

Why these commands in mercurial create a new head?

作为一项任务,我被要求弄清楚以下哪一行会导致头数发生变化,现在我检查并看到第 16 行和第 20 行向他们的存储库添加了新的头,但我不太清楚确定为什么..我知道当有冲突时数字会改变但是这里有点不清楚..

谁能帮我理解一下? :)

谢谢。

1: /home/user> hg clone http://remoteserver/mainrepository first 
2: /home/user> cd first 
3: /home/user/first> echo one > a.txt # Create a new file a.txt containing “one” 
4: /home/user/first> hg add a.txt 
5: /home/user/first> hg commit -m "Added a file" 
6: /home/user/first> cd .. 
7: /home/user> hg clone first second 
8: /home/user> cd second 
9: /home/user/second> echo two >> a.txt # Append a line to a.txt containing “two” 
10: /home/user/second> hg commit -m "Modified a file" 
11: /home/user/second> hg push -f http://remoteserver/mainrepository 
12: /home/user/second> cd ../first 
13: /home/user/first> echo more > b.txt # Create a new file b.txt containing “more” 
14: /home/user/first> hg add b.txt 
15: /home/user/first> hg commit -m "Added another file" 
16: /home/user/first> hg pull # default pulls from where repo was cloned 
17: /home/user/first> echo ‘‘even more’’ > c.txt # Create a new file c.txt 
18: /home/user/first> hg add c.txt 
19: /home/user/first> hg commit -m "Added yet another file" 
20: /home/user/first> hg push -f 

让我们一次完成这些步骤并解释会发生什么:

第 1-2 步:克隆一个存储库,并将工作文件夹更新到提示,然后进入该文件夹。

步骤 3-5:提交另一个变更集,创建一个新的提示(但不是另一个头)。

第 6-8 步:将第一个存储库克隆到一个新的存储库中,同时更新其工作文件夹,然后进入该文件夹。

步骤 9-10:在第二个克隆的 tip 之上提交另一个变更集。

第 11 步:将这个新的变更集推送到原始源中。这个存储库,即我们从中克隆以创建 first 的存储库,因此除了我们在步骤 1 中克隆的那些之外,现在还有一个变更集。

第 12 步:返回第一个存储库

步骤 13-15:在第一个当前变更集之上提交另一个变更集。

第 16 步:从原始源拉取,这里我们引入我们首先在第二个克隆中添加的变更集,然后在上面的第 11 步中推送。这将使我们的 first 存储库现在有两个头。

步骤 17-19:在前一个变更集之上提交另一个变更集,这不会创建另一个头部,我们只是 "extending" 那个带有另一个变更集的头部。

第 20 步:推送到原始源,强制推送,这将推送新的变更集并在远程存储库中创建另一个头。


现在,为什么会发生这种情况,可以吗?

首先,好吗?当然是。好吧,有点。在本地存储库中创建额外的头是可以的,也是推荐的。例如,如果您发现前段时间引入了错误,建议的修复方法是首先更新回引入错误的变更集,然后修复工作文件夹中的错误,然后将错误修复提交到原始变更集。

上面的"sort of"是因为在推送之前应该在本地解析额外的头。你几乎不应该 push 额外的头到远程存储库。因此,hg push-f 参数最好单独保留。

修复附加头的正确方法是合并,这需要两个父级并将在这两个并行分支中引入的更改合并回一个头。

那么,为什么会发生这种情况?好吧,最好的学习方法就是阅读分布式版本控制系统的工作原理。

简而言之,如果您将存储库克隆到本地机器,然后在本地工作,同时其他人工作并将他们自己的新变更集推送到您从克隆的存储库中,那么最终当你尝试推动你会被告知这会引入额外的头,这很糟糕。

要解决此问题,您应该在重新尝试推送之前拉取并合并您的头与被拉下的头(该头将包含其他人同时贡献的新变更集)。

步骤 1-5 使主存储库和第一个存储库处于以下状态,假设 r1-r3 是主存储库的原始状态:

Main:  r1--r2--r3

First: r1--r2--r3--r4

第 6-11 步将 first 复制到 second,向 second 提交内容,然后将其推回 main:

Main:   r1--r2--r3--r4--r5

First:  r1--r2--r3--r4

Second: r1--r2--r3--r4--r5

步骤 12-15 回到第一个并再次提交一些内容:

Main:   r1--r2--r3--r4--r5

First:  r1--r2--r3--r4--r6

Second: r1--r2--r3--r4--r5

第 16 步从 main 拉入 first,引入缺失的 r5,但请注意 r6r5 具有相同的 r4 父级,所以这创建一个分支:

Main:   r1--r2--r3--r4--r5

First:  r1--r2--r3--r4--r6
                      \-----r5

Second: r1--r2--r3--r4--r5

步骤 17-19 首先创建另一个提交:

Main:   r1--r2--r3--r4--r5

First:  r1--r2--r3--r4--r6------r7
                      \-----r5

Second: r1--r2--r3--r4--r5

第 20 步 强制 推回 main,并在那里创建一个分支:

Main:   r1--r2--r3--r4--r5
                      \-----r6--r7

First:  r1--r2--r3--r4--r6------r7
                      \-----r5

Second: r1--r2--r3--r4--r5

相反,更好的做法是首先在本地合并,这样主存储库就不会留下两个头。因此,在第 19 步和第 20 步之间执行 hg merge,然后执行 hg push,而不强制使用 -f。结果将是:

Main:   r1--r2--r3--r4--r5----------m8
                      \-----r6--r7-/

First:  r1--r2--r3--r4--r6------r7--m8
                      \-----r5-----/

Second: r1--r2--r3--r4--r5