【问题标题】:git-svn clone | spurious branchesgit-svn 克隆 |虚假分支
【发布时间】:2012-07-06 06:24:01
【问题描述】:

我使用以下命令将 svn repo 克隆到 git 中,执行后,我看到了一些虚假的分支。

git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp

git branch -a

*(no branch)
  master
  remotes/abc-1.3.x
  remotes/abc-1.3.x@113346
  remotes/abc-1.3.x@541512
  remotes/branch_test_script
  remotes/tags/modules-1.2
  remotes/tags/modules-1.2@113346
  remotes/tags/modules-1.2@516265
  remotes/tags/release-1.1
  remotes/tags/release-1.1@113346
  remotes/tags/release-1.1@468862
  remotes/trunk

在 svn 中创建的实际分支是 abc、branch_test_script、modules 和 release。 有人可以帮助了解 'abc-1.3.x@113346' 、 'abc-1.3.x@541512' ... 'release-1.1@468862' 等是什么吗?

我们怎样才能摆脱这些虚假的分支/它们意味着什么?

谢谢,
加亚特里

【问题讨论】:

  • 我很难找到这个命名的来源,但看起来这些分支是从 SVN 提交创建的,发现它们不再被 svn 分支(或标签)引用最初制作的。与 Git 中未引用的提交类似,只是可以恢复提交的分支名称。
  • @fork0 :感谢您的回复。但我不清楚如何在 svn 中存在未引用的提交。参考资料怎么会丢失?您能分享一下您对此的看法吗?
  • 我不知道。也许 SVN 存储库的维护者从未清理过它们(或者 SVN 根本没有能力?)。我并不是说参考资料丢失了,而是有人刚刚从历史的较早时间点开始提交
  • 也许 SVN 中的提交列表总是产生所有提交的完整列表,与它们是否被标签或分支引用无关
  • 但是其中一些分支没有被删除或移动。即使对于一些正常的提交修订,也会创建这些分支。知道为什么会这样吗?

标签: git git-svn git-branch


【解决方案1】:

tl;博士:

git svn 如果为子目录(或 git-svn 未跟踪的另一个目录)创建了分支(或标签),则创建这些“@”-分支。总会有一个同名的“常规”分支,但没有“@”后缀。 “@”分支仅作为常规分支的分支点存在。


注意:我为此提交了一个补丁;这个解释的编辑版本现在是官方 git svn 手册页的一部分,作为一个新的部分“处理 SVN 分支”(从 Git 1.8.1 开始)。


在 Subversion 中,分支和标签只是目录树的副本,因此可以(尽管通常不鼓励)从本身不是分支(或树干)的目录创建分支。例如,通过将 /trunk/foo 复制到 /branches/bar,而不是复制 /trunk(可以说是“子目录分支”),或者复制位于 trunk/tags/branches 结构之外的目录(即可能在 SVN 中)。

然而,在 git 中,一个分支总是针对整个 repo,不存在子目录分支。 git svn 因此使用了一种解决方法。如果它检测到从目录复制的分支,该目录本身没有被 git-svn 跟踪为分支,它将创建一个新的历史记录。例如,对于 /trunk/foo 被复制到 r1234 中的 /branches/bar 的子目录分支,它将创建:

  • 从 r1233 向后的每个 SVN 修订版的新 git 提交(注意数字是创建分支之前的最后一个修订版)。这些提交的树将只包含分支的子目录。因此,对于从 r1233 向后的每个修订版,通常会有两个 git 提交,一个包含整个树(在 git-svn 处理 trunk 的历史记录时创建),另一个是新的。
  • 一个名为“bar@1233”(分支名称@revision)的虚拟分支,指向从上面的 r1233 创建的提交。
  • 来自 r1234 的提交,即创建分支的提交。此提交将上面的分支作为其(唯一)祖先。
  • 名为“bar”的分支,指向第二次提交。

这样,对于子目录分支栏,你在git中得到两个分支

  • bar@1233 ,表示创建分支的仓库状态
  • bar,代表分支

我不太清楚为什么会创建这个虚拟分支。我认为这样做是为了表示有关分支从哪个修订版分支出来的信息,并拥有该分支的完整历史记录。


请注意,可以使用标志--no-follow-parent 关闭整个机制。在这种情况下,每个 SVN 分支都会生成一个 git 分支,其中仅包含来自 SVN 分支目录的提交。每个分支都将与历史的其余部分断开连接,并且将有自己的根提交,对应于分支中的第一个提交。

【讨论】:

    【解决方案2】:

    当我将我的 SVN 存储库克隆到 Git 存储库时,我也有如此奇怪的分支。

    在查看了预期的分支(在您的情况下为 modules-1.2、abc-1.3.x、branch_test_script 和 release-1.1)后,我注意到 @revisionnumberbranches 只不过是在其前缀分支中提交。

    如果您想手动执行此操作,请在分支 abc-1.3.x 上打开 gitk 并验证 abc-1.3.x@113346 和 abc-1.3.x@541512 是否出现在该分支的历史记录中。如果是这样,您可以删除相应的分支。

    如果您有许多分支或许多提交要浏览,这可能会有点麻烦。

    自动方式:让git为你做:

    git branch -r --contains abc-1.3.x@113346
    

    将回显(或至少应该)

    abc-1.3.x
    abc-1.3.x@113346
    abc-1.3.x@541512
    

    这意味着您可以安全地删除 abc-1.3.x@113346,因为它包含在 abc-1.3.x 中:

    git branch -r -d abc-1.3.x@113346
    

    由于 SVN 的线性历史,它当然也包含它(较新的)提交 541512。


    旁注:
    您可能已经注意到,您的 SVN 标签实际上并未转换为 Git 标签和原生 Git 分支。这可以使用svn2git 将 SVN 存储库克隆到 Git 存储库中来实现。

    【讨论】:

    • 如何删除这些分支?是否有任何参数可以传递给 git 以忽略此类提交而不创建分支?
    • 正如我所写:可以使用git branch -r -d <branchname> 删除分支。我不认为有一个标志可以实现没有创建分支。
    • git-svn 可能会不必要地创建这些“@”分支,但有一个重要的情况是,abc@113346 不是abc 的祖先。如果分支在颠覆中被删除,然后通过从另一个点复制再次创建,就会发生这种情况。此外,abc@113346 是abc 的祖先这一事实并不意味着这没有发生,这可能意味着abc 被合并到主干,被删除(在高于 113346 的某些版本中)并创建了一个新的在它的位置从树干。
    • 换句话说,不,这个答案是错误的。 “应该”不是真的。它可能会也可能不会,取决于分支在被删除之前是否被合并。
    猜你喜欢
    • 1970-01-01
    • 2021-06-26
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    相关资源
    最近更新 更多