我们有一门课程,我们学习Mercurial。我有一个关于Mercurial的问题,但我相信Git在这里的行为完全相同。
为了回答这个问题,我使用了Mercurial Workbench,并在每个命令后跟随图表。
这是一个问题: 对于以下序列的mercurial操作,解释哪一行 导致任何引用的存储库中的磁头数量发生变化(比如说哪个 存储库受影响,为什么)。假设主存储库最初只有一个 头,有一些现有的数据:
(我已经加粗了我认为新头脑的线条)
/家/使用者> hg clone http://remoteserver/mainrepository clone1
/家/使用者> hg clone http://remoteserver/mainrepository clone2
我得出了这个结论:
我们最终得到了克隆1中的3个头和克隆2中的3个头。
我的问题是:
谢谢
答案 0 :(得分:1)
对于(1):是的,这是对的。对于(2),我不确定你要问的是什么("在每一步添加一个新行" - 行这里的意思是?)。 [按评论编辑]让我们看一下前面步骤的步骤14,15,19和21。
在第14步,您运行hg commit -m "Added another file"
。 当前提交不是现有的提示提交,因为在步骤12中您进入了" clone2"目录/克隆,其当前提交与您进行克隆时相同(步骤2)。也就是说,如果当前提交在步骤2中是numeric-ID 0
和hash-ID a1234567....
,那么仍然是当前提交,即使步骤10向该存储库添加了更多提交。 (当前分支可能是default
,虽然这不太重要,因为clone1和clone2都在同一个分支上,并且添加到clone1的提交现在出现在clone2中,在同一个分支上。关键项是由于推入提交,clone2中的当前 commit 不是clone2中当前分支的头部。)
在更典型的情况下,例如在步骤7中,当您进行新提交时,您将进行头部提交(没有子级的提交)。进行新提交会创建新提交,并将当前提交作为其父提交,以便 一个头(没有子节点)的提交不再是头(具有子节点);而新的承诺本身就是新的,没有孩子,因此是一个头脑。因此,头数被调整为-1(前一个头的丢失)和+1(通过新提交获得新头)。
但是你在步骤14中做出的新提交有一个非头脑 - 不再提交作为其父。它的头脑"在{10}获得子提交时,git push
在早期被删除。现在它有两个孩子,这使得它不是一个头;并且作为新提交的新子提交具有 no 子项,使其成为一个头。因此,头数被调整为+1而没有偏移-1。
在第15步,您运行hg push -f ../clone1
。这会将您刚刚在步骤14中创建的新提交放入clone1。由于您所做的新提交是一个头,因此clone1获得了新的头脑。
步骤19类似,但我们回到了clone1(由于步骤16)。由于步骤17(hg up initial
使用标记来查找要切换到的提交),当前提交不是现有的头。你做了一个新的提交,这是一个新的头;但是你将这个新提交添加为新子提交的提交本身并不是一个头,所以人数增加了一个。第21步简单地将这个新提交推送到clone2:它是clone2的新手,因此它是一个新头,但它不会将任何现有头转换为非头部。
请注意,当您使用hg branch <newbranch>
然后使用hg commit
时,您为当时的当前提交创建了一个新子项,但该新子项是在另一个分支中。成为当前提交的新提交是新(现在)分支的新头,并且它曾经是当前提交的子代这一事实是无关紧要的,因为&#34; head -ness&#34;由同一分支中的子提交确定。
......我相信Git的行为完全相同
就提交而言,但不是 head 。
Mercurial将 head 定义为任何提交,没有传出的弧进入(子提交)同一分支。 Mercurial的分支与Git非常不同,Git或多或少将头定义为&#34;任何具有直接指向它的分支名称的提交&#34; (虽然Git称这些 tip 提交,并将分支名称本身称为&#34; head&#34;)。
Git的分支没有永久性:它们的存在只是因为分支名称本身存在,并且分支名称只有在您不告诉Git删除它时才存在。删除名称后,分支就不再存在。 提交,直到不再有对它们的引用,此时垃圾收集器(一旦运行)丢弃它们。一些引用在 reflogs 中被删除,并且每个分支都有一个单独的reflog(删除分支时删除)加上一个特殊名称HEAD
( never < / em>已删除),因此即使分支的reflog引用消失,HEAD
reflog引用也会使delete-branch提交保持活动一段时间。
如果从某些其他分支可以访问这些(in-Git)提交,那么它们会继续保持不变。同时,Git中的每个提交通常可以同时从 N 分支到达( N 是任何非负整数,通常 N ≥1) 。我们说那些提交包含在那些分支中。相比之下,Mercurial中的每个提交都在一个分支上,其分支在提交时被选中,并且它永远不会改变。
换句话说,我们可以说Mercurial中的,分支的存在依赖于分支上的提交; 但是在Git, commit 的存在取决于包含该提交的(分支和其他)名称。 任何名称都可以,包括标记名称 - Git在这里有一个比Mercurial更大的命名空间,因为它的标签存储在外部(这使得它们没有版本化,这意味着所有这些)。
使用Mercurial工作,&#34; head-ness&#34;是一个提交的自动属性,并使这个工作在Git,&#34; head-ness&#34; (或branch-tip-ness)由手动管理。要使其主要 - 自动,git commit
将自动更新当前分支(其名称存储在HEAD
中)以指向刚刚进行的新提交。
两个VCS都以相同的方式添加新提交:它们采用Git 索引中存储的建议提交中的任何内容,或Mercurial的工作状态,如下所示: hg summary
- 并将其打包成真正的提交,其父级是当前提交。在Mercurial中,我们已经完成了这项工作,我们已经做到了:因为没有孩子,它会自动成为头脑。在Git中,在完成新提交之后,我们的最后一项任务是将提交的ID写入当前分支名称,以便分支名称现在指向新的提示提交。