情况如下:
RepoA
.git
文件夹的所有文件复制到新文件夹RepoB
git init
并添加了不同的远程
RepoB
并将许多提交推送到远程现在,我想将我的作品与他们的回购合并。这就是我在RepoA
中所做的。
git checkout develop
git remote add repoBOrigin https://www.cloud.com/repoB.git
git fetch repoBOrigin aBranchOfRepoB // all of the work is in this branch
git merge repoBOrigin/aBranchOfRepoB
我收到了这个错误:fatal: refusing to merge unrelated histories
我在stackoverflow上查了一下,发现可以使用--allow-unrelated-histories
标志来解决这个问题,但是会发出警告,这种情况应该在极少数情况下使用。
现在,我真正担心的是这个标志会产生什么影响/问题。 RepoA的git历史将如何形成?
没有人解释合并无关历史的后果。由于该项目的规模相当大,我必须非常小心才能将任何愚蠢的东西推到他们的回购中。
答案 0 :(得分:1)
我真正担心的是
--allow-unrelated-histories
会产生什么影响/问题...
标志本身不会造成任何后果。它的作用是启用一个不是Git用户期望的行动。
要理解它 - 或者一般的Git,真的 - 你需要掌握一些关于图形的基本知识,正如通常的数学定义所定义的那样,图形 G 是顶点的集合 V 通过边 E 连接,或以通常的符号写入, G =(V,E)。当边缘有一个方向 - 一种单向箭头时,每个顶点(或节点)"进入"另一个顶点,但你不能回头,边缘被称为 arcs 。
在Git中,提交图的定向如下:每个提交充当图节点,并列出其父提交。这些是传出的弧,因此它们以一种倒退的方式连接提交。 Git的分支名称然后用于查找 last 提交,以便在一个很小的三个提交存储库中,您将拥有:
A <-B <-C <--master
提交A
是您做过的第一次提交,因此它没有父级。提交B
列出提交A
作为其父项,C
列出B
作为其父项;并且Git找到提交C
- 其真实姓名,即其哈希ID,看起来非常随机 - 使用名称master
来保存C
的哈希ID。
知道这些链接 - 弧线 - 全部向后,从子到父,我们可以更方便地绘制链接,并添加更多提交:
A--B--C--D <-- master
\
E--F--G <-- branch
如果我们现在将合并分支重新转换回master
,Git会使用这些连接箭头来确定您在master
上的工作在哪里分开别人在branch
工作。这回到了提交B
,图表节点重新加入。因此,Git现在可以将此合并基础B
中保存的快照与master
的提示进行比较:
git diff --find-renames <hash-of-B> <hash-of-D>
找出你的变化。然后Git可以将B
中的快照与branch
中的快照进行比较:
git diff --find-renames <hash-of-B> <hash-of-G>
合并的行为 - 合并动词 - 使这两个差异并组合起来,将组合的变化应用于基本提交中的任何内容。如果一切顺利,Git会自己提交最终结果。 (如果没有,Git会停止,并让你清理混乱并自己做提交;提交内容取决于你如何修复Git发现的冲突。)结果是合并提交,而不是一个两个父母:
A--B--C--D---H <-- master (HEAD)
\ /
E--F--G <-- branch
同样,新合并提交H
的源代码快照是组合自合并基础以来所做的更改的结果 - 公共起点两个分支提示。
但是,在您的情况下,您已经制作了两个无关的存储库。结果是数学家称之为disconnected graph。它可能看起来像这样,例如:
A--B--C--D---H <-- br1
\ /
E--F--G
L--M
/ \
I--J--K------N <-- br2
如果您现在git checkout
这两个分支中的一个,以便HEAD
附加到br1
,然后运行git merge br2
,Git就会找到共同点起点,从两个分支尖端向后(向左)工作。但是没有共同的起点:历史是无关的。
旧版本的Git将继续并合并。除非你提供旗帜,否则新人会抱怨;如果你提供旗帜,它们会以完全相同的方式继续合并。
这里的问题是没有共同的起点,所以Git所做的是假设公共起点是真正的空提交:提交没有文件就在里面。
这意味着新创建了两个分支中每个分支的每个文件。具有相同路径名的两个文件将导致&#34;添加/添加冲突&#34;:Git说您从头开始编写README.txt
,并且他们从头开始编写README.txt
,而Git本身并不知道如何将这些结合起来,所以你必须自己做。对于每个具有相同名称的文件重复此操作。
另一方面,如果您创建了README.md
并且他们创建了README.rst
,则这两个名称会有所不同,因此Git假定将README.md
与任何内容合并的正确方法是取README.md
,将README.rst
与任何内容合并的正确方法是README.rst
。所以你最终得到了这两个文件,Git认为它们现在已正确组合。 (这是真的吗?我不知道.Git也没有,但Git 认为它是真的。)
这对所有文件都重复:要么每个文件名对于特定的差异都是唯一的,所以Git会添加它,或者它不是,所以Git声明冲突并由你来解决问题。最后,如果没有文件名冲突,Git会自行进行新的提交;如果有冲突,Git会让你清理它们并自己做。我们可以绘制新的提交:
A--B--C--D---H-----O <-- br1 (HEAD)
\ / /
E--F--G /
/
L--M /
/ \ /
I--J--K------N <-- br2
这是一件明智的事吗?我无法回答这个问题;只有你能回答。