将两个存储库合并为一个,都具有分支

时间:2018-08-31 12:25:45

标签: git bitbucket git-merge branching-and-merging

我有两个独立的存储库-后端和前端。我想将它们结合起来,所以我在考虑类似的东西:

git clone git@server.com:backend.git
git clone git@server.com:frontend.git
cd frontend
mkdir frontend
git mv !(frontend) frontend
git commit -a -S -m "Moving frontend into its own subdirectory"

cd ../backend
git remote add frontend ../frontend
git fetch frontend
git checkout -b feature/merge-front-back
git merge -S --allow-unrelated-histories frontend/master
git push origin feature/merge-front-back
git remote rm frontend

...现在,在确认合并后:

git checkout master
git merge feature/merge-front-back

所以我的第一个问题是:这是个好计划吗?您看到任何缺陷或更好的方法了吗?

还有2个问题..前端分支呢? 我中的大多数人现在都不需要(也许永远不需要),但希望将来有选择地与他们合并。 我是否需要重复上述过程,但是对于每个前端分支,分别将frontend / branches / feature1合并到backend / branches / front-back-merge-feature1,依此类推?

(我假设后端分支合并到包含前端目录和历史记录的“新”主分支时不会有问题)

1 个答案:

答案 0 :(得分:4)

  

这是个好计划吗?您看到任何缺陷或更好的方法了吗?

通过“这是一个好的计划”,我假设您的意思是“这组命令是完成我打算要做的事情的好方法”。在这方面,还有其他的方法,但我不会说是好是坏。

如果您希望最终的仓库具有前端分支,则缺少一个步骤;我会在下面解决。

更笼统地说-我将提供警告,几乎总是有人试图通过将多个项目组合到一个仓库中来解决的任何问题,都将被处理组合结构的更大问题所取代。您必须确定这些项目在逻辑上是否分离,但是通常,我看到结合回购是错误方向的事情。

但是,如果您坚信它们应该是一个回购协议,那么这些命令(一目了然)似乎和其他命令一样好。我猜最明显的问题是,为什么不尝试一下呢?唯一可以破坏的是新创建的克隆。

  

前端分支如何?

当您从fetchfrontend时,合并的仓库将为每个frontend分支获得“远程跟踪参考”。因此,对于frontend分支master,您将获得remotes/frontend/master

但是,当您remove遥控器时,这些将被删除。对于master而言,这并不重要(因为您已将frontend/master合并到master中)。对于其他分支,您需要告诉git保留对它们的引用-当然,如果保留的引用是一个分支,这将很方便。一种方法是

git fetch frontend refs/heads/*:refs/heads/frontend/*

这里您要为分支创建frontend命名空间,并将frontend中的所有分支添加到该命名空间。 (只要您在后端存储库中没有名为frontend的分支或尚不存在的frontend分支名称空间,就可以了。如果您出于某种原因拥有其中一个,您必须为名称空间使用其他名称。)

这些新创建的参考位于refs/heads下,因此它们将被视为适当的分支(而不是远程跟踪参考),并且在删除原点时不会将其删除。从那时起,它们与您的后端分支没有什么不同。

将来,当您将frontend分支合并到master时,您可能遇到问题,或者您可能没有。 git将尝试解决所有文件移动引起的冲突;但是请记住git不会真正跟踪文件移动-相反,它会在事实发生后通过启发式方式重建它们-因此这种机制并不完美。

如果您担心此类问题-或进行了一些测试合并并发现存在不可接受的问题级别-那么可以选择重写frontend/*分支的历史记录,使其看起来像frontend/文件夹下的文件“总是”。如果要这样做,我将在合并存储库之前执行该操作。即在克隆frontend之后,我将重写克隆的历史记录,而不是创建新的提交来移动文件。

(您建议针对每个分支重复在master上执行的过程类型。尽管您可以对其进行测试,但我不确定这样做是否会很好。问题在于,{{1} }被视为无关历史记录的合并,后续其他master个分支的合并将不会进行。为了使这些合并正常工作,git仍必须正确解释文件移动-实际上,必须进行解释在合并的两个“方面”都正确。)

如果您选择重写frontend的历史记录,最直接的方法是将frontendgit filter-branch脚本一起使用,该脚本会将文件移动到子目录中。有关详细信息,请参见--tree-filter文档。 (https://git-scm.com/docs/git-filter-branch