Git-svn合并了两个SVN分支

时间:2013-04-18 08:33:34

标签: git git-svn

我已经在git-svn上阅读了许多SO问题和博客并进行了合并。其中一些(特别是git-svn手册页)在我计划dcommit的分支附近的任何地方使用合并警告

其他人,比如SO answer,只要我使用我在dcommitting之前删除的一次性功能分支,就表示合并正常。

我有两个长寿SVN(和git)分支的设置:

  • 主干(git-svn:svn/trunk,git:master) - 稳定分支
  • branches / devel (git-svn:svn/devel,git:devel) - 我从中分支功能分支的主要开发分支(我可以忍受将它们重新定位回devel而不是合并。)

Snapshot of current state in Source Tree

在上图中,(1)显示过去的SVN历史记录,其中branches/devel已合并到trunk

(2)表明我已成功dcommitted我当前的发展回到SVN。

问题:我可以使用git-svn合并两个SVN分支,以便历史记录显示合并点(如SVN本身可以做到的)?换句话说:如果我dcommit来自master会发生什么,如(3)

这会搞砸我的SVN(或git)历史吗?或者这简直忘记devel完全合并到master

编辑:如果git忘记devel已合并到master,那么dcommiting与点之间是否存在差异(3)并将所有提交应用为单个补丁

2 个答案:

答案 0 :(得分:14)

进一步深入研究此事,我发现git支持在svn:mergeinfo时在SVN分支上设置dcommit属性:

git svn dcommit --mergeinfo "/branches/somebranch:1-3"

NB! svn:mergeinfo覆盖与命令行上给出的内容一样,所以要小心列出以前的合并

虽然更新的git版本添加了config参数来自动设置此属性:

config key: svn.pushmergeinfo

我在使用自动mergeinfo时遇到了一些麻烦 - 由于某种原因或其他GIT计算错误,我无法让它工作。

解决方案:git-merge-svn

为了自动完成这个过程,我写了一个shell脚本git-merge-svn,它可以用来合并两个SVN分支,并在dcommit上设置正确的svn:mergeinfo

该脚本处理两种情况:

  • 分支未在git中合并 - 将事先git merge
  • 分支已经在git中合并(但不在SVN中) - 将遍历前一个祖先进行合并的提交修订。

使用这个脚本,我只能在git端生成这些合并并保留合并信息,以便GIT图很好地显示日志:

git-merge-svn result

使用示例:

  1. devel6
  2. 进行一些提交
  3. dcommit devel6 到SVN(必需获取提交的SVN修订号)
  4. 查看 testtunk6 - 是的,我知道我在名字中写了一个拼写错误; - )
  5. git merge-svn devel6
  6. 最后一个commant输出:

    % git merge-svn devel6
    About to do an SVN merge: devel6 -> testtunk6
    
    * NEW MERGE COMMIT
    |\
    | * devel6 [7b71187] (r102)
    * | testtunk6 [0682a45] (r101)
     \|
      * [273d6d6] (r100)
    
    
    STEP 1: GIT merge
    Executing:
      git merge devel6
    
    Continue? (y/n) [n]: y
    Merge made by the 'recursive' strategy.
     testfile | 1 +
     1 file changed, 1 insertion(+)
    
    STEP 2: SVN dcommit
    
    executing:
    git svn dcommit --mergeinfo
    /idp/branches/devel:9-32,35-41 /idp/branches/devel6:89 /idp/branches/devel6:94 /idp/branches/devel6:93 /idp/branches/devel6:96 /idp/branches/devel6:97 /idp/branches/devel6:99 /idp/branches/devel6:100 /idp/branches/devel6:102
    
    Continue? (y/n) [n]: y
    Committing to https://my.svn.host/svn/auth/idp/branches/testtunk6 ...
      M testfile
    Committed r103
      M testfile
    Found merge parent (svn:mergeinfo prop): 7b71187fc371d3f86658c5850009e63be88157ac
    r103 = 87759323cbadd38bac78087d57b6870a926287e7 (refs/remotes/svn/testtunk6)
    No changes between 3fb2168cfbbe605fbd810d76513443203a85a549 and refs/remotes/svn/testtunk6
    Resetting to the latest refs/remotes/svn/testtunk6
    

答案 1 :(得分:4)

Git和Svn有不同的数据结构来保存历史记录。

Svn使用一棵简单的树。即每个提交只有一个父,但一个提交可能有几个子(分支)。所以,Svn不支持合并。他们称之为“合并”的东西实际上是变更集移植,git中最接近的类比是rebase或者cherry-pick。从版本1.5开始,Svn支持元信息属性svn:mergeinfo,它有助于以某种方式跟踪“合并”的内容,但它看起来主要是一种解决方法,这解释了为什么Svn中的分支如此难以使用。合并点是一个提交,它将所有合并的变更集和冲突解决方案压缩为一个变更集,可能使用svn:mergeinfo属性进行注释。

Git使用Directed acyclic graph这是描述历史合并和分支的非常自然的方式。合并点只是另外两个(或更多!)父项的提交。所以,你的(3)图片是合并提交。因此,所有历史记录看起来都很自然,它可以在当前点的历史图表上访问所有提交。

Git-Svn网桥尝试尽力处理Svn设计缺陷,在执行dcommit之前,它通常会重新绑定当前Svn分支顶部的所有合并提交。 〜2年前,git-svn无法提供svn:mergeinfo,所以你要问的是不可能的。此外,当你dcommit时,git会创建一个“难以”链接到svn提交的“双胞胎”提交,因此它会重写原始提交。