将两个不同的git存储库放在一起,而不会丢失任何历史记录

时间:2012-11-06 13:13:15

标签: git

在我目前的项目中,我遇到了一个有趣的问题:git:

自项目开始以来,更改存储在客户端远程服务器上的SVN存储库中。在开发过程中,我开始并行使用本地git存储库,以便我在不破坏当前版本的情况下更轻松地测试新功能。可悲的是,git-svn无法工作,这会让我的生活变得更轻松。

现在我的客户端切换到另一台服务器,在这个过程中,他们将SVN repo移动到git(使用git2svn)。

虽然我对此感到高兴,我现在有两个问题

  1. 由于我参与了一项更大的功能,因此我没有在SVN工作7天。我在一个本地功能分支工作,并将其备份到我的本地服务器,但现在远程git仓库的SVN副本与我的本地版本相比已过时。

  2. 由于远程仓库是由git2svn创建的,因此它与我自己的仓库完全不同(消息:警告:Repo没有常见的提交。) - 这使得标准合并成为不可能。

  3. 现在我的期望目标

    1. 合并两个repos以使我当前的版本成为已签入的版本并再次推送到原点。

    2. 保留两个回购的历史记录(来自SVN的旧记录以及过去7天来自我的git的记录)

    3. 到目前为止我尝试了什么

      我尝试克隆远程git(来自svn)并将我的本地repo合并到它中。我在两个版本中都改变了153次冲突。接受“他们的”(即我的最新开发)会丢失文件的历史记录(它只是从我的并行git repo初始化开始)。

      我的想法是,我可以为过去7天的每次提交创建一个补丁,并使用相应的提交消息(即“手动合并”)将其提交到新的repo中。在我编写脚本来执行此操作之前,我想询问是否有内置方法来执行此操作。

      提前致谢!

      更新:我尝试了很多解决方案,但每一个都让我失望。基本问题是我现在有两个分支,不是一个公共提交,而是相同的树结构。这导致合并冲突,如“在两个分支中添加”,因为git不知道myFile.txt" and myFile.txt“是相同的并且可以合并。而是我必须手动合并150个文件,我在那一周发生了变化 - 我不能也不会这样做。

      到目前为止,我最好的方法是为更改创建补丁并将其应用于“新”仓库。但是由于树不匹配,我没有开始创建一个不会失败的补丁。我还没有找到正确的提交来启动补丁信息。

      分辨率

      TL; DR:没有。你可以在较小的邪恶之间做出选择。

      1. 您可以使用merge method desribed here但它会将SVN中的单个文件历史记录替换为您的side-git中的文件历史记录(即您无法查找为什么此文件已更改3个月前如果你的其他回购只有2个月)。但从积极的方面来说,您仍然可以通过git log将您的更改合并到全局历史记录中。

      2. 我最后选择的另一个选项是使用我的git repo的当前状态复制并替换“new”(又名SVN)repo中的所有文件(通过cp -vru,但省略{ {1}} - 文件夹和所有生成的文件)。这让我放松了一周的历史,但是让我回顾过去,直到我喜欢的项目开始。 为了减轻这种损失的痛苦,我使用.git在提交消息中详细描述了我的行为,这至少使我有机会返回此条目并查看带有描述的消息。 但是,当然这对于文件删除不起作用,并且您无法知道哪个更改实际上属于biiiig提交消息的哪个部分。

2 个答案:

答案 0 :(得分:3)

我刚用我的存储库测试了这个。我创建了一个新的克隆,它代表了客户的新存储库。然后我将旧版本的内容复制到新文件夹,并在其中初始化了一个存储库。我添加了内容,并做了一些提交。

这样我就有两个没有共同提交的存储库。

现在,在新的存储库中,我将我的副本(在下面:mine)中添加为远程并获取其内容。然后我检查了一个新分支给我的主人:

git checkout -b new mine/master

所以我可以从这个分支访问我的单独存储库的所有历史记录。接下来,我使用递归合并策略将更新后的master合并到我的分支中,但支持我们的(新)冲突更改:

git merge master -s recursive -Xours

这将自动合并所有内容,如果发生冲突,它将通过仅使用我们的版本自动解决这些问题,从而有效地丢弃主数据中的更改。

因此,您最终应该使用合并的分支,并且两个存储库中的所有历史记录仍然存在。

答案 1 :(得分:1)

如果我理解正确,你会遇到这样的情况:

remote repo:
A - B

your repo
C - D - E - F

其中提交A实际上与C相同,并且提交B到D(关于包含的文件)。我相信可能有用的只是通过做类似

之类的事情来简化你对最新远程提交的工作
git rebase --onto B D

这应该从D到你的HEAD(例如F)进行提交,并将它们作为补丁应用到B,结果如下:

A - B - E' - F'

这应该与您的本地更改相同,并且可以舒适地推送到远程存储库。