远程git repo和svn之间的无休止冲突

时间:2012-10-02 02:13:26

标签: git git-svn

我在这里结束了我刚刚创建的git-to-svn设置。我已经设置了一个存储库,其中包含两个远程repos,一个基于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/master来关闭foo.dat文件。这样很好,但试图运行git svn rebase会导致冲突。完全期望,所以我完成了编辑冲突和使用svn rebase --continue的步骤。但随后混乱开始了。尝试运行git rebase origin/master以从repo中删除其他更改后,我在同一个foo.dat文件上发生冲突。我已经把它变成了一个状态,如果我解决了svn的冲突,那么git就会失败,反之亦然。最令人沮丧的是,我似乎无法找到一种方法让存储库恢复到一个状态来恢复这个混乱。现在,我有能够彻底吹走回购并再次尝试的奢侈品,但是在未来开发人员使用它时,如果我让自己进入这样的状态,我真的很想知道如何离开。关于正在发生什么以及如何结束常数合并的任何提示都将非常受欢迎。

谢谢!

1 个答案:

答案 0 :(得分:4)

这些冲突与git-svn无关。

如果有一个遥控器:remote1和remote2,并且这些遥控器的历史已经分歧,那么rebase操作总是会将第一个遥控器的历史重写在另一个遥控器之上。

假设一个具有由master分支引用的单个提交A:

$ 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

注意的? Rebase操作将提交R1置于R2之上。正如您所料,在remote1 / master之上重新定义给定历史只需交换提交R1和R2并生成完全相同的冲突。

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

现在回到git-svn。对于您的情况,合并分歧的历史记录将不起作用,因为当您运行git svn dcommit时,git-svn始终会重写您的本地历史记录。相反,你必须做以下事情:

  1. 从Git存储库获取和重新提交提交:

     $ 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
    
  4. 第三步非常危险,可能会导致失去历史。所以,我不建议这样做 - 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 documentationgit-svn比较页面。

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