如何使用git-svn保持svn:external最新?

52

如果将我的存储库视为 SVN 存储库,则我会得到:

svn co http://myrepo/foo/trunk foo
...
foo/
  bar/
  baz/ -> http://myrepo/baz/trunk

将其视为Git存储库,我得到:

git svn clone http://myrepo/foo --trunk=trunk --branches=branches --tags=tags
...
foo/
  bar/

我可以将baz克隆到其他地方的本地机器上并添加符号链接,但那只是一个hack。是否有一种方法让git svn rebase在更新其他所有内容时自动拉取这些更改,就像svn up一样?


我知道我曾经在某个地方读到过如何使用git子模块设置它,但我找不到链接了。 - JesperE
8个回答

26
我见过的将svn外部引用与git-svn集成的最佳方法是这个脚本,它会将您的外部引用克隆到.git_externals/目录中,并创建您需要的符号链接和排除文件。我认为这是一个简单直接的解决方案。可能因人而异。
这里有一个旧的概述,介绍了其他处理git-svn中svn外部引用的选项。对我来说看起来有些过于复杂,而且在后续的Git使用中容易出现问题。

这似乎对我不起作用(这里的外部链接是指向同一存储库的相对链接)。 - Paŭlo Ebermann

25

我最终使用的解决方案是在本地将其他git-svn克隆库建立符号链接。这个方案非常有效:它允许我提交更改,并允许我在项目A中进行本地更改以便将其同步到项目B。


6
我刚刚编写了一个简短的脚本,它将检出当前“HEAD”的所有svn外部依赖项到根目录,并将它们从git仓库中排除。
将其放置在“.git/hooks/post-checkout”中,它会在工作树更改时保持这些外部依赖项的最新状态,例如由于git svn rebase或git-checkout引起的更改。
#!/bin/bash
set -eu

revision=$(git svn info | sed -n 's/^Revision: \([1-9][0-9]*\)$/\1/p')
git svn -r${revision} propget svn:externals | head -n-1 | {
    while read checkout_args
    do
        checkout_dirname=$(echo ${checkout_args} | cut -d' ' -f3)
        svn checkout ${checkout_args}
        if [ -z $(grep ${checkout_dirname} .git/info/exclude) ]
        then
            echo ${checkout_dirname} >> .git/info/exclude
        fi
    done
}

1
+1 对于在 Windows 上几乎可行的 Git 操作,我进行了一些微调,但这是这里最好的解决方案。 - pms1969
1
@pms1969:调整版本的源代码在哪里? - Carl

4
我还编写了一个脚本(提供了Perl和Ruby版本),可以在http://github.com/liyanage/git-tools/找到。它具有以下功能:
  • 递归检查所有svn:externals
  • 如果克隆大型存储库的过程中中止,可以重复运行。这种情况经常发生。它会从上次结束的地方继续。
  • 将找到并处理的所有svn:externals条目添加到.git/info/exclude中
  • 将遇到的所有svn:ignore条目添加到.git/info/exclude中
  • 可以在第一次运行后定期运行,以在所有克隆的子沙箱中执行svn:rebase,发现新的外部引用和新的svn:ignores
更新:我不再维护此脚本。它递归克隆和更新SVN存储库以及其他git相关功能的功能现在已经在我正在积极维护的这个新项目中提供:http://liyanage.github.com/git-tools/

1
我想了解您遇到的问题,以便我可以改进脚本。您能联系我吗? - Marc Liyanage
有很多分支。有人知道哪一个可以在Windows上使用msysgit?链接的版本总是卡住。 - axk
也无法使其工作。文档似乎不同步。gh clone-externals 不被识别为有效的子命令。 - Plouff

2
仅供记录:我遵循了this的建议,并尝试使用SmartGit来处理svn:externals
SmartGit是我见过的最好的Git GUI客户端。关于svn:externals,它不仅可以正确地获取它们,还提供了一个“快照”选项(只读、仅HEAD克隆)外部存储库。
不幸的是,商业使用需要付费(而且我觉得许可证价格有点太高 - 是的,我是个吝啬鬼)。但是,它可以免费用于非商业目的。

1

尝试这个Python脚本:https://bitbucket.org/nytmyn/gitsvnext/overview

要在您的git存储库中运行svn externals,请执行以下操作:

python /../gitsvnext/run update

运行此命令以了解应将什么放入.git/info/exclude文件中

python /../gitsvnext/run list

你会在哪个文件夹下运行这个脚本?如果我的主要svn仓库是 /path/to/repo,而外部定义在 /path/to/repo/myexternals/folder/ 中,那么我应该在 /path/to/repo 还是 myexternals/folder 文件夹中运行脚本呢? - Bibek Shrestha

1

我决定编写一个“简单”的Perl脚本来处理所有这些事情。我最近将它放到了Github上,试试吧,也许会有所帮助:http://github.com/sushdm/git_svn_externals/

它基本上为找到的所有外部文件执行git-svn克隆操作,并递归地查找它们,将它们克隆并在适当的位置创建符号链接,并排除所有.git_externals目录和符号链接,以便您仍然可以使用'git svn dcommit'。

祝你好运。


1

这是我所做的。

首先,我创建了一个空的 SVN 仓库(与 Git 相同的根目录):

svn checkout --depth empty http://path/to/repo .

这在git根目录中创建了一个空的svn仓库。重点是它包含SVN外部属性。
接下来,我只检查外部属性(我将cygwin工具放在PATH中):
svn propget svn:externals | sed -e 's/ / .\//' | sed -e 's/\'//g' | xargs -L1 svn co

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接