合并:Hg/Git 与 SVN [英] Merging: Hg/Git vs. SVN

查看:23
本文介绍了合并:Hg/Git 与 SVN的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常读到 Hg(以及 Git 和...)在合并方面比 SVN 更好,但我从未见过 Hg/Git 可以在 SVN 失败的地方(或 SVN 需要手动干预的地方)合并某些内容的实际示例.您能否发布一些分支/修改/提交/...操作的分步列表,以显示当 Hg/Git 愉快地继续前进时 SVN 会失败的地方?实际情况,不是非常特殊的情况,请...

一些背景:我们有几十名开发人员在使用 SVN 开发项目,每个项目(或一组类似的项目)都在自己的存储库中.我们知道如何应用发布分支和功能分支,所以我们不会经常遇到问题(即,我们一直在那里,但我们已经学会了克服 Joel 的问题一名程序员对整个团队造成创伤"或需要六名开发人员两周时间才能重新整合一个分支").我们有非常稳定的发布分支,仅用于应用错误修正.我们的主干应该足够稳定,以便能够在一周内创建一个版本.我们有功能分支,单个开发人员或开发人员组可以工作.是的,它们在重新集成后会被删除,因此它们不会弄乱存储库.;)

所以我仍在努力寻找 Hg/Git 相对于 SVN 的优势.我很想获得一些实践经验,但是我们还没有可以迁移到 Hg/Git 的任何更大的项目,所以我一直在玩只包含几个组成文件的小型人工项目.而且我正在寻找一些案例,您可以在其中感受到 Hg/Git 的强大力量,因为到目前为止我经常阅读它们,但我自己却没有找到.

解决方案

我自己不使用 Subversion,而是来自 Subversion 1.5 的发行说明:合并跟踪(基础) 看起来与完整的合并跟踪工作方式存在以下差异-DAG 版本控制系统,如 Git 或 Mercurial.

  • 将主干合并到分支与将分支合并到主干不同:出于某种原因,将主干合并到分支需要 --reintegrate 选项到 svn merge.

    在像 Git 或 Mercurial 这样的分布式版本控制系统中,trunk 和 branch 之间没有技术区别:所有分支都是平等创建的(不过可能存在社交差异).向任一方向合并的方式相同.

  • 您需要为 svn log 提供新的 -g (--use-merge-history) 选项>svn blame 考虑合并跟踪.

    在 Git 和 Mercurial 中,显示历史(日志)和责备时会自动考虑合并跟踪.在 Git 中,您可以请求仅使用 --first-parent(我想 Mercurial 也存在类似的选项)来关注第一个父级,以丢弃"git log 中的合并跟踪信息.

  • 据我所知 svn:mergeinfo 属性存储关于冲突的每个路径信息(Subversion 是基于变更集的),而在 Git 和 Mercurial 中它只是提交对象,可以有更多超过一位家长.

  • 已知问题" Subversion 中合并跟踪的小节表明重复/循环/反射合并可能无法正常工作.这意味着对于以下历史,第二次合并可能不会做正确的事情('A' 可以是主干或分支,'B' 可以分别是分支或主干):

    <前>**---*---x---*---y---*---*---*---M2 <-- A /--*----M1---*---*---/<-- B

    如果上述 ASCII-art 被破坏:分支 'B' 在修订版 'x' 从分支 'A' 创建(分叉),然后分支 'A' 在修订版 'y' 合并到分支 'B'作为合并'M1',最后分支'B'合并到分支'A'作为合并'M2'.

    <前>**---*---x---*-----M1--*---*---M2 <-- A//-*---y---*---*---/<-- B

    在上述 ASCII 艺术被破坏的情况下:分支 'B' 从修订版 'x' 的分支 'A' 创建(分叉),它在 'y' 处合并到分支 'A' 作为 'M1',然后再次合并到分支A"中作为M2".

  • Subversion 可能不支持 交叉合并的高级案例.

    <前>**-b-----B1--M1--**---M3 // X ///--B2--M2--*

    Git 在实践中使用递归"合并策略很好地处理了这种情况.我不确定 Mercurial.

  • 已知问题"中,有警告说合并跟踪可能不适用于文件重命名,例如当一侧重命名文件(并可能修改它),另一侧修改文件而不重命名(以旧名称).

    Git 和 Mercurial 在实践中都能很好地处理这种情况:Git 使用重命名检测,Mercurial 使用重命名跟踪.

