2

我刚刚创建了一个 git-to-svn 设置,我对此束手无策。我已经设置了一个包含两个远程存储库的存储库,一个基于 svn,另一个基于远程 git:

svn-remote.svn.url=https://subversion.acme.com/svn/sales/portal/trunk
svn-remote.svn.fetch=:refs/remotes/git-svn
remote.origin.url=mottinger@git.tkknow.com:/gitroot/acme-gtm-2-0.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

一旦我设置了这个,我就可以将提交从 git repo 移动到 svn repo,如下所示:

git fetch origin
git rebase origin/master (linearizes commits to svn)

git svn rebase
git svn dcommit

一切都很好,直到我决定测试我将如何处理冲突。我创建了一个 foo.dat 文件,并从 svn 端在其中添加了一行,并在 git 端创建了一个相应的文件,其中一行表明它来自 git。我跑过去git fetch origingit rebase origin/masterfoo.dat 文件放下。这很好,但是尝试运行git svn rebase导致了冲突。完全符合预期,所以我完成了编辑冲突和使用 svn rebase --continue 的步骤。但随后混乱开始了。尝试运行后git rebase origin/master为了从 repo 中删除其他更改,我在同一个 foo.dat 文件上发生冲突。我已经把它变成了一个状态,如果我解决了 svn 的冲突,git 就会失败,反之亦然。最令人沮丧的是,我似乎无法找到一种方法让存储库恢复到恢复这种混乱状态的状态。目前,我有幸完全吹走 repos 并重试,但将来当开发人员使用它时,如果我让自己进入这样的状态,我真的很想知道如何摆脱。任何关于正在发生的事情以及如何结束不断合并的提示将不胜感激。

谢谢!

4

1 回答 1

4

这些冲突与 git-svn 无关。

如果一个人有几个遥控器:remote1 和 remote2,并且这些遥控器的历史已经不同,那么 rebase 操作总是会重写第一个遥控器的历史。

假设一个提交 A 被 master 分支引用:

$ git log master
* commit A
Initial commit

还有几个历史不同的遥控器:

$ git log remote1/master
* commit R1
Added conflict.txt at remote1
* commit A
Initial commit

$ git log remote2/master
* commit R2
Added conflict.txt at remote2
* commit A
Initial commit

现在,将本地历史重新设置为如下:

$ git rebase remote1/master
$ git log master
* commit R1
Added conflict.txt at remote1
* commit A
Initial commit

现在尝试在 remote2/master 之上重新设置本地历史记录,得到冲突并解决它们:

$ git rebase remote2/master
$ git log master
* commit R1
Added conflict.txt at remote1
* commit R2
Added conflict.txt at remote2
* commit A
Initial commit

注意到了吗?变基操作将提交 R1 置于 R2 之上。如您所料,在 remote1/master 之上重新设置给定历史记录只是交换提交 R1 和 R2 并生成完全相同的冲突。

如何解决?好吧,您必须使两个遥控器的历史记录相同。最安全的方法是合并提交 R1 和 R2,并将生成的合并提交推送到 remote1 和 remote2。

现在回到 git-svn。对于您的情况,合并不同的历史记录将不起作用,因为 git-svn 总是在您运行时重写您的本地历史记录git svn dcommit。相反,您必须执行以下操作:

  1. 从 Git 存储库中获取和 rebase 提交:

     $ git fetch origin
     $ git rebase origin/master (linearizes commits to svn)
    
  2. 将更改发送到 SVN 存储库:

     $ git svn rebase
     $ git svn dcommit
    
  3. 将从 SVN 获取的提交推送回源:

     $ git push -f origin master:master
    

第三步是极其危险的,可能会导致历史丢失。所以,我不建议这样做—— git-svn 只是不支持这样的工作流程。

相反,您可以尝试SubGit。SubGit 是用于 SVN 和 Git 存储库的双向服务器端镜像工具。

如果您对 Subversion 存储库具有本地访问权限,则可以将 SubGit 安装到其中:

$ subgit configure $SVN_REPOS
# Adjust $SVN_REPOS/conf/subgit.conf to specify your branches and tags
# Adjust $SVN_REPOS/conf/authors.txt to specify git & svn authors mapping
$ subgit install $SVN_REPOS
...
$ INSTALLATION SUCCESSFUL

结果,您获得了转换后的 Git 存储库,该存储库自动与原始 SVN 存储库同步。

如果您没有 SVN 存储库的本地访问权限,您可以考虑使用即将进入早期访问阶段的 SubGit 2.0。SubGit 2.0 允许在 Git 存储库和远程 SVN 存储库之间设置双向镜像。

SubGit 是一个商业产品。它对开源和学术项目以及最多 10 个提交者的项目都是免费的。

有关详细信息,请参阅SubGit 文档git-svn比较页面。

全面披露:我是 SubGit 开发人员之一。

于 2012-10-03T01:01:38.110 回答