题 如何将包含历史记录的SVN存储库迁移到新的Git存储库?


我阅读了Git手册,常见问题解答,Git - SVN速成课程等等,他们都解释了这个和那个,但是你无处可以找到一个简单的指令:

SVN存储库: svn://myserver/path/to/svn/repos

Git存储库: git://myserver/path/to/git/repos

git-do-the-magic-svn-import-with-history \
svn://myserver/path/to/svn/repos \
git://myserver/path/to/git/repos

我不希望它那么简单,我不指望它是一个单一的命令。但我确实希望它不要试图解释任何事情 - 只是说这个例子采取了哪些步骤。


1392
2017-09-17 02:08


起源


它变得越来越容易,我自己完成了它并在SO的帮助下记录了我的发现 jmoses.co/2014/03/21/moving-from-svn-to-git.html - John Moses
使用Casey的答案,但在运行“svn clone ...”命令之前,请参阅如何将额外的“Visual SVN Server”行添加到user.txt文件中......此处: stackoverflow.com/questions/8971208/... - MacGyver
此外,如果您在GitHub个人资料中选中了“发送电子邮件私人选项”,请将此作为您在users.txt中的电子邮件地址以匹配.yourgituser @ users.noreply.github.com,以便您的真实电子邮件地址不会显示在提交。 - MacGyver


答案:


魔法:

$ git svn clone http://svn/repo/here/trunk

Git和SVN的运作方式截然不同。你需要学习Git,如果你想跟踪上游SVN的变化,你需要学习 git-svn。该 git-svn 手册页有一个很好的例子:

$ git svn --help

495
2017-09-17 18:20



@Casey的答案更好地回答了原始问题。 - Doug Wilson
这会保留分支机构和一切吗?或者只是克隆行李箱? - Eildosa
@Eildosa:这只会克隆主干。请参阅凯西的替代方案。 - sleske
@DougWilson但我在这里看不到凯西的任何答案。以下是13位作者以“创建用户文件”开头的答案吗? - Andrey Regentov
对于其他任何想知道哪个是“凯西的答案”的人,这里有许多评论引用,这是 这个 (凯西将他的昵称改为cmcginty)。 - Stefan Monov


创建用户文件(即 users.txt)将SVN用户映射到Git:

user1 = First Last Name <email@address.com>
user2 = First Last Name <email@address.com>
...

您可以使用此单行程序从现有SVN存储库构建模板:

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt

如果SVN发现缺少SVN用户,SVN将停止。但之后,您可以更新文件并从上次停止的地方继续。

现在从存储库中提取SVN数据:

git svn clone --stdlayout --no-metadata --authors-file=users.txt svn://hostname/path dest_dir-tmp

此命令将在中创建一个新的Git存储库 dest_dir-tmp 并开始拉动SVN存储库。请注意,“ - stdlayout”标志表示您具有通用的“trunk /,branches /,tags /”SVN布局。如果您的布局不同,请熟悉 --tags--branches--trunk 选项(一般来说 git svn help)。

允许所有常用协议: svn://http://https://。 URL应该以基本存储库为目标,例如 http://svn.mycompany.com/myrepo/repository。那必须  包括 /trunk/tag 要么 /branches

请注意,执行此命令后,通常看起来操作是“挂起/冻结”,并且在初始化新存储库后可能会长时间卡住它是很正常的。最后,您将看到日志消息,表明它正在迁移。

