【问题标题】:After "git svn clone", I still don't have fantastic branch-merging commit?在“git svn clone”之后,我仍然没有出色的分支合并提交?
【发布时间】:2011-11-24 18:08:50
【问题描述】:

在我做了 git svn clone --stdlayout ... 之后,一切看起来都很好,我已经转换了远程分支。但是当 git log --graph 时,我没有看到任何分支合并图。正常吗?

【问题讨论】:

  • 没用过真的支持合并的svn,不过是的,恐怕这很正常。

标签: git git-svn


【解决方案1】:

自 2008 年夏天发布的 1.5.0 版本以来,Subversion 支持合并跟踪。 Subversion 将执行合并的信息保存为合并目标上设置的 svn:mergeinfo 属性,无论是分支目录,如 ^/trunk/,还是任何其他目录。

Git 和 Subversion 中的合并跟踪机制之间存在重大差异:

  1. 整个分支合并。

    当你在 master 分支上时,命令

    $ git merge some-branch
    

    导致合并提交,其第一个父级设置为 master 引用的提交,第二个父级设置为 some-branch 引用的提交(我不此处不考虑快进和冲突合并)。

    对于 git,这意味着创建的合并提交包括 mastersome-branch整个历史

    当你签出 ^/trunk/ 分支到 svn 工作副本然后运行

    $ svn merge ^/branches/some-branch trunk-working-copy
    

    Subversion 将在 trunk-working-copy 目录上设置 svn:mergeinfo 属性,如下所示:

    /branches/some-branch:10-20,30-40,50-60
    

    范围 10-20,30-40,50-60 包括那些尚未从 ^/ 合并到 ^/trunk/ 分支的修订版分支/一些分支/(Subversion 会自动检测它们)。

    Mergeinfo 属性只指定那些曾经合并到分支中的修订。并且由用户来检查所有这些合并的修订是否包含分支的整个历史

  2. Cherry-pick 合并。

    当您需要将来自单个提交的更改合并到您的 master 分支中时,您可以运行

    $ git cherry-pick bc347a8
    

    在此之后,git 创建了一个包含相应更改的提交,并将一个父级设置为先前由 master 分支引用的提交。

    也就是说,git 不会为cherry-pick 创建任何类型的合并提交。因此,git 无法通过其图形结构跟踪精心挑选的提交。

    相反,Subversion 确实通过调整 svn:mergeinfo 属性来跟踪cherry-pick 合并:

    $ svn merge -c100 ^/branches/some-branch trunk-working-copy
    

    这个命令很简单,它调整svn:mergeinfo如下:

    /branches/some-branch:100
    

    这意味着 Subversion 会跟踪cherry-pick 合并。

因此,翻译后您不会收到合并提交。据我所知,git-svn 在合并历史方面存在某些问题。

但作为 subgit 开发人员,我不得不说 subgit 应该正确处理合并跟踪信息。很可能在您的分支上设置的 svn:mergeinfo 属性不包括合并到它们的分支的整个历史。这是如何发生的:

  • 您使用的是旧的 svn 客户端 (
  • 您已经执行了挑选并跳过了一些修订范围以添加到 svn:mergeinfo
  • 您在不是分支目录的目录上设置了 svn:mergeinfo,即它们不是 ^/trunk/^/branches/some-branch 等(用于标准布局)。

要解决这个问题,您必须找到合并跟踪信息的跳过部分并将其添加到您的分支中:

  1. 尝试查找尚未合并的修订:

    $ svn mergeinfo --show-revs eligible ^/branches/some-branch/@HEAD ^/trunk/@HEAD
    

    输出必须包含您尚未从 ^/branches/some-branch/ 合并到 ^/trunk/ 的所有修订。

  2. 尝试通过svn合并尚未合并的修订。

    • 如果您认为所有更改都已合并,请使用 svn merge 命令的 --record-only 选项;
    • 如果您不确定,最好执行正常的 svn 合并,这将应用所有缺失的更改。
  3. 使用 subgit,您还可以通过 git 方式进行合并,然后将创建的合并提交推送到 subgit 支持的存储库,因此它会将这些合并提交转换为具有正确 svn:mergeinfo 的 svn 修订版。

作为一个很好的奖励,您可以参考与合并跟踪相关的 SubGit specification,它有一些我上面所说的漂亮图表。

【讨论】:

    【解决方案2】:

    Subversion 轨道在 svn:mergeinfo 属性的帮助下合并。虽然您的工具可能不会将历史记录显示为图表,但它本质上不是线性的。实际上 svn:mergeinfo 比 Git 合并提交更强大(尽管这种能力可能没有实际用处)

    SubGit 之类的工具会在可能的情况下将 svn:mergeinfo 转换为合并提交。

    我正在使用我推荐的工具(SubGit),但 git-svn 在双向翻译合并方面确实很弱。

    【讨论】:

    • 这是否意味着我可以尝试使用 SubGit 来解决这个问题?该怎么做?
    • @DrakeGuan 你可以试试SubGit,以防你将 SubGit 安装到你的 Subversion 存储库中——SubGit 在服务器端工作。要安装 SubGit,请在服务器端运行 subgit install repos。安装 SubGit 后,您只需使用 git 运行,例如,git clone ssh://user@host/svn/repos,更详细的配置示例请参阅 SubGit 网站上的文档。
    • 我确实试了一下,仍然得到了直接的提交日志,而不是树状的......
    【解决方案3】:

    使用 git-svn 不会改变 SVN 本身具有线性历史的事实,因此从技术上讲,所有合并都是快进,用 git 术语来说。没有合并提交,因此图中也没有合并。

    【讨论】:

    • Subversion 轨道在 svn:mergeinfo 属性的帮助下合并。虽然历史可能不会显示为图表,但它本质上不是线性的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 2010-11-22
    • 2012-08-31
    相关资源
    最近更新 更多