1565

我阅读了 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

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

4

34 回答 34

1617

创建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/ {gsub(/ /, "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt

如果 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”标志意味着您具有通用的“主干/、分支/、标签/”SVN 布局。如果您的布局不同,请熟悉--tags--branches--trunk选项(通常git svn help)。

允许所有常用协议:svn://, http://, https://. URL 应该以基本存储库为目标,例如http://svn.mycompany.com/myrepo/repository。URL 字符串不能包含/trunk,/tag/branches

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

另请注意,如果您省略该--no-metadata标志,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 names

标签作为分支导入。您必须创建一个本地分支,创建一个标签并删除该分支才能将它们作为 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
于 2010-10-19T19:45:07.157 回答
540

魔法:

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

Git 和 SVN 的运作方式非常不同。你需要学习 Git,如果你想跟踪 SVN 上游的变化,你需要学习git-svn. git-svn 主页有一个很好的示例部分:

$ git svn --help
于 2008-09-17T02:08:25.197 回答
201

干净地将您的 Subversion 存储库迁移到 Git 存储库。首先,您必须创建一个文件,将您的 Subversion 提交作者姓名映射到 Git 提交者,例如~/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
于 2008-09-17T02:10:22.180 回答
73

我使用了svn2git 脚本,效果非常好。

于 2011-02-01T07:53:50.143 回答
60

我建议在尝试不断使用 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 存储库时,您可能希望将其推送到集中式 Git 存储库以便于协作。

首先创建你的空远程仓库(也许在GitHub 上?):

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

然后,可以选择同步您的主分支,以便当两者都包含新内容时,拉取操作将自动将远程 master 与本地 master 合并:

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

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

第一篇解释性帖子:“ Git 远程分支

最新版本的跟进:“ git 与 git_remote_branch 协作的时间

于 2008-09-17T18:20:16.700 回答
33

有一个新的解决方案可以从 Subversion 平滑迁移到 Git(或同时使用两者):SubGit

我自己也在做这个项目。我们在我们的存储库中使用 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(例如,对于您已经配置的构建工具)。

希望这可以帮助!

于 2011-11-24T20:12:41.430 回答
20

请参阅官方git-svn 手册页。特别是,在“基本示例”下查看:

跟踪和贡献整个 Subversion 管理的项目(包括主干、标签和分支):

# Clone a repo (like git clone):
    git svn clone http://svn.foo.org/project -T trunk -b branches -t tags
于 2008-09-17T17:09:55.480 回答
14

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

于 2011-02-11T21:17:27.193 回答
14

SubGit(与蓝屏死机相比)

subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

就是这样。

+ 要从 SVN 更新,第一个命令会创建一个 Git 存储库。

subgit import  directory/path/Local.git.Repo

我使用了一种方法来立即迁移到 Git 以获得巨大的存储库。
当然,你需要一些准备。
但是您可能根本不会停止开发过程。

这是我的方式。

我的解决方案如下所示:

  • 将 SVN 迁移到 Git 存储库
  • 在团队切换到.

对于大型 SVN 存储库,迁移需要大量时间。
但是更新完成的迁移只需几秒钟。

当然,我正在使用SubGit,妈妈。git-svn 让我蓝屏死机。只是不断。git-svn 让我厌烦了 Git 的“文件名太长”致命错误。

脚步

1. 下载SubGit

2.准备迁移和更新命令。

假设我们是为 Windows 做的(移植到 Linux 很简单)。
在 SubGit 的安装bin目录 (subgit-2.XX\bin) 中,创建两个 .bat 文件。

迁移的文件/命令的内容:

start    subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

“开始”命令在这里是可选的 (Windows)。它将允许在启动时查看错误,并在 SubGit 完成后打开一个 shell。

您可以在此处添加类似于 git-svn 的附加参数。我只使用--default-domain myCompanyDomain.com来修复 SVN 作者的电子邮件地址的域。
我有标准的 SVN 存储库的结构(主干/分支/标签),我们没有遇到“作者映射”的问题。所以我什么都不做了。

(如果您想迁移分支之类的标签,或者您的 SVN 有多个分支/标签文件夹,您可以考虑使用更详细的 SubGit方法

提示 1:使用 --minimal-revision YourSvnRevNumber 快速查看事情的结果(某种调试)。特别有用的是查看已解析的作者姓名或电子邮件。
或者限制迁移历史深度。

提示 2:迁移可能会被中断 ( Ctrl+ C) 并通过运行下一个更新命令/文件来恢复。
我不建议对大型存储库这样做。我收到“内存不足 Java+Windows 异常”。

提示 3:最好创建结果裸存储库的副本。

用于更新的文件/命令的内容:

start    subgit import  directory/path/Local.git.Repo

当您想要获取最后一个团队对您的 Git 存储库的提交时,您可以随时运行它。

警告!不要触摸您的裸存储库(例如创建分支)。
您将遇到下一个致命错误:

不可恢复的错误:不同步且无法同步...正在将 Subversion 修订版转换为 Git 提交...

3.运行第一个命令/文件。大型存储库需要很长时间。我不起眼的存储库需要 30 小时。

就是这样。
您可以通过运行第二个文件/命令随时从 SVN 更新您的 Git 存储库。在将您的开发团队切换到 Git 之前。
只需几秒钟。



还有一项更有用的任务。

将本地 Git 存储库推送到远程 Git 存储库

是你的情况吗?让我们继续。

  1. 配置你的遥控器

跑:

$ git remote add origin url://your/repo.git
  1. 准备将巨大的本地 Git 存储库初始发送到远程存储库

默认情况下,你的 Git 不能发送大块。 致命:远端意外挂断

让我们为它奔跑:

git config --global http.postBuffer 1073741824

524288000 - 500 MB 1073741824 - 1 GB 等

修复本地证书问题。如果您的 git-server 使用损坏的证书。

我有禁用证书

此外,您的 Git 服务器可能有需要更正的请求数量限制

  1. 将所有迁移推送到团队的远程 Git 存储库。

使用本地 Git 运行:

git push origin --mirror

(旧 Git 版本的 git push origin '*:*' )

如果您收到以下信息:错误:无法生成 git:没有这样的文件或目录……对我来说,完全重建我的存储库可以解决这个错误(30 小时)。您可以尝试下一个命令

git push origin --all
git push origin --tags

或者尝试重新安装 Git对我没用)。或者您可以从所有标签创建分支并推送它们。或者,或者,或者……

于 2015-02-06T11:12:04.073 回答
12

重新开始

对于复杂的病例, Eric S. Raymond的reposurgeon是首选工具。除了 SVN 之外,它还通过fast-export格式支持许多其他版本控制系统,还支持CVS。作者报告了EmacsFreeBSD等古老存储库的成功转换。

该工具显然旨在接近完美的转换(例如将 SVN 的svn:ignore属性转换为.gitignore文件),即使对于具有悠久历史的困难存储库布局也是如此。在许多情况下,其他工具可能更易于使用。

在深入研究reposurgeon命令行文档之前,请务必阅读出色的DVCS 迁移指南,该指南逐步介绍了转换过程。

于 2015-03-20T18:20:29.037 回答
8

atlassian 网站上的本指南是我发现的最好的指南之一:

https://www.atlassian.com/git/migration

这个工具 - https://bitbucket.org/atlassian/svn-migration-scripts - 对于生成您的authors.txt 也非常有用。

于 2014-03-13T13:58:34.153 回答
8
于 2014-07-22T04:36:33.677 回答
7

GitHub 现在具有从 SVN 存储库导入的功能。不过,我从未尝试过。

于 2008-09-21T02:15:07.947 回答
7

仅使用 git、SVN 和 bash 的一些扩展答案。它包括不使用带有 trunk/branches/tags 目录布局的常规布局的 SVN 存储库的步骤(SVN 绝对不会强制执行这种布局)。

首先使用此 bash 脚本扫描您的 SVN 存储库以查找不同的贡献者,并为映射文件生成模板:

#!/usr/bin/env bash
authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
for author in ${authors}; do
  echo "${author} = NAME <USER@DOMAIN>";
done

使用它来创建一个authors文件,在其中将 svn 用户名映射到开发人员使用git config属性user.name和设置的用户名和电子邮件user.email(请注意,对于像 GitHub 这样的服务,只有匹配的电子邮件就足够了)。

然后git svn将 svn 存储库克隆到 git 存储库,告诉它映射:

git svn clone --authors-file=authors --stdlayout svn://example.org/Folder/projectroot

这可能需要非常长的时间,因为 git svn 将单独检查每个存在的标签或分支的每个修订。(请注意,SVN 中的标签只是真正的分支,因此它们最终在 Git 中也是如此)。您可以通过删除 SVN 中不需要的旧标签和分支来加快速度。

在同一网络中的服务器或同一服务器上运行它也可以真正加快速度。此外,如果由于某种原因此过程被中断,您可以使用

git svn rebase --continue

在很多情况下,你已经完成了。但是,如果您的 SVN 存储库有一个非常规的布局,您只需在 SVN 中有一个目录,您想放入一个 git 分支,您可以执行一些额外的步骤。

最简单的方法是在您的服务器上创建一个新的 SVN 存储库,该存储库遵循约定并用于svn copy将您的目录放在主干或分支中。如果您的目录一直位于存储库的根目录,这可能是唯一的方法,当我上次尝试时,这git svn只是拒绝进行结帐。

您也可以使用 git 执行此操作。只需使用要git svn clone放入 git 分支的目录即可。

运行后

git branch --set-upstream master git-svn
git svn rebase

请注意,这需要 Git 1.7 或更高版本。

于 2013-09-25T09:23:33.273 回答
7

我已经发布了一步一步的指南(这里)将 svn 转换为 git,包括将 svn 标签转换为 git 标签和 svn 分支转换为 git 分支。

简洁版本:

1) 从特定的修订号克隆 svn。(修订号必须是您要迁移的最早版本)

git svn clone --username=yourSvnUsername -T trunk_subdir -t tags_subdir -b branches_subdir -r aRevisionNumber svn_url gitreponame

2)获取svn数据。这一步是最耗时的一步。

