如何在获取回购协议后告诉git-svn有关创建的远程分支的信息?


193

我过去一直git-svn在与公司的中央Subversion存储库相对应。我们最近在中央仓库中创建了一个新的功能分支。

我该如何告诉Git?运行时,git branch -r我只能看到fetch针对Subversion存储库初始化Git存储库时存在的分支?


来自这里的答案:stackoverflow.com/questions/13376917/…也可能有用。
Tomasz Gandor

Answers:


294

您可以手动添加远程分支,

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch

3
只需将此链接添加到文档作为参考kernel.org/pub/software/scm/git/docs/git-svn.html
slf 2011年

1
从.git / config中,很容易理解如何从单个/多个存储库配置远程分支。
MikaelLepistö2012年

6
如果我能投票赞成八次,我会的。最后,一种添加在非标准位置添加的svn分支的方法!
Tim Keating 2012年

7
我进入fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.git checkout步骤。
phpguru

17
@phpguru尝试删除-t选项标志,使其变为'git checkout -b local-newbranch newbranch'。别忘了将遥控器的前缀包括在newbranch中(例如origin / newbranch)。
mj1531 2014年

96

如果要跟踪所有远程svn分支,则解决方案很简单:

git svn fetch

这将提取所有尚未提取的远程分支。

额外提示:如果您首先仅检出中继,然后又要跟踪所有分支,则进行编辑.git/config,如下所示并重新运行git svn fetch

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

其要点是url应指向库根,并在限定的路径fetchbranches应该是相对于url

如果您只想获取特定的分支而不是全部,则可以在git svn --help以下示例中找到一个很好的示例:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

对于较旧的版本git-svn,一旦指定了这样的分支,便可能无法使用来获得新的分支git svn fetch。一种解决方法是添加更多fetch行,如下所示:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

@AndyEstes的另一种解决方法:在创建任何新指定的分支或标记之前,编辑.git/svn/.metadata或更改修订版的值branches-maxRevtags-maxRev将其更改为修订版。完成此操作后,请运行git svn fetch以跟踪新的svn远程分支。


1
如果在设置这些设置之前已经获取了执行svn分支的修订版,则可能需要执行git svn reset。
kcm1700

3
编辑.git/svn/.metadata非常有帮助!我在我的站点中添加了额外的分支.git/config,但git svn fetch并没有继续进行-因为元数据修订号“太过领先”。在一种情况下,仅提取分支的最后一次提交。我手动摆脱了错误的分支(重命名.git/svn/refs/remotes/svn/qa/XYZ.git/svn/refs/remotes/svn/qa/XYZ~,将其存在于.git/packed-refs等)……为元数据选择了“较早的”修订版本号…… git svn fetch最终获得了完整的历史记录(带有正确的连接图)。
starlocke

8
这应该是被接受的答案!@janos,您刚刚救了我几个小时!如果你来印度,我会带你去喝啤酒!
Roopesh Shenoy

1
或:git svn fetch --all
kenorb

1
这个答案是惊人的,因为它回答了我找不到的7个问题,而且没有写6页的叙述。
德罗伊'18

53

看来我只需要git svn fetch; 我以某种方式说服自己可以获取整个仓库,而不仅仅是更改。


7
@mitjak如果可以解决,为什么它不是正确的答案?我不明白回应的微妙之处。
罗尔姆斯2011年

“解决方案”可能不是“解决方案”
2011年

1
@rholmes:我敢肯定,mitjak意味着这是您的问题的解决方案,而不是您所提出问题的答案。(因为您问错了问题;因为您当时对该问题的理解有误。)
Mike Nelson

当您将svn存储库克隆到git时,存在分支时,此方法有效。如果之后在svn信息库中创建了分支,它将不起作用。
Petr Gladkikh 2012年

3
在克隆之后创建分支时,它工作正常,我一直都这样做。
蒂姆·高铁耶

15

也许我以某种方式弄乱了它,但是我遵循了vjangus的回答中的说明,并且几乎可以正常工作。唯一的问题是newbranch似乎不是从主干分支出来的。在gitk中,它本身就是一种“浮动”的形式。它与树干没有共同的祖先。

解决方案是:

  1. 查找创建分支之前在主干上发生的最后一次提交的SHA1。
  2. 在新分支上找到第一次提交的SHA1(消息可能是“已创建新分支,从trunk @ 12345复制”)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>-应该没有输出。如果有输出,则可能是您选择了错误的提交。
  4. git checkout local-newbranch然后git rebase <sha1 from step 1>。这将local-newbranch基于新树,但remotes/newbranch仍将断开连接。
  5. 转到文件.git/refs/remotes/newbranch并对其进行编辑,以包含提交的完整SHA1 (在rebased上newbranch),该提交与当前指向的旧提交相对应。(或者使用git-update-ref refs/remotes/newbranch <new-SHA>。谢谢inger。)
  6. 下次你git svn dcommitnewbranch,你会得到一堆关于它的消息更新一些日志。我认为这很正常。

我建议始终保持gitk --all开放状态,并经常刷新以跟踪您的工作。我还是git和git svn的新手,所以请提出对该方法的改进建议。


2
谢谢,这听起来很有用。大约5。可能更安全的选择是'git-update-ref refs / remotes / newbranch <new-SHA>'。
inger

再次尝试使用vjangus的方式,效果非常理想。无论如何我都会把它留在这里,因为它可能对某人有价值...
MatrixFrog 2011年

1
vjangus解决方案始终创建与中继断开连接的新分支。我认为这是因为SVN本身对如何复制实际内容一无所知。
bogdan.mustiata 2011年

