情况如下:
RepoA.git到新文件夹RepoBgit 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
Run Code Online (Sandbox Code Playgroud)
我得到了这个错误:fatal: refusing to merge unrelated histories
我在 stackoverflow 上查找了这个问题,发现可以通过使用--allow-unrelated-historiesflag 来解决这个问题,但这会附带一个警告,表明应该在极少数情况下使用它。
现在,我真正关心的是这个标志会导致什么后果/问题。RepoA 的 git 历史将如何形成?
没有人解释合并不相关历史的后果。由于该项目规模相当大,因此在将任何愚蠢的内容推送到他们的仓库之前我必须非常小心。
\n\n\n我真正关心的是影响/问题
\n--allow-unrelated-histories会导致什么影响/问题......
旗帜本身不会造成任何影响。它的作用是启用新 Git 用户所不期望的操作。
\n\n要理解\xe2\x80\x94或一般的Git,实际上\xe2\x80\x94你需要有一些关于图的基本知识,正如通常的数学定义所定义的那样,其中图G是由边连接的顶点V的集合E,或用通常的符号写成G = (V, E)。当边有一个方向\xe2\x80\x94a 一种单向箭头,使得每个顶点(或节点)“前往”另一个顶点但不一定能返回时,这些边称为弧。
\n\n在 Git 中,提交图是这样定向的:每个提交充当图节点,并列出其父提交。这些是传出弧,因此它们以某种向后的方式连接提交。然后Git 的分支名称会找到最后一个提交,因此在一个小型的三提交存储库中,您将拥有:
\n\nA <-B <-C <--master\nRun Code Online (Sandbox Code Playgroud)\n\n提交A是您所做的第一个提交,因此它没有父级。CommitB将 commitA列为其父级,并C列出B为其父级;Git 找到提交C\xe2\x80\x94,其真实名称(即其哈希 ID)看起来相当随机\xe2\x80\x94,使用名称master来保存C\ 的哈希 ID。
知道这些链接\xe2\x80\x94和弧\xe2\x80\x94都向后,从子到父,我们可以更方便地将它们绘制为链接,并添加更多提交:
\n\nA--B--C--D <-- master\n \\\n E--F--G <-- branch\nRun Code Online (Sandbox Code Playgroud)\n\n如果我们现在将分支合并回master,Git 使用这些连接箭头来找出历史上您的工作master与其他人的工作在哪里分开branch。回到 commit 处B,图节点重新加入。B所以 Git 现在可以将这个合并库中保存的快照与master提示进行比较:
git diff --find-renames <hash-of-B> <hash-of-D>\nRun Code Online (Sandbox Code Playgroud)\n\n找出你改变了什么。B然后 Git 可以将快照与提示中的快照进行比较branch:
git diff --find-renames <hash-of-B> <hash-of-G>\nRun Code Online (Sandbox Code Playgroud)\n\n合并\xe2\x80\x94以合并动词\xe2\x80\x94的行为使这两个差异并组合它们,将组合的更改应用到基本提交中的任何内容。如果一切顺利,Git 会自行提交最终结果。(如果没有,Git 会停止,让你清理混乱并自己进行提交;提交的内容取决于你如何修复 Git 发现的冲突。)结果是合并提交,不是一个而是两个父项:
\n\nA--B--C--D---H <-- master (HEAD)\n \\ /\n E--F--G <-- branch\nRun Code Online (Sandbox Code Playgroud)\n\n同样,新合并提交的源代码快照是合并自合并基\xe2\x80\x94(两个分支提示的共同起点)以来所做更改H的结果。
然而,就您而言,您创建了两个不相关的存储库。结果就是数学家所说的断开图。它可能看起来像这样,例如:
\n\nA--B--C--D---H <-- br1\n \\ /\n E--F--G\n\n L--M\n / \\\nI--J--K------N <-- br2\nRun Code Online (Sandbox Code Playgroud)\n\n如果您现在git checkout这两个分支之一,例如HEAD附加到 ,br1并运行git merge br2,Git 就会找到共同的起点,从两个分支提示向后(向左)工作。但没有共同的起点:历史互不相关。
旧版本的 Git 只会继续进行合并。除非你提供标志,否则新人会抱怨;如果您提供标志,它们就会以完全相同的方式继续并合并。
\n\n这里的问题是没有共同的起点,所以 Git 所做的就是假设共同的起点是一个真正的空提交:一个里面根本没有文件的提交。
\n\n这意味着两个分支中的每个文件都是新创建的。两个具有相同路径名的文件会导致“添加/添加冲突”:Git 说你是README.txt从头开始写的,而他们也是从头开始写的README.txt,而 Git 本身不知道如何组合这些,所以你必须自己动手。对每个具有相同名称的文件重复此操作。
另一方面,如果你创建了 aREADME.md并且他们创建了 a README.rst,则两个名称不同,因此 Git 假定README.md与 Nothing 组合的正确方法是 take README.md,而与 Nothing 组合的正确方法README.rst是 take README.rst。因此,您最终得到了这两个文件,并且 Git 认为它们现在已正确组合。(这是真的吗?我不知道。Git 也不知道,但 Git认为这是真的。)
这对所有文件都会重复:要么每个文件名对于该特定差异是唯一的,因此 Git 添加它,或者不是,因此 Git 声明冲突并让您自行解决问题。最后,如果没有文件名冲突,Git 会自行进行新的提交;如果存在冲突,Git 会让您清理它们并自行提交。我们可以绘制新的提交:
\n\nA--B--C--D---H-----O <-- br1 (HEAD)\n \\ / /\n E--F--G /\n /\n L--M /\n / \\ /\nI--J--K------N <-- br2\nRun Code Online (Sandbox Code Playgroud)\n\n这是明智之举吗?我无法回答这个问题;只有你能回答这个问题。
\n| 归档时间: |
|
| 查看次数: |
520 次 |
| 最近记录: |