将两个有共同历史记录的SVN仓库迁移到Git

4
我计划迁移一堆代码库的 svn 到 git。其中两个处于特定状态。
一个项目在 svn 存储库中已经开发完成。由于各种约束,该项目在某个时候被分叉了。复制 svn 存储库来制作分叉。从那时起,这两个项目分别演进。除了主干之外,两个存储库中都不存在任何分支或标签。
原始项目开发了重要的功能,需要将其移植到分支上。在当前情况下,可以通过从不同版本创建补丁并将其应用于分支项目来完成此操作。这样做的优点是短期内方便,但长期具有许多棘手的后果。
我们可以拥有两个不同的 git 存储库,并通过拉取请求进行跨分支移植,但这可能缺乏可用性(我们没有使用 GitHub)。此外,可能会出现我们希望通过模块化设计重构将分支重新集成到父项目中的时间。另一种方法是将两个 svn 存储库合并为单个 git 存储库的不同分支,并从那里管理后续合并(具有所有它所提供的优点)。
理想情况下,我想重新创建项目的真实历史记录,即具有以下内容的 git 存储库:
- 一个包含分叉之前的提交的单一分支 - 两个不同的分支,由父分支和分叉分支的提交组成
一个有趣的事实可能会有所帮助,以下命令为通用提交生成相同的 SHA1:
git svn clone -s -A svn.authors --no-metadata http://subversion.foo.local/repo/path git_migration

我不关心--no-metadata,因为这是单向迁移。
如果可能的话,我该如何实现这样的结果?
2个回答

2

既然您有一种方法可以克隆具有相同哈希值的常见提交的SVN存储库,那么这应该可以工作。

git svn clone -s -A svn.authors --no-metadata http://subversion.foo.local/repo1/path git_migration
git svn clone -s -A svn.authors --no-metadata http://subversion.foo.local/repo2/path git_migration-2
cd git_migration
git branch repo1 # Branch for first repo
git reset --hard <highest_common_hash> # To have only common history on master
git checkout -b repo2 # Branch for second repo
git pull ../git_migration-2 master

现在,您必须在master和2个不同SVN存储库的分支中有共同的历史记录。


我想出了一个快速而简单的命令来查找最高公共哈希值:cd git_migrationgit log | grep 'commit' | cut -f2 -d' ' | while read hash; do (cd ../git_migration-2; git log | grep "$hash"); done | head -1。没有匹配就退出,所以可以自由使用Ctrl+C。注意,这是O(m*n)复杂度(我们有大约2000个版本,这是一次性操作,所以我们不太在意)。 - Lloeki
1
@Lloeki:看一下git merge-base,我认为它可以做这些事情。 - sehe
git remote add -f -t master migration2 ../git_migration-2 然后 git merge-base $(cat .git/refs/heads/master) $(cat .git/refs/remotes/migration2/master) 产生了与我的 hack 相同的提交,只是速度快得多(多得多!)。感谢 @sehe。 - Lloeki
1
@Lloeki:如果你只说 git merge-base master migration2/master,它会更短 :) (符号名称 - 称为 refs - 将自动解析;请参见 git rev-parse - sehe
哎呀,我怎么会忽略那个呢?我想我还有很长的路要走 :) - Lloeki

2

通常使用git的Graft Points将历史记录连接到单个根。

我建议您参考https://git.wiki.kernel.org/index.php/GraftPoint

简单来说,您只需告诉git哪些版本共享某个父版本(如果您愿意,可以将其视为一个神奇的“合并”结果)。 一旦您满意,就可以使用git filter-branch使其永久保存。

示例来自man git-filter-branch

echo "$commit-id $graft-id" >> .git/info/grafts
git filter-branch $graft-id..HEAD

尽管这只是对我的问题的部分和相当残酷的回答,但每当我想要从git-svn方面强制记录合并时,它让我感到很有趣。 - Lloeki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接