4

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

自项目开始以来,更改都存储在我客户端远程服务器上的 SVN 存储库中。在开发过程中,我开始并行拥有一个本地 git 存储库,以便在不破坏当前版本的情况下更轻松地测试新功能。可悲的是 git-svn 失败了,这会让我的生活更轻松。

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

虽然总的来说我对此感到高兴,但我现在有两个问题

  1. 由于我致力于一个更大的功能,我没有承诺 7 天的 SVN。我在本地功能分支中工作并将其备份到我的本地服务器,但与我的本地版本相比,现在作为远程 git repo 的 SVN 副本已经过时。

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

现在我想要的目标

  1. 合并两个存储库以将我当前的版本签入一个并再次推送到原点。

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

到目前为止我尝试了什么

我试图克隆远程 git(来自 svn)并将我的本地 repo 合并到其中。我有 153 个与“在两个版本中更改”的冲突。接受“他们的”(即我的最新进展)会丢失文件的历史记录(它只是从我的并行 git 存储库的初始化开始)。

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

提前致谢!

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

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

解析度

TL;DR:没有。您可以在较小的邪恶之间进行选择。

  1. 您可以使用此处描述的合并方法,但它会将 SVN 中的单个文件历史记录替换为您的 side-git 中的文件历史记录(即,如果您的其他存储库仅为 2,则您无法查找 3 个月前更改此文件的原因个月大)。但从积极的方面来说,您仍然可以通过 git log 在全局历史记录中将您的更改合并在一起。

  2. 我最终得到的另一个选择是用我的 git repo 的当前状态复制和替换“新”(又名 SVN)repo 中的所有文件(通过cp -vru但省略.git-folder 和所有生成的文件)。这让我失去了一周的历史价值,但仍然让我回顾过去,直到我喜欢的项目开始。为了稍微减轻这种损失的痛苦,我在提交消息中制作了我所做的详细总结,使用git log --date=short --pretty="format:%cd - %s" --name-status它至少让我有机会回到这个条目并查看带有描述的消息。但是,这当然不适用于文件删除,并且您无法知道哪个更改实际上属于 biiiig 提交消息的哪个部分。

4

2 回答 2

3

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

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

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

git checkout -b new mine/master

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

git merge master -s recursive -Xours

这将自动合并所有内容,如果发生冲突,它将仅使用我们的版本自动解决这些问题,有效地丢弃 master.xml 中的更改。

因此,您应该最终得到一个合并的分支,并且来自两个存储库的所有历史记录仍然存在。

于 2012-11-08T12:40:21.693 回答
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'

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

于 2012-11-06T13:19:18.600 回答