我如何告诉git-svn关于我获取repo后创建的远程分支?

我正在使用git-svn来对抗我公司的中央Subversion存储库。我们最近在中央回购中创建了一个新的功能分支。

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

77390 次浏览

似乎我只需要git svn fetch;不知怎的,我已经说服了自己,这将获得整个回购,而不仅仅是变化。

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

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

也许我搞砸了,但我遵循了vjangus回答中的说明,它几乎工作了。唯一的问题是,新分支似乎没有从树干上分叉出来。在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并编辑它,以包含提交(基于重基的newbranch)的完整SHA1,该提交对应于它当前指向的旧提交。(或者可以使用git-update-ref refs/remotes/newbranch <new-SHA>。谢谢你。)
  6. 下次你git svn dcommitnewbranch时,你会得到一堆关于它更新一些日志的消息。我认为这很正常。

我建议让gitk --all一直打开,并经常刷新它来跟踪你在做什么。我仍然对git和git svn有点陌生,所以请对这种方法提出改进建议。

如果签出时没有使用有效的布局,则无法签出远程分支。

这就是我所做的:

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

然后您将自动切换到您的分支机构。

我没有找到关于这个特性的任何文档,但是看起来git svn配置支持多个获取条目。通过这种方式,您还可以单独添加分支,而不需要向配置中添加另一个远程svn存储库条目,也不需要使用通配符来获取某个目录的所有分支。

假设您的SVN树非常糟糕,有许多分支,没有任何逻辑如何定位,例如,分支和子目录包含更多分支。

即。

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

您只需要手动选择一些要包含到git存储库中的分支。

你可以先初始化你的存储库,只有trunk,没有任何额外的分支:

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

有时似乎有必要运行fetch with——all parameter来获取新添加的分支:

git svn fetch --all -r 10000:HEAD

如果你想要跟踪所有远端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

如果你只想获取特定的分支而不是ALL,在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远程分支。

而不是处理git-svn的怪癖,你可以尝试SubGit

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

  1. 推送新提交

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Fetching incoming changes

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Creating a new branch:

    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
    

See SubGit documentation for more details.

为了补充vjangus的答案,这对我很有帮助,我还发现添加使用git移植在适当的位置将分支绑定到主干上很有用——允许git查看历史并正确执行合并。

这只是一个用哈希值向.git/info/grafts添加一行的例子:

<initial branch commit> <parent commit in trunk>

如。

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

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

(我想加上这句话作为评论,但我没有足够的声誉。)

vjangus回答的一个简化:

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

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

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

第一步:找到分支副本修订

# svn log --stop-on-copy svn+ssh://gil@svn.myplace.com/repo/branches/newbranch | tail -4
r7802 | someone | 2014-03-21 18:54:58 +0000 (Fri, 21 Mar 2014) | 1 line


branching HEAD to newbranch
------------------------------------------------------------------------

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

步骤2:获取修订

# git svn fetch -r 7802
Found possible branch point: svn+ssh://gil@svn.myplace.com/repo/trunk => svn+ssh://gil@svn.myplace.com/repo/branches/newbranch, 7801
Found branch parent: (refs/remotes/trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
Following parent with do_switch
Successfully followed parent
r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs/remotes/newbranch)

Git-svn完成了所有工作,现在知道了远程:

# git show-ref | grep newbranch
2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs/remotes/newbranch

步骤3:创建跟踪远程分支的新本地分支:

# git checkout -b git-newbranch -t newbranch
Checking out files: 100% (413/413), done.
Branch git-newbranch set up to track local ref refs/remotes/newbranch.
Switched to a new branch 'git-newbranch'