Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Git 连接并提交子树的历史记录_Git_Git Commit_Git History - Fatal编程技术网

Git 连接并提交子树的历史记录

Git 连接并提交子树的历史记录,git,git-commit,git-history,Git,Git Commit,Git History,有一个git存储库,其中一部分是从另一个存储库复制粘贴的,并在某个时间点在一次提交中提交 从那时起,进行了许多改变 我想跨多个分支将过去的提交历史添加到该子树中。有没有一种不费吹灰之力就能做到这一点的方法?假设您已经(或者可以创建)了一个包含您想要添加的历史记录的git回购,那么它就可以完成了。第一件事是决定是否要重写历史 在我看来,如果你能重写历史,那是更好的选择。问题在于,这需要使用回购协议的所有人都给予一定程度的合作。(对于这种彻底的更改,理想情况下,您可以安排一个日期,让每个人都将所有工

有一个git存储库,其中一部分是从另一个存储库复制粘贴的,并在某个时间点在一次提交中提交

从那时起,进行了许多改变

我想跨多个分支将过去的提交历史添加到该子树中。有没有一种不费吹灰之力就能做到这一点的方法?

假设您已经(或者可以创建)了一个包含您想要添加的历史记录的git回购,那么它就可以完成了。第一件事是决定是否要重写历史

在我看来,如果你能重写历史,那是更好的选择。问题在于,这需要使用回购协议的所有人都给予一定程度的合作。(对于这种彻底的更改,理想情况下,您可以安排一个日期,让每个人都将所有工作推送到源站—不必合并或做任何事情,但必须全部位于单个源站repo中—然后放弃其克隆,这样他们就可以在重写后重新克隆。)

但如果重写不实用,还有另一种选择:您可以使用
git replace
逐个回购拼接历史记录。有关警告列表,请参见git replace文档,但最明显的问题是,您必须对每个要查看组合历史的克隆进行设置

在任何情况下,一旦你决定了走哪条路,并且做了任何必要的准备(即,如果你要进行硬转换,让所有人都推动),你就会希望将其他历史记录导入回购协议。最有可能的情况是,您希望创建一个源镜像克隆并完成其工作

git clone --mirror <origin-url>
也许
c
上的代码是作为提交
B
的一部分复制到您的repo中的。真实的历史可能更复杂,但在任何情况下,我能想到的都无关紧要。您需要做的是签出将文件添加到repo中的提交(
B
)。在本例中,这只是
master
的第三个祖先(遵循第一个父链接);实际上,您可能需要查找其提交ID

git checkuot master~3
现在,如果
B
所做的唯一一件事就是将
c
中的文件添加到您的回购协议中,那么您可能想要完全替换它。所以你要签出它的父母

git checkout HEAD^
如果
B
进行了其他更改,则您需要保留这些更改。具体的操作方式可能取决于这些更改是否需要添加代码。(如果不是,您可能希望在合并历史记录之前提交其他更改;如果是这样,您可能希望在合并历史记录之后重新添加它们。)而不是扩展到三个类似但不同的过程中,现在我假设这些文件是在它们自己的提交中添加的。现在您已签出该提交的父级

接下来,您将合并其他历史记录。在我们的示例中,这是
历史记录/master
的父级;同样,您可能需要一个不同的表达式来标识提交,或者可能只需要查找其提交ID

git checkuot master~3
更大的问题是,您希望代码位于回购协议的子目录中;但这大概是另一种回购协议的根源。有几种方法可以解决这个问题;这里有一个

git merge --s ours --no-commit --allow-unrelated history/master^
git read-tree --prefix=<path-to-subdirectory> history/master^
git commit
M
应具有与
B
相同的内容(
TREE
)(您可以使用
git diff
进行验证),但它具有添加的历史记录。所以剩下的就是重新设置
C
。这一重新育儿步骤是彻底重写的地方;因此,如果您不打算进行重写,您可以在这里标记新的合并,并将其留给各个克隆使用
git replace

您可以使用
git filter branch
;但同样地,
git filter branch
是一个旧工具,它的文档建议您使用
git filter repo
。我不熟悉较新的工具,可能不应该花时间宣传使用旧工具的方法,因此在这一步,我将向您介绍文档。(通常,如果你在google
git
上搜索任何命令的官方文档都不难,只要你知道你想使用哪个命令。)

最后,您可以删除
历史记录
遥控器,然后您就有了一个新的repo,可以用作
原点
(或者从中创建新原点)

请注意,此过程确实会在回购协议中留下两个不同的历史记录。从“当前”提交,您将能够“查看”任何文件的完整历史记录,但如果您
签出
到一个历史记录中,那么另一个将从索引和工作树中消失,直到您移回较新的共享历史记录


拥有一个真正统一的历史要困难得多,但在技术上并非不可能。您可以使用
filter repo
重写“other”历史记录,使其看起来总是在它的子目录中,但接下来您必须找出如何合并历史记录的时间线,并且我只提供手动方式来实现这一点。

感谢您提供的详细答案。从filter repo的文档来看,这似乎只是git replace之外的一个步骤:
git replace--graft$commit id$graft id
git filter repo--force
git merge --s ours --no-commit --allow-unrelated history/master^
git read-tree --prefix=<path-to-subdirectory> history/master^
git commit
          A -- B -- C -- D -- E <--(master)
           \
            M <-(HEAD)
           /
a -- b -- c -- d <--(history/master)