git-svn:将现有 git 存储库的全部历史提交到一个空的 Subversion 子目录中

git-svn: commit whole history of an existing git repository into an empty Subversion sub-directory

我一直在我的计算机上本地处理一些代码,使用 git(没有远程)跟踪修改。 该代码现在将成为更大项目中的一个模块,其代码库存储在 Subversion 中(类似于 https://svnserver/svnroot/project/trunk/module_x),所以我想我可以使用 git-svn 来管理 Subversion存储库作为远程。我记得之前为另一个项目做过,但找不到 modus ope运行di(中间更换了计算机)。

这是我尝试过的:

cd ~/mygitrepo/
git svn init https://svnserver/svnroot/project/trunk/module_x
git svn fetch
git svn rebase

最后一条命令产生以下错误消息:

Unable to determine upstream SVN information from working tree history

我在某处读到这可能是因为 Subersion 中的目录是空的,所以我尝试将一个虚拟文件单独提交到 SVN,然后 运行:

git svn fetch
    A   dummy.txt
r10744 = 89294ba713c6fed368f3b879c8dc7744b1015308 (refs/remotes/git-svn)

但是,我在 git 存储库中找不到 dummy.txt 文件,rebasedcommit 将继续显示相同的错误消息。 我做错了什么?

您签出的分支不是来自颠覆,因此git svn不知道如何使用它。

然而,

Git 确实如此,因此您需要做的是使用普通 git rebase 变基到 git-svn (refs/remotes/git-svn)。然后历史将包含来自颠覆的提交,git svn dcommit 将知道在哪里提交它。

另一件事是,您的更改需要放在正确的子目录中 ,然后再 尝试对其进行变基,因为 git rebase 不支持移动到子目录中。 git merge 确实如此,通过 subdirectory 策略,但使用合并将作为单个提交导出到 Subversion。如果你想导出完整的历史,而你没有在正确的目录 所有提交 中,你将不得不使用 git filter-branch 来修复它。

Jan 提供的答案给出了我遇到的错误的基本原理,并指出普通的旧 git rebase --onto 是正确的解决方案,但缺少实际命令。

我最初提议将这些命令作为对他的回答的编辑,但被拒绝了,所以这里是:

git checkout -b svnrebase git-svn            # create a temporary branch
git cherry-pick master~1                     # cherry pick the first  commit
git rebase --onto svnrebase master~1 master  # rebase the 2nd through current commit
git svn dcommit                              # finally commit the results to svn

注意 必须更改 master~1 以引用您对 git 大师的第一次提交。在这里,我们假设我们有一个只有两次提交的 git 回购协议。

有必要创建一个临时分支和 cherry-pick 第一次提交到 master 因为 rebase --onto 只 rebase 了 after master~1(并且 master~2 引用不会只存在两次提交)。