HTH

I often read that Hg (and Git and...) are better at merging than SVN but I have never seen practical examples of where Hg/Git can merge something where SVN fails (or where SVN needs manual intervention). Could you post a few step-by-step lists of branch/modify/commit/...-operations that show where SVN would fail while Hg/Git happily moves on? Practical, not highly exceptional cases please...

Some background: we have a few dozen developers working on projects using SVN, with each project (or group of similar projects) in its own repository. We know how to apply release- and feature-branches so we don't run into problems very often (i.e., we've been there, but we've learned to overcome Joel's problems of "one programmer causing trauma to the whole team" or "needing six developers for two weeks to reintegrate a branch"). We have release-branches that are very stable and only used to apply bugfixes. We have trunks that should be stable enough to be able to create a release within one week. And we have feature-branches that single developers or groups of developers can work on. Yes, they are deleted after reintegration so they don't clutter up the repository. ;)

So I'm still trying to find the advantages of Hg/Git over SVN. I'd love to get some hands-on experience, but there aren't any bigger projects we could move to Hg/Git yet, so I'm stuck with playing with small artificial projects that only contain a few made up files. And I'm looking for a few cases where you can feel the impressive power of Hg/Git, since so far I have often read about them but failed to find them myself.

解决方案

I do not use Subversion myself, but from the release notes for Subversion 1.5: Merge tracking (foundational) it looks like there are the following differences from how merge tracking work in full-DAG version control systems like Git or Mercurial.

  • Merging trunk to branch is different from merging branch to trunk: for some reason merging trunk to branch requires --reintegrate option to svn merge.

    In distributed version control systems like Git or Mercurial there is no technical difference between trunk and branch: all branches are created equal (there might be social difference, though). Merging in either direction is done the same way.

  • You need to provide new -g (--use-merge-history) option to svn log and svn blame to take merge tracking into account.

    In Git and Mercurial merge tracking is automatically taken into account when displaying history (log) and blame. In Git you can request to follow first parent only with --first-parent (I guess similar option exists also for Mercurial) to "discard" merge tracking info in git log.

  • From what I understand svn:mergeinfo property stores per-path information about conflicts (Subversion is changeset-based), while in Git and Mercurial it is simply commit objects that can have more than one parent.

  • "Known Issues" subsection for merge tracking in Subversion suggests that repeated / cyclic / reflective merge might not work properly. It means that with the following histories second merge might not do the right thing ('A' can be trunk or branch, and 'B' can be branch or trunk, respectively):

    *---*---x---*---y---*---*---*---M2        <-- A
                                 /
              --*----M1---*---*---/           <-- B
    

    In the case the above ASCII-art gets broken: Branch 'B' is created (forked) from branch 'A' at revision 'x', then later branch 'A' is merged at revision 'y' into branch 'B' as merge 'M1', and finally branch 'B' is merged into branch 'A' as merge 'M2'.

    *---*---x---*-----M1--*---*---M2          <-- A
                    /           / 
              -*---y---*---*---/             <-- B
    

    In the case the above ASCII-art gets broken: Branch 'B' is created (forked) from branch 'A' at revision 'x', it is merged into branch 'A' at 'y' as 'M1', and later merged again into branch 'A' as 'M2'.

  • Subversion might not support advanced case of criss-cross merge.

    *---b-----B1--M1--*---M3
               /        /
               X        /
              /       /
            --B2--M2--*
    

    Git handles this situation just fine in practice using "recursive" merge strategy. I am not sure about Mercurial.

  • In "Known Issues" there is warning that merge tracking migh not work with file renames, e.g. when one side renames file (and perhaps modifies it), and second side modifies file without renaming (under old name).

    Both Git and Mercurial handle such case just fine in practice: Git using rename detection, Mercurial using rename tracking.

HTH

这篇关于合并:Hg/Git 与 SVN的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