cd gitreponame
git svn fetch

重复 git svn fetch 直到完成且没有错误

3) 更新主分支

git svn rebase

4) 通过复制引用从 svn 分支创建本地分支

cp .git/refs/remotes/origin/* .git/refs/heads/

5)将svn标签转换为git标签

git for-each-ref refs/remotes/origin/tags | sed 's#^.*\([[:xdigit:]]\{40\}\).*refs/remotes/origin/tags/\(.*\)$#\2 \1#g' | while read p; do git tag -m "tag from svn" $p; done

6) 将存储库放在更好的地方,例如 github

git remotes add newrepo git@github.com:aUser/aProjectName.git
git push newrepo refs/heads/*
git push --tags newrepo

如果您想了解更多详细信息,请阅读我的帖子或询问我。

于 2016-02-24T14:45:17.963 回答
6

我们可以使用git svn clone如下命令。

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

上面的命令将从 SVN 提交创建作者文件。

  • svn log --stop-on-copy <SVN_URL>

当你的 SVN 项目创建时,上面的命令会给你第一个修订号。

  • git svn clone -r<SVN_REV_NO>:HEAD --no-minimize-url --stdlayout --no-metadata --authors-file authors.txt <SVN_URL>

上面的命令将在本地创建 Git 存储库。

问题是它不会将分支和标签转换为推送。您将不得不手动执行它们。例如下面的分支:

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
* master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$$ git checkout -b MyDevBranch origin/MyDevBranch
Branch MyDevBranch set up to track remote branch MyDevBranch from origin.
Switched to a new branch 'MyDevBranch'
$ git branch -a
* MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$

对于标签:

$git checkout origin/tags/MyDevBranch-1.0
Note: checking out 'origin/tags/MyDevBranch-1.0'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 3041d81... Creating a tag
$ git branch -a
* (detached from origin/tags/MyDevBranch-1.0)
  MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$ git tag -a MyDevBranch-1.0 -m "creating tag"
$git tag
MyDevBranch-1.0
$

现在将 master、branchs 和 tags 推送到远程 git 存储库。

$ git push origin master MyDevBranch MyDevBranch-1.0
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (14/14), 2.28 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To https://github.com/pankaj0323/JDProjects.git
 * [new branch]      master -> master
 * [new branch]      MyDevBranch -> MyDevBranch
 * [new tag]         MyDevBranch-1.0 -> MyDevBranch-1.0
$

svn2git 实用程序

svn2git实用程序消除了使用分支和标签的手动工作。

使用命令安装它sudo gem install svn2git。之后运行以下命令。

  • $ svn2git <SVN_URL> --authors authors.txt --revision <SVN_REV_NO>

现在您可以列出分支、标签并轻松推送它们。

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
  MyDevBranch
* master
  remotes/svn/MyDevBranch
  remotes/svn/trunk
$ git tag
  MyDevBranch-1.0
$ git push origin master MyDevBranch MyDevBranch-1.0

想象一下,你有 20 个分支和标签,显然 svn2git 会为你节省很多时间,这就是为什么我比原生命令更喜欢它的原因。这是一个很好的原生命令包装器git svn clone

有关完整示例,请参阅我的博客条目

于 2016-05-02T16:13:49.740 回答
5

TortoiseGit 就是这样做的。看到这篇博文:http: //jimmykeen.net/articles/03-nov-2012/how-migrate-from-svn-to-git-windows-using-tortoise-clients

是的,我知道用链接回答不是很好,但它是一个解决方案,嗯?

于 2013-04-18T03:41:17.967 回答
4

对于GitLab用户,我在这里提出了我如何从 SVN 迁移的要点:

https://gist.github.com/leftclickben/322b7a3042cbe97ed2af

从 SVN 迁移到 GitLab 的步骤

设置

  • SVN 托管在svn.domain.com.au.
  • SVN 可以通过http(其他协议应该可以)访问。
  • GitLab 托管于git.domain.com.au
    • 使用命名空间创建一个组dev-team
    • 至少创建一个用户帐户,将其添加到组中,并具有用于迁移的帐户的 SSH 密钥(使用 测试ssh git@git.domain.com.au)。
    • 该项目favourite-project是在dev-team命名空间中创建的。
  • 该文件users.txt包含相关的用户详细信息,每行一个用户,格式为username = First Last <address@domain.com.au>,其中username是 SVN 日志中给出的用户名。(有关详细信息,请参阅参考部分中的第一个链接,特别是用户 Casey 的回答)。

版本

  • 颠覆版本 1.6.17 (r1128011)
  • 混帐版本 1.9.1
  • GitLab 版本 7.2.1 ff1633f
  • Ubuntu 服务器 14.04

命令

bash
git svn clone --stdlayout --no-metadata -A users.txt 
http://svn.domain.com.au/svn/repository/favourite-project
cd favourite-project
git remote add gitlab git@git.domain.com.au:dev-team/favourite-project.git
git push --set-upstream gitlab master

就是这样!在 GitLab Web UI 中重新加载项目页面,您将看到现在列出的所有提交和文件。

笔记

  • 如果有未知用户,该git svn clone命令将停止,在这种情况下,更新users.txtcd favourite-project并将git svn fetch从它停止的地方继续。
  • trunkSVN 存储库的标准布局是必需的tagsbranches
  • 提供给git svn clone命令的 SVN URL 停止在紧接在上面的级别trunk/tags/并且branches/
  • git svn clone命令产生大量输出,包括顶部的一些警告;我忽略了警告。
于 2014-09-13T13:04:29.957 回答
3

我强烈推荐我刚刚发现的这个简短的截屏视频系列。作者带您了解基本操作,并展示一些更高级的用法。

于 2011-03-22T00:34:48.103 回答
3

如果您使用 SourceTree,您可以直接从应用程序执行此操作。转到文件-> 新建/克隆,然后执行以下操作:

  1. 输入远程 SVN URL 作为“源路径/URL”。
  2. 出现提示时输入您的凭据。
  3. 输入本地文件夹位置作为“目标路径”。
  4. 给它一个名字。
  5. 在高级选项中,从“创建类型的本地存储库”的下拉列表中选择“Git”。
  6. 您可以选择指定要从中克隆的修订。
  7. 点击克隆。

在 SourceTree 中打开 repo,您​​将看到您的提交消息也已迁移。

现在转到存储库 -> 存储库设置并添加新的远程存储库详细信息。如果您愿意,请删除 SVN 远程(我通过“编辑配置文件”选项执行此操作。

当您准备好并自由编码时,将代码推送到新的远程仓库。

于 2014-06-17T04:43:33.357 回答
2

另外,当尝试使用 git-svn dcommits 进行 git 操作时,git-stash 命令是天赐之物。

一个典型的过程:

  1. 设置 git 仓库
  2. 对不同的文件做一些工作
  3. 决定检查一些工作,使用 git
  4. 决定要svn-dcommit
  5. 得到可怕的“不能用脏索引提交”错误。

解决方案(需要 git 1.5.3+):

git stash; git svn dcommit ; git stash apply
于 2008-09-26T13:13:26.187 回答
2

我只是想将我的贡献添加到 Git 社区。我编写了一个简单的 bash 脚本,它可以自动执行完整的导入。与其他迁移工具不同,该工具依赖于原生 git 而不是 jGit。此工具还支持具有大量修订历史和/或大型 blob 的存储库。它可以通过 github 获得:

https://github.com/onepremise/SGMS

此脚本将使用以下格式转换存储在 SVN 中的项目:

/trunk
  /Project1
  /Project2
/branches
     /Project1
     /Project2
/tags
 /Project1
 /Project2

该方案也很受欢迎并受到支持:

/Project1
     /trunk
     /branches
     /tags
/Project2
     /trunk
     /branches
     /tags

每个项目将按项目名称同步:

Ex: ./migration https://svnurl.com/basepath project1

如果您希望转换完整的 repo,请使用以下语法:

Ex: ./migration https://svnurl.com/basepath .
于 2012-02-16T18:28:52.833 回答
2

这是一个没有依赖关系的简单 shell 脚本,它将一个或多个 SVN 存储库转换为 git 并将它们推送到 GitHub。

https://gist.github.com/NathanSweet/7327535

在大约 30 行脚本中:使用 git SVN 克隆,从 SVN::ignore 属性创建 .gitignore 文件,推送到裸 git 存储库,将 SVN 主干重命名为 master,将 SVN 标签转换为 git 标签,并将其推送到 GitHub同时保留标签。

为了将十几个 SVN 存储库从 Google Code 迁移到 GitHub,我经历了很多痛苦。我使用 Windows 并没有帮助。Ruby 在我的旧 Debian 机器上被各种损坏了,让它在 Windows 上运行是个笑话。其他解决方案无法使用 Cygwin 路径。即使我得到了一些工作,我也无法弄清楚如何让标签显示在 GitHub 上(秘密是 --follow-tags)。

最后,我拼凑了两个简短的脚本,链接在上面,效果很好。解决方案不需要比这更复杂!

于 2013-11-06T14:06:24.420 回答
2

我在一台 Windows 机器上,并制作了一个小批量,只需调用即可将具有历史记录(但没有分支)的 SVN 存储库转移到 GIT 存储库

transfer.bat http://svn.my.address/svn/myrepo/trunk https://git.my.address/orga/myrepo

也许任何人都可以使用它。它创建一个 TMP 文件夹,用 git 签出那里的 SVN 存储库,并添加新的来源并推送它......并再次删除该文件夹。

@echo off 
SET FROM=%1 
SET TO=%2 
SET TMP=tmp_%random%

echo from:  %FROM% 
echo to:    %TO% 
echo tmp:   %TMP%

pause

git svn clone  --no-metadata --authors-file=users.txt %FROM% %TMP%  
cd %TMP% 
git remote add origin %TO% 
git push --set-upstream origin master


cd .. 
echo delete %TMP% ... 
pause

rmdir /s /q %TMP%

您仍然需要 users.txt 和您的用户映射,例如

User1 = User One <u.1@xxx.com>
于 2018-02-06T06:37:45.860 回答
1

首先,归功于@cmcginty 的回答。这对我来说是一个很好的起点,我将在这里发布的大部分内容都大量借鉴了它。然而,我正在移动的存储库有多年的历史,这导致了在对这封信的答复之后出现了一些问题(数百个分支和标签需要手动移动;稍后阅读更多内容)。

因此,经过数小时的搜索和反复试验,我能够编写一个脚本,使我可以轻松地将多个项目从 SVN 迁移到 GIT,并且我决定在这里分享我的发现,以防其他人站在我的立场上。

<tl;dr> 让我们开始吧


首先,创建一个“作者”文件,它将基本的 svn 用户转换为更复杂的 git 用户。最简单的方法是使用命令从您要移动的 svn 存储库中提取所有用户。

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

这将生成一个名为 authors-transform.txt 的文件,其中每个用户在运行它的 svn 存储库中进行了更改。

someuser = someuser <someuser>

更新以包含 git 的全名和电子邮件

someuser = Some User <someuser@somewhere.com>

现在使用您的作者文件开始克隆

git svn clone --stdlayout --no-metadata -r854:HEAD --authors-file=authors-transform.txt https://somesvnserver/somerepo/ temp
  • --stdlayout 表示 svn repo 遵循标准 /trunk /branches /tags 布局
  • --no-metadata 告诉 git 不要在每个 git 提交上标记与 svn 提交相关的元数据。如果这不是单向转换,请删除此标签
  • -r854:HEAD 仅获取修订版 854 以上的历史记录。这是我遇到的第一个障碍;我正在转换的 repo 在修订版 853 中有一个“损坏的”提交,因此它不会克隆。使用此参数允许您仅克隆部分历史记录。
  • temp 是为初始化新的 git 存储库而创建的目录的名称

此步骤可能需要一段时间,尤其是在大型或旧的 repo 上(我们的一个大约需要 18 小时)。您还可以使用该 -r 开关仅获取一小段历史记录来查看克隆,然后再获取其余部分。

移动到新目录

cd temp

如果您仅在克隆中提取部分内容,则获取任何丢失的历史记录

git svn fetch

标签在克隆期间创建为分支。如果您只有几个,则可以一次转换一个。

git 1.0.0 origin/tags/1.0.0

但是,如果您有数百个标签,这会很乏味,因此以下脚本对我有用。

for brname in `git branch -r | grep tags | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do echo $brname; tname=${brname:5}; echo $tname; git tag $tname origin/tags/$tname; done

您还需要检查您想要保留的所有分支

git checkout -b branchname origin/branches/branchname

如果你也有很多分支,这个脚本可能会有所帮助

for brname in `git branch -r | grep -v master | grep -v HEAD | grep -v trunk | grep -v tags | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do echo $brname; git checkout -b $brname origin/$brname; done

这将忽略主干分支,因为它已经作为主分支检出,并在稍后删除重复分支保存步骤,并忽略我们已经转换的 /tags。

现在是查看新存储库的好时机,并确保您有一个本地分支或标签来存放您想要保留的任何内容,因为稍后将删除远程分支。

好的,现在让我们将我们签出的所有内容克隆到一个干净的 repo(这里命名为 temp2)

cd ..
git clone temp temp2
cd temp2

现在我们需要再次检查所有分支,然后再将它们推送到它们的最终远程,因此请从上面按照您最喜欢的方法进行操作。

如果您正在关注 gitflow,您可以将您的工作分支重命名为开发。

git checkout -b WORKING
git branch -m develop
git push origin --delete WORKING
git push origin -u develop

现在,如果一切看起来都不错,您就可以推送到您的 git 存储库了

git remote set-url origin https://somebitbucketserver/somerepo.git
git push -u origin --all
git push origin --tags

我确实遇到了最后一个问题,即 Control Freak 最初阻止我推送不是我创建的标签,因此如果您的团队使用 Control Freak,您可能需要禁用或调整该设置以进行初始推送。

于 2020-08-24T23:45:48.443 回答
0

通过 Subversion 有效地使用 Git是对 git-svn 的温和介绍。对于现有的 SVN 存储库,git-svn 使这变得超级简单。如果您正在启动一个新的存储库,那么首先创建一个空的 SVN 存储库然后使用 git-svn 导入比相反的方向要容易得多。可以创建一个新的 Git 存储库然后导入 SVN,但这有点痛苦,特别是如果您是 Git 新手并希望保留提交历史。

于 2010-09-24T14:13:01.617 回答
0

下载适用于 Windows 的 Ruby 安装程序并使用它安装最新版本。将 Ruby 可执行文件添加到您的路径。

  • 安装 svn2git
  • 开始菜单 -> 所有程序 -> Ruby -> 使用 Ruby 启动命令提示符
  • 然后输入“gem install svn2git”并输入

    迁移 Subversion 存储库

  • 打开 Ruby 命令提示符并转到要迁移文件的目录

    然后 svn2git http://[域名]/svn/ [repository root]

  • 将项目迁移到 Git 可能需要几个小时,具体取决于项目代码大小。

  • 这个主要步骤有助于创建如下所述的 Git 存储库结构。

    SVN (/Project_components) 主干 --> Git master SVN (/Project_components) 分支 --> Git 分支 SVN (/Project_components) 标签 --> Git 标签

创建远程存储库并推送更改。

于 2015-07-09T13:19:08.817 回答
0

GitHub 有一个导入器。创建存储库后,您可以通过其 URL 从现有存储库导入。如果适用,它将询问您的凭据并从那里开始。

当它运行时,它会找到作者,你可以简单地将他们映射到 GitHub 上的用户。

我现在已经将它用于几个存储库,而且它非常准确且速度也快得多!大约 4000 次提交的存储库花了 10 分钟,而我的朋友花了四天时间!

于 2015-07-30T14:56:26.747 回答
0

这里的几个答案是指https://github.com/nirvdrum/svn2git,但对于大型存储库,这可能会很慢。我尝试使用https://github.com/svn-all-fast-export/svn2git代替它,它是一个名称完全相同但用于将 KDE 从 SVN 迁移到 Git 的工具。

设置它需要做更多的工作,但是当我完成转换后,我需要花费几分钟,而其他脚本则需要花费数小时。

于 2016-01-19T14:17:52.183 回答
0

有不同的方法可以实现这一目标。我已经尝试了其中的一些,发现在 Windows 操作系统上只安装了 git 和 svn 确实可以工作。

先决条件:

  1. Windows 上的 git(我用过这个)https://git-scm.com/
  2. 安装了控制台工具的 svn(我用过 tortoise svn)
  3. 转储您的 SVN 存储库的文件。 svnadmin dump /path/to/repository > repo_name.svn_dump

实现最终目标的步骤(将所有具有历史记录的存储库移动到 git,首先是本地 git,然后是远程)

  1. 在目录 REPO_NAME_FOLDER 中创建空存储库(使用控制台工具或 tortoiseSVN) cd REPO_NAME_PARENT_FOLDER,将 dumpfile.dump 放入 REPO_NAME_PARENT_FOLDER

  2. svnadmin load REPO_NAME_FOLDER < dumpfile.dump等待这个操作,可能会很长

  3. 这个命令是无声的,所以打开第二个 cmd 窗口:svnserve -d -R --root REPO_NAME_FOLDER 为什么不直接使用 file:///......?Unable to open ... to URL:由于答案https://stackoverflow.com/a/6300968/4953065 ,导致下一个命令将失败

  4. 创建新文件夹 SOURCE_GIT_FOLDER

  5. cd SOURCE_GIT_FOLDER
  6. git svn clone svn://localhost/ 等待这个操作。

最后,我们得到了什么?

让我们检查一下我们的本地存储库:

git log

看到你之前的提交了吗?如果是 - 好的

因此,现在您拥有功能齐全的本地 git 存储库,其中包含您的源代码和旧的 svn 历史记录。现在,如果要将其移动到某个服务器,请使用以下命令:

git remote add origin https://fullurlpathtoyourrepo/reponame.git
git push -u origin --all # pushes up the repo and its refs for the first time
git push -u origin --tags # pushes up any tags

就我而言,我不需要标签命令,因为我的仓库没有标签。

祝你好运!

于 2016-02-15T13:00:40.403 回答
0

将 svn 子模块/文件夹 'MyModule' 转换为具有历史记录的 git,没有标签或分支。

要保留 svn 忽略列表,请在步骤 1 之后使用上述注释

于 2016-06-07T16:02:29.763 回答
0

我使用以下脚本读取包含我所有 SVN 存储库列表的文本文件并将它们转换为 Git,然后git clone --bare用于转换为裸 Git 存储库:

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt 的格式为:

repo1_name
repo2_name

users.txt 格式如下:

(no author) = Prince Rogers <prince.rogers.nelson@payesley.park.org>

www-data 是 Apache Web 服务器用户,需要通过 HTTP 推送更改的权限。

于 2017-01-03T17:33:27.843 回答
0

SVN多合一 -用于GIT迁移的 shell 脚本。用占位符提及GITSVN细节<>

#!/bin/bash

######## Project name 
PROJECT_NAME="Helloworld"
EMAIL="example mail"

#Credientials Repo
GIT_USER='<git username>'
GIT_PWD='<git password>'
SVN_USER='<svn username>'
SVN_PWD='<svn password>'

######## SVN repository to be migrated # Dont use https - error will be thrown
BASE_SVN="<SVN URL>/Helloworld"

#Organization inside BASE_SVN
BRANCHES="branches"
TAGS="tags"
TRUNK="trunk"

#Credientials
git config --global user.name '<git username>'
git config --global user.password '<git password>'
git config --global credential.helper 'cache --timeout=3600'

######## GIT repository to migrate - Ensure already project created in Git
GIT_URL=https://$GIT_USER:$GIT_PWD@<GIT URL>/Helloworld.git

###########################
#### Don't need to change from here
###########################

#Geral Configuration
ABSOLUTE_PATH=$(pwd)
TMP=$ABSOLUTE_PATH/$PROJECT_NAME

#Branchs Configuration
SVN_BRANCHES=$BASE_SVN/$BRANCHES
SVN_TAGS=$BASE_SVN/$TAGS
SVN_TRUNK=$BASE_SVN/$TRUNK

AUTHORS=$PROJECT_NAME"-authors.txt"

echo '[LOG] Starting migration of '$SVN_TRUNK
echo '[LOG] Using: '$(git --version)
echo '[LOG] Using: '$(svn --version | grep svn,)

mkdir $TMP
echo
echo '[DIR] cd' $TMP
cd $TMP

echo
echo '[LOG] Getting authors'
svn --username $SVN_USER --password $SVN_PWD log -q $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2"@"$EMAIL">"}' | sort -u >> $AUTHORS

echo
echo '[RUN] git svn clone --authors-file='$AUTHORS' --trunk='$TRUNK' --branches='$BRANCHES' --tags='$TAGS $BASE_SVN $TMP
git svn clone --authors-file=$AUTHORS --trunk=$TRUNK --branches=$BRANCHES --tags=$TAGS $BASE_SVN $TMP

#Not working so no need to mention it
#--stdlayout $PROJECT_NAME
echo
echo '[RUN] svn ls '$SVN_BRANCHES
svn ls $SVN_BRANCHES

echo 
echo 'git branch -a'
git branch -a

echo
echo '[LOG] Getting first revision'
FIRST_REVISION=$( svn log -r 1:HEAD --limit 1 $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", $1); sub(" $", "", $1); print $1}' )

echo
echo '[RUN] git svn fetch -'$FIRST_REVISION':HEAD'
git svn fetch -$FIRST_REVISION:HEAD

#Branches and Tags  
echo
echo '[RUN] svn ls '$SVN_BRANCHES
for BRANCH in $(svn ls $SVN_BRANCHES); do
    echo git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
    git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
done

git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/origin/tags | grep -v "@" | cut -d / -f 3- |
while read ref
do
  echo git tag -a $ref -m 'import tag from svn'
  git tag -a $ref -m 'import tag from svn'
done

git for-each-ref --format="%(refname:short)" refs/remotes/origin/tags | cut -d / -f 1- |
while read ref
do
  git branch -rd $ref
done
  
echo
echo 'git tag'
git tag

echo
echo 'git show-ref --tags'
git show-ref --tags

echo
echo '[RUN] git remote add origin '$GIT_URL
git remote add origin $GIT_URL

echo
echo '[RUN] git push'
git push origin --all --force
git push origin --tags

#echo git branch -d -r trunk
#git branch -d -r trunk

git config --global credential.helper cache
echo 'Successful.'
  • 当您运行上述脚本时,它将从 SVN 获取分支和标签详细信息并将其放在.git文件夹下。
  • 交叉检查是否所有分支都存在于SVN该文件夹下应该可用的.git/refs/heads目录中。
  • 如果缺少某些分支,SVN那么请手动将分支文件从复制.git/refs/remotes/origin/<branches>.git/refs/heads
  • 仅复制分支(包括master)并忽略(如果有)tagstrunk.
  • 现在再次运行脚本。您可以在 git 存储库中branches查看所有内容。tags
于 2021-07-04T06:31:08.573 回答
-1

为此,我使用了 svn2git库,过程如下:

sudo apt-get install git-core git-svn ruby
​​ sudo gem install svn2git
svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | 剪切-d'|' -f2 | sed 's/ //g' | 排序 | uniq > authors.txt(此命令用于映射作者)

上述步骤应在您要从 svn 转换为 git 的文件夹中执行。

像这样在 authors.txt 中每行添加一个映射

anand = Anand Tripathi <email_id>
trip = Tripathi Anand <email_id>

为新的 git 存储库创建一个文件夹并执行以下命令,路径为 authors.txt

svn2git <svn_repo_path> --nobranches --notags --notrunk --no-minimize-url --username <user_name> --verbose  --authors <author.txt_path>

If no trunk and no tag and branch is present then have to execute the above command else if root is trunk then mention rootistrunk or trunk is present then --trunk <trunk_name>

git remote add origin
git push --all origin
git push --tags origin

于 2018-02-11T13:45:29.980 回答