【问题标题】:How to fool git-svn to recognize merges made with svn?如何欺骗 git-svn 以识别使用 svn 进行的合并?
【发布时间】:2009-06-02 05:44:38
【问题描述】:

我们有一个稳定的主干和不稳定的开发分支的 SVN 设置。开发工作(大部分)在分支上完成,然后在部署前合并到主干。

我使用 git-svn 作为我的 SVN 客户端。我从不稳定到主干的合并过程如下:

git svn fetch
git co -b trunk svn/trunk 
git merge --no-ff svn/unstable
git svn dcommit

svn/* 是远程 SVN 分支。

这当然要求在我完成之前没有人向主干提交任何东西,但这在实践中不是问题。

这个过程的好处是 git 现在将合并提交的父级记录在我的本地存储库中。这对我的同事没有好处,但它确实允许 git 在 I 进行合并时计算共同祖先。这是非常可取的。

这就是问题所在。当其他人进行合并时,git 不知道。这是一个例子:

  o-...-A---o---C--- unstable
 /
X--...--B---o---o--- stable

不稳定分支是在 X 点创建的。在 A 点,我们决定将来自不稳定分支的更改合并到 B 点的稳定分支中。正确的共同祖先是 X。

由于合并没有记录在 git 历史记录中,因此在 C 处的以下合并再次假设 X 是共同祖先。我希望它是 A,如下图所示:

  o-...-A---o---C--- unstable
 /       \
X---...---B---o---o--- stable

并非绝对需要得到一张与图片完全一样的图表。任何可以将 A 识别为共同祖先的图我都可以。

我有一些选择,例如正确使用 git-filter-branch 或从未提交给 SVN 的“假”提交。然而,到目前为止,我的任何尝试都没有奏效。

感谢您提出的任何想法。该过程不必是自动的。合并非常罕见,我可以忍受“手工”完成的痛苦。

【问题讨论】:

    标签: git merge git-svn


    【解决方案1】:

    另一种选择是使用 Grafts 文件,它允许您在不实际操作历史记录的情况下覆盖提交的父项。

    这意味着在 SVN 存储库中看到合并后,您只需在 .git/info/grafts 中添加一行,其中包含合并提交 (M) 及其父级 (A,B) 的 SHA-1 .

          o-...-A---o---D--- unstable
         /       
        X-----B---M---o---o--- stable
    
    A = 31423cd8a838f984547a908777308d846043cbda
    B = d99cfccb1f859a8f1dbfac95eec75227fe518b23
    M = 13319a54d3e3d61b501e7cc6474c46f37784aaa3
    

    为了从 A-M 创建链接,您可以将 M 的父母指定为 B 和 A。grafts 文件的格式相当简单:

    commit newparent1 ... newparentN
    

    这意味着您将以下(相当长的)行添加到您的移植文件中:

    13319a54d3e3d61b501e7cc6474c46f37784aaa3 d99cfccb1f859a8f1dbfac95eec75227fe518b23 31423cd8a838f984547a908777308d846043cbda
    

    Git 现在会假装这个合并确实发生了。不利的一面是,这不会通过 git push/fetch/clone 传播,但这不应该是个人发展的主要问题。

    【讨论】:

    • 谢谢!这是我第一次听说移植。总是很高兴了解更多信息。
    【解决方案2】:

    你的问题有点像SVN populating svnmergeinfo from git merges 反过来:
    您不希望 SVN 记录来自 Git 的合并,而是希望 Git 记录来自 SVN 的合并;)

    由于git-svn 从SVN 导入时不关心svnmergeinfo 属性,因此留下“手动操作”选项。

    我不会推荐 git-filter-branch 解决方案或任何在 Git 端重写历史的东西。
    如果您知道 SVN 上的“A->B”合并,您应该在 Git ** 上的“合并”分支中进行合并,然后将其合并回稳定分支(此时是微不足道的合并),因此向您当前的稳定历史添加新的提交。

        o-.....-A---o---C--- unstable
       /         \
      /           o-------\__ merge recorder branch
     /           /         \
    X---.....---B---o---o---o__ stable
    

    那么从 C 到 stable 的合并应该有 A 作为共同祖先。

    【讨论】:

    • 对!所以关键是要进行 两个 中间提交,其中一个最终也会出现在 SVN 中。这似乎至少在纸面上有效。谢谢提供信息!我想知道是否可以将其压缩到 git 别名中...
    • 你忘记在“... Git **in a "merge" branch ...”中结束“**”(粗体)
    【解决方案3】:

    从 git 1.6.6 开始,这应该会自动发生。

    " * "git svn" 学会了阅读 SVN 1.5+ 和 SVK 合并票证。"

    在:

    http://www.kernel.org/pub/software/scm/git/docs/RelNotes/1.6.6.txt

    【讨论】:

      【解决方案4】:

      小心移植文件。

      1. 如果做错了,git gc 会(一段时间后)删除部分历史记录
      2. 如果您推送到另一个主机,它不会知道移植物,最终可能会破坏历史记录。

      【讨论】:

        猜你喜欢
        • 2011-02-26
        • 1970-01-01
        • 1970-01-01
        • 2013-04-11
        • 1970-01-01
        • 1970-01-01
        • 2011-02-11
        • 2011-01-29
        • 1970-01-01
        相关资源
        最近更新 更多