我对大型git-svn repo的经验是,svn分支总是在与主干分离的git中创建。应该有某种方式将它们连接起来,但是我还没有花时间弄清楚它。AFAIK,您不能重新建立连接到svn分支的git分支的基准,因为这会弄乱dcommit逻辑。我们刚刚学会忍受它。
Spencer 2012年

7

简化vjangus的答案:

如果您在SVN中使用标准布局,并且已经执行了通常的svn init,则git-svn将为您完成配置工作。只是:

  1. 在SVN中查找分支副本修订版
  2. 使用git-svn获取该修订版
  3. 创建新的本地分支跟踪远程

一个例子。SVN网址为svn+ssh://gil@svn.myplace.com/repo。我要寻找的SVN分支是newbranch。本地git分支(远程跟踪newbranch)将为git-newbranch

步骤1:找到分支副本修订版

SVN登录--stop-上复制SVN + SSH://gil@svn.myplace.com/repo/branches/newbranch | 尾巴-4
    r7802 | 某人| 2014-03-21 18:54:58 +0000(2014年3月21日,星期五)| 1线

    将HEAD分支到newbranch
    -------------------------------------------------- ----------------------

因此,SVN中的分支点是版本7802。

步骤2:取得修订

混帐SVN取-r 7802
    找到可能的分支点:svn + ssh://gil@svn.myplace.com/repo/trunk => svn + ssh://gil@svn.myplace.com/repo/branches/newbranch,7801
    找到分支父级:(refs / remotes / trunk)8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    用do_switch跟随父对象
    成功跟随父母
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e(引用/远程处理/新分支)

git-svn完成了所有工作,现在知道了遥控器:

    #git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c参考/远程/新分支

步骤3:建立追踪远端的新本地分支:

git的结帐-b混帐newbranch -t newbranch
    检出文件:100%(413/413),已完成。
    分支git-newbranch设置为跟踪本地ref / remotes / newbranch。
    切换到新的分支“ git-newbranch”

最终,这让我了解了(show-ref非常宝贵)!对于那些错误地引用远程分支的人,您可以将其删除(我必须这样做git branch -d newbranch,然后强行删除中的ref dir .git/svn/refs/remotes/newbranch),然后从步骤2(以上)重新开始。
tutuDajuju 2014年

5

我尚未找到有关此功能的任何文档,但看起来git svn配置支持多个提取条目。这样,您还可以单独添加分支,而无需在配置中添加另一个远程svn存储库条目,也无需使用通配符来获取特定目录的所有分支。

假设您的SVN树真的很讨厌,有很多分支,而没有任何逻辑如何定位,例如,分支和包含更多分支的子目录。

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

而您只想手工选择一些要包含在git存储库中的分支。

您可以首先仅使用主干而不使用任何其他分支来初始化存储库:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

之后,您应该看到以下配置:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

每当您想从MyRepo获取新分支时,都可以通过以下方式将新的获取条目添加到配置中:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

或者您可以在.git / config中编辑相同的配置

要在将新分支添加到配置后获取新分支,只需运行:

git svn fetch -r 10000:HEAD

[编辑]有时似乎需要使用--all参数运行访存来访存新添加的分支:

git svn fetch --all -r 10000:HEAD

4

您可以尝试使用SubGit来代替git-svn怪癖。

必须将SubGit安装到Subversion存储库中。之后,可以使用标准的git工作流程,而不是使用特殊的git-svn命令:

  1. 推送新提交:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. 获取传入的更改

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. 创建一个新分支:

    git-svn:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

有关更多详细信息,请参见SubGit文档


1
SubGit的缺点是它创建两个存储库-一个svn和一个“影子” git存储库。对于庞大的SVN存储库,这可能是个问题……
Udo 2012年

@Udo如果SVN信息库中有几个项目,则可以只指定其中一个项目,并将其与Git信息库进行同步。在这种情况下,无需将整个Subversion存储库转换为Git。但是,如果一个人在此存储库中有一个庞大的SVN项目,则可能不转换该存储库的全部历史记录,而是转换一些最低修订版本的历史记录。这样可以减小翻译后的Git存储库的大小。
vadishev 2012年

1
@Udo-任何不愿意在硬盘驱动器上购买其存储库服务器的公司都将其优先事项弄乱了。但是大多数具有大型存储库的地方都非常重视其存储库,即使对于拥有数十年历史,数千万行代码和数十万次修订的公司而言,存储库的磁盘空间要求通常也不是主要问题。这是公司最核心的知识资产形式,磁盘空间非常便宜。它可能会引发需要升级RAID控制器的需求,但即使如此,生产率的提高……
Bob Kerns 2012年

@Bob Kerns-重点是“大小明智”的SVN和Git且不兼容。这不是磁盘存储等问题。但是您可以使用庞大的SVN存储库,因为通常只需要检出几个文件/项目。但是您不能克隆一个巨大的Git存储库-至少没有一点乐趣;-)“巨大”是指几个演出。
Udo 2012年

2

为了增加对vjangus的回答(这对我有所帮助),我还发现添加git嫁接在适当的位置将分支绑定到主干非常有用-允许git查看历史记录并正确执行合并。

这只是.git/info/grafts在哈希表中添加一行的情况:

<initial branch commit> <parent commit in trunk>

例如。

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

归功于http://evan-tech.livejournal.com/255341.html

(我将其添加为评论,但我的信誉不够。)


0

如果您未检出有效布局,则将无法检出远程分支。

这是我的工作:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

之后,您可以切换到远程分支:

git checkout --track -b branch_name branch_name

然后,您将自动切换到分支。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.