另请注意,如果省略 --no-metadata flag,Git会在提交消息中附加有关相应SVN修订的信息(即 git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID>

如果找不到用户名,请更新您的 users.txt 文件然后:

cd dest_dir-tmp
git svn fetch

如果你有一个大型项目,你可能需要多次重复那个最后一个命令,直到获取了所有的Subversion提交:

git svn fetch

完成后,Git将检查SVN trunk 进入一个新的分支。任何其他分支都设置为遥控器。您可以通过以下方式查看其他SVN分支:

git branch -r

如果要在存储库中保留其他远程分支,则需要手动为每个分支创建本地分支。 (跳过trunk / master。)如果你不这样做,分支将不会在最后一步克隆。

git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same name

标签作为分支导入。你必须创建一个本地分支,制作一个标签并删除分支,将它们作为Git中的标签。要使用标记“v1”执行此操作:

git checkout -b tag_v1 remotes/tags/v1
git checkout master
git tag v1 tag_v1
git branch -D tag_v1

将您的GIT-SVN存储库克隆到干净的Git存储库中:

git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir

您之前从远程分支创建的本地分支将仅作为远程分支复制到新的克隆存储库中。 (跳过trunk / master。)对于你想要保留的每个分支:

git checkout -b local_branch origin/remote_branch

最后,从干净的Git存储库中删除指向现在已删除的临时存储库的远程:

git remote rm origin

1467
2017-09-17 17:09



Eelke的这篇博文是对上述答案的一个很好的交叉引用。 blokspeed.net/blog/2010/09/converting-from-subversion-to-git - kgriffs
这是99%真棒,按照这些步骤,除了分支之外我按顺序排序:在最后一步之后,它们只是远程的(当我执行命令时就消失了:git remote rm origin) - Dirty Henry
我只是使用这个程序,它工作得很好。我的观察结果是:1)将“标签分支”转换为标签的过程仍然离开了分支(虽然没有标记)。如果您在SVN中创建了标记而未修改内容,那么您实际上可以标记前面的提交并删除“标记分支”以获得更清晰的历史记录。 2)没有提到迁移svn:ignore属性。这在互联网的其他地方有所涉及。另见'git svn show-ignore'。 3)最后的克隆对我没有好处。事实上,我最终得到了原始目录的远程参考,这很奇怪。 - dty
GitHub有一个非常方便的步骤: github.com/nirvdrum/svn2git#readme - Dan Nissenbaum
对于Windows下的用户,我基于此方法创建了一个PowerShell脚本: gist.github.com/Gimly/90df046dc38181bb18de - Gimly


将您的Subversion存储库干净地迁移到Git存储库。首先,你必须创建一个文件,将你的Subversion提交作者名称映射到Git commiters ~/authors.txt

jmaddox = Jon Maddox <jon@gmail.com>
bigpappa = Brian Biggs <bigpappa@gmail.com>

然后,您可以将Subversion数据下载到Git存储库中:

mkdir repo && cd repo
git svn init http://subversion/repo --no-metadata
git config svn.authorsfile ~/authors.txt
git svn fetch

如果你在Mac上,你可以得到 git-svn 从MacPorts安装 git-core +svn

如果你的subversion存储库与你想要的git存储库在同一台机器上, 那么你可以将这个语法用于init步骤,否则完全相同:

git svn init file:///home/user/repoName --no-metadata

183
2017-09-21 02:15



当我评论另一个答案时,我不得不删除周围的空格 = 在 users.txt 因为导入正在中止,我得到一个空的存储库。 - Sebastián Grignoli
啊!简单有效的解释。在我的情况下 file:/// 拒绝工作,只是我用过 svnserve.exe --daemon 然后用 svn://localhost/home/user/repo 代替。 - Daniel Reis
在运行Mountain Lion的Mac上,git svn在我进入Xcode并安装了“首选项”窗格的“下载”选项卡中的命令行工具之后才能工作。或者,我本可以在Apple的开发者网站上安装OS X Mountain Lion的命令行工具。 - Drew
对于我的情况,我不得不转换文件 authors.txt 至 utf-8 without BOM。 - Silvan
这个链接似乎缺少一些信息 - Aran Mulholland


我使用了svn2git脚本,就像一个魅力! https://github.com/nirvdrum/svn2git


67
2017-09-26 13:13



