我必须合并两个单独的 git 存储库 ORIG 和 WORK。WORK 是作为 ORIG 子目录的衍生品创建的,其中有一些尚未提交给 ORIG 的实验性更改。
~> mkdir WORK
~> cp -a ORIG/src/* WORK
~> cd WORK
~/WORK> # apply some experimental changes to WORK
~/WORK> git init
~/WORK> git add .
~/WORK> git commit -m "Entirely disconnected commit."
Run Code Online (Sandbox Code Playgroud)
因此,WORK 不知道它源自 ORIG,并且缺少src文件名的前缀。
是否有可能
./src/FILE而不是),./FILE目前我已经解决了这个问题
git mv'将 WORK 中的每个文件复制到新创建的./src目录中,融入ORIG/master工作master
git merge -X theirs --allow-unrelated-histories ORIG/master
Run Code Online (Sandbox Code Playgroud)
使用theirs合并策略,并手动重新应用更改,用于git diff查找相关部分,
但结果充其量只是一段不洁的历史:
./src,来自外部的文件./src根本不存在。我如何产生一个干净的、合并的历史?
\n\n\n是否有可能
\n
不知怎的,这是相当开放的,所以是的。
\n\n\n\n\n\n
\n- 识别 ORIG 中创建 WORK 的提交
\n
最简单的方法就是:记住它。另一种方法是找到一个提交,其中该提交的源树与您保存的子树相匹配。这很困难(但并非不可能,如果您愿意进行精确的子树匹配,并且速度相当快:使用子树的哈希 ID),但打开了多个匹配的可能性:取决于源存储库,看起来很可能许多提交都有ORIG一个与根提交树匹配的子树WORK。在这种情况下,有可能但不能保证它们中的任何一个都是合适的。
问题是,它并没有真正给你买任何东西\xe2\x80\x94,好吧,还没有。它可能会使合并步骤更容易(见下文)。
\n\n\n\n\n\n
\n- 更改 WORK 以便存在完整文件路径(即
\n./src/FILE而不是)./FILE
是的,有点;或不,取决于你的意思。您可以使用git filter-branch创建存储库的副本,并在副本中进行此更改。副本不再与原始版本兼容,但如果您打算举办卖旗日并将每个人都切换到副本,那么这非常简单。
\n\n\n\n
\n- 将存储库合并在一起而不丢失历史记录?
\n
这是真正棘手的部分。
\n\nGit 永远不会真正丢失历史:在 Git 中,历史就是(是?)提交。提交是永久且不变的。但是,Git通过分支名称(以及其他名称,例如标签)来记住提交,因此,如果您强制分支名称停止记住某些提交\xe2\x80\x94,则将所有已过滤的提交复制git filter-branch到新的提交后会发生什么commits\xe2\x80\x94 那么这些提交实际上就被忘记了。最终,如果您删除所有查找这些提交的能力,Git 将通过垃圾收集真正删除它们:。git gc
同样,这就是git filter-branch它的工作方式:您告诉它将每个提交复制到一个新的提交,新的提交与原始提交非常相似,只是每个提交FILE都已重命名为src/FILE. 然后,您使所有分支名称都指向新副本的最后一个,而不是原始副本的最后一个。您删除所有保存的原始名称(git filter-branch复制原始引用以防万一),删除所有其他备用安全带和安全线(git reflog expire等),并强制执行垃圾收集通过,然后噗,您原来的提交集消失了,并且您只有替换提交。
但是:提交是快照。 您拥有 中的所有快照ORIG,您可以向其中添加您喜欢的所有快照WORK(或通过 制作的修改后的替换副本git filter-branch)。结果只是提交的总和。这不是一部两套作品交织在一起的历史:它只是一部实际上说“在<日期>这些作品被合并在一起的历史,在那之前我们就有了这两个独立的历史” 。例如,ORIG可能看起来像这样:
root--o--(history graph)---o <-- master\n \\ /\n o--(branchy)--o--o <-- feature\nRun Code Online (Sandbox Code Playgroud)\n\n您的过滤结果WORK可能如下所示:
o--o\n / \\\nroot2--o--o------o <-- master\nRun Code Online (Sandbox Code Playgroud)\n\n将两者放入一个存储库中,将WORK\'s的名称更改master为其他名称,您将获得:
o--o\n / \\\nroot2--o--o------o <-- workmaster\n\nroot--o--(history graph)---o <-- master\n \\ /\n o--(branchy)--o--o <-- feature\nRun Code Online (Sandbox Code Playgroud)\n\n您现在可以运行git checkout master; git merge workmaster,解决所有合并冲突\xe2\x80\x94Git 会抱怨src/*两个提示提交中的每个文件master都有添加/添加冲突,因为共同的起点是“无文件”\xe2\x80\ x94 并从合并结果中进行提交:
o--o\n / \\\nroot2--o-------------o------o <-- workmaster\n \\\nroot--o--(history graph)---o--o <-- master\n \\ /\n o--(branchy)--o--o <-- feature\nRun Code Online (Sandbox Code Playgroud)\n\n现在您有了一个ORIG基于 - 的存储库,其中包含一个新的提交,该提交将两个历史记录连接起来。
如果这足以满足您的目的,那么您现在就完成了。如果没有,其余的可能不会真正有帮助,但无论如何我都会概述一下。
\n\n直截了当git merge很困难,因为所有文件都存在冲突。但是,如果您找到了文件全部匹配的点,则可以使用git replace进行临时移植,而不是像上面那样进行合并。然后,您可以更轻松地合并,甚至可能使替换永久化(使用另一个filter-branch,以及这意味着的所有内容)。
X我们从与上面相同的绘图开始,但选择“root2”与主存储库中的某些提交匹配的点。请注意,我也给这里的孩子贴上了标签root2:
o--o\n / \\\nroot2--Y--o------o <-- workmaster\n\nroot--o--...--X----...-----o <-- master\n \\ /\n o--(branchy)--o--o <-- feature\nRun Code Online (Sandbox Code Playgroud)\n\n我们现在用来git replace告诉 Git:不要查看 commit Y,而是查看新的替换提交Y\',这样大多数 Git 都会看到:
o--o\n / \\\n Y\'---o------o <-- workmaster\n /\nroot--o--...--X----...-----o <-- master\n \\ /\n o--(branchy)--o--o <-- feature\nRun Code Online (Sandbox Code Playgroud)\n\n提交Y并root2仍然在那里,只是 Git 不再查看它们(除了git gc、 或使用该--no-replace-objects选项运行的任何命令)。
Y为了进行此替换,我们在 \xe2\x80\x94之后找到子提交,root2幸运的话只有一个,但如果有多个,我们可以将git replace它们全部 \xe2\x80\x94 并运行:
git replace --graft <hash-of-Y> <hash-of-X>\nRun Code Online (Sandbox Code Playgroud)\n\n这使得替代者提交Y\'。这给了我们上面制作的绘图,现在git merge将被视为X合并两个分支提示的公共提交。
我们的合并会更容易(也许),我们得到:
\n\n o--o\n / \\\n Y\'---o------o <-- workmaster\n / \\\nroot--o--...--X----...-----o--o <-- master\n \\ /\n o--(branchy)--o--o <-- feature\nRun Code Online (Sandbox Code Playgroud)\n\n作为我们的结果。
\n\n如果我们运行无过滤器git filter-branch\xe2\x80\x94 并且确保不使用git --no-replace-objects filter-branch\xe2\x80\x94,过滤器分支将复制存储库而不使用原始存储库Y并root2提交,而是使用X和Y\'。换句话说,这些移植物现在永久存在于我们新的、再次重写的存储库中(另一个卖旗日转换,尽管运气好或计划良好,但在同一天,因此只有一个卖旗日)。
| 归档时间: |
|
| 查看次数: |
2978 次 |
| 最近记录: |