问:这是否修复了标记和分支名称中的空格(在svn中允许并且在git中不允许)? - spazm
本指南使用它很有帮助: troyhunt.com/2014/08/migrating-from-subversion-to-git-with.html - Morten Holmgaard
这对我来说有问题: groups.google.com/forum/#!topic/msysgit/7MQVwRO-2N4  - 也可以看看: github.com/nirvdrum/svn2git/issues/50  解决方案在这里: stackoverflow.com/questions/3009738/... - HDave
最好解释答案,否则我们会产生脚本小子。 - Josh Habdas
如果您的分支机构都在SVN的根目录中并且您没有中继线或标签,那该怎么办? - Kal


我建议在尝试不断使用git-svn之前熟悉Git,即保持SVN为集中式仓库并在本地使用Git。

但是,对于包含所有历史记录的简单迁移,以下是几个简单的步骤:

初始化本地仓库:

mkdir project
cd project
git svn init http://svn.url

标记您想要开始导入修订的距离:

git svn fetch -r42

(或者只是所有转速的“git svn fetch”)

从那时起实际上取了所有东西:

git svn rebase

您可以使用Gitk检查导入的结果。我不确定这是否适用于Windows,它适用于OSX和Linux:

gitk

当您在本地克隆SVN repo时,您可能希望将其推送到集中的Git仓库以便于协作。

首先创建您的空远程仓库(也许开启 GitHub上?):

git remote add origin git@github.com:user/project-name.git

然后,可选地同步您的主分支,以便当两个包含新内容时,pull操作将自动将远程主服务器与您的本地主服务器合并:

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

在那之后,你可能有兴趣尝试我自己的 git_remote_branch 工具,有助于处理远程分支:

第一个解释性帖子:“Git远程分支机构

最新版本的后续行动:“是时候git与git_remote_branch合作了


56



非常有帮助,这非常有效。我想补充说,如果要同步到远程存储库,还有最后一步。在git配置步骤之后,我需要 git push origin master - mag382


有一种新的解决方案可以顺利地从Subversion迁移到Git(或同时使用两者):SubGit(http://subgit.com/)。

我自己正在做这个项目。我们在我们的存储库中使用SubGit - 我的一些队友使用Git和一些Subversion,到目前为止它的效果非常好。

要使用SubGit从Subversion迁移到Git,您需要运行:

$ subgit install svn_repos
...
TRANSLATION SUCCESSFUL 

之后你将获得svn_repos / .git中的Git存储库并可以克隆它,或者继续一起使用Subversion和这个新的Git存储库:SubGit将确保两者始终保持同步。

如果您的Subversion存储库包含多个项目,那么将在svn_repos / git目录中创建多个Git存储库。要在运行之前自定义翻译,请执行以下操作:

$ subgit configure svn_repos
$ edit svn_repos/conf/subgit.conf (change mapping, add authors mapping, etc)
$ subgit install svn_repos

SubGit 您可以迁移到纯Git(而不是git-svn)并开始使用它,同时在您需要时仍保留Subversion(例如,对于您已配置的构建工具)。

希望这可以帮助!


29



注意一次性导入(使用 subgit import 命令)似乎甚至不需要许可证。准确的翻译 svn:ignore 财产 .gitignore 文件也包括在内。 - krlmlr
SubGit无法识别我的私钥,也无法识别我在命令行中设置的任何标志。文档很差。这不是一个可行的选择 git svn。 - pfnuesel
错误:'svn_repos'不是有效的配置位置; SubGit配置文件丢失。 - Jon Davis


见官方 git-svn联机帮助页。特别是,请查看“基本示例”:

跟踪并贡献整个Subversion管理的项目(完整       带有主干,标签和分支):

# Clone a repo (like git clone):
    git svn clone http://svn.foo.org/project -T trunk -b branches -t tags

16





Pro Git 8.2解释了它: http://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git


14



Pro Git说明包括迁移标签和分支。它使用本地mv而不是svn命令。聪明。 - spazm