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

时间:2008-09-17 02:04:21

标签: svn git version-control git-svn

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

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

34 个答案:

答案 0 :(得分:1515)

创建一个用户文件(即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数据:

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

此命令将在dest_dir-tmp中创建一个新的Git存储库,并开始拉动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标志,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

答案 1 :(得分:514)

魔术:

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

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

$ git svn --help

答案 2 :(得分:185)

Cleanly Migrate Your Subversion Repository To a Git Repository。首先,你必须创建一个文件,将你的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

答案 3 :(得分:69)

我使用svn2git script并且像魅力一样。

答案 4 :(得分:57)

我建议在尝试不断使用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 remote branches

最新版本的跟进:“Time to git collaborating with git_remote_branch

答案 5 :(得分:30)

有一种新的解决方案可以顺利地从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(例如,对于您已配置的构建工具)。

希望这有帮助!

答案 6 :(得分:17)

见官方git-svn manpage。特别是,请查看“基本示例”:

  

跟踪并参与整个Subversion管理的项目(完成       用树干,标签和树枝):

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

答案 7 :(得分:13)

答案 8 :(得分:13)

SubGit(vs蓝屏死机)

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存储库
  • 在团队转换为之前更新Git存储库。

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

我当然使用SubGit,妈妈。 git-svn让我Blue Screen of Death。只是不断。 git-svn让Git&#34; filename too long&#34;致命的错误。

<强> STEPS

1。 Download SubGit

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

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

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

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

&#34;开始&#34;命令在这里是可选的(Windows)。它允许在启动时看到错误,并在完成SubGit后打开一个shell。

您可以在此处添加additional parameters similar to git-svn。 我只使用 - default-domain myCompanyDomain.com 来修复SVN作者的电子邮件地址域。
我有标准的SVN存储库结构(主干/分支/标签),我们没有遇到过“作者映射”问题。所以我不再做任何事了。

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

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

提示2 :迁移可能会中断( Ctrl + C )并通过运行下一个更新命令/文件进行恢复。
我不建议为大型存储库执行此操作。我收到了#34;内存不足的Java + Windows异常&#34;。

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

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

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

如果您希望获得最后一个团队对Git存储库的提交,您可以运行任意次。

警告!请勿触摸您的裸存储库(例如,创建分支机构)。
你将接下来的致命错误:

  

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

3. 运行第一个命令/文件。它需要花费大量时间来建立一个大型存储库。我的简陋存储库需要30个小时。

全部。
您可以通过运行第二个文件/命令随时随地从SVN更新您的Git存储库。在将开发团队转换为Git之前。
它只需几秒钟。



还有一个更有用的任务。

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

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

  1. 配置您的遥控器
  2. 执行命令

    $ git remote add origin url://your/repo.git
    
    1. 准备将您庞大的本地Git存储库初始发送到远程存储库
    2. 默认情况下,你的Git无法发送大块数据。 fatal: The remote end hung up unexpectedly

      让我们为它奔跑:

      git config --global http.postBuffer 1073741824
      

      524288000 - 500 MB 1073741824 - 1 GB等

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

      我已停用certificates

      您的Git服务器也可能有request amount limitations needing to be corrected

      1. Push all migration加入团队的远程Git存储库。
      2. 使用本地Git运行:

        git push origin --mirror
        

        git push origin&#39; *:*&#39; 旧Git版本)

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

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

        或尝试reinstall Git对我无用)。 或者您可以从所有标签创建分支并推送它们。或者,或者......或者......

答案 9 :(得分:9)

reposurgeon

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

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

在深入研究reposurgeon命令行的文档之前,请务必阅读优秀的DVCS migration guide,逐步完成转换过程。

答案 10 :(得分:7)

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

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

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

答案 11 :(得分:7)

你必须安装

git
git-svn

从此链接http://john.albin.net/git/convert-subversion-to-git复制。

<强> 1。检索所有Subversion提交者的列表

Subversion只列出每次提交的用户名。 Git的提交有更丰富的数据,但最简单的是,提交作者需要列出名称和电子邮件。默认情况下,git-svn工具只会在作者和电子邮件字段中列出SVN用户名。但是通过一些工作,您可以创建所有SVN用户的列表以及他们相应的Git名称和电子邮件。 git-svn可以使用此列表将普通的svn用户名转换为适当的Git提交者。

从本地Subversion结帐的根目录运行以下命令:

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

这将获取所有日志消息,拔出用户名,消除任何重复的用户名,对用户名进行排序并将它们放入“authors-transform.txt”文件中。现在编辑文件中的每一行。例如,转换:

jwilkins = jwilkins <jwilkins>

进入这个:

jwilkins = John Albin Wilkins <johnalbin@example.com>

<强> 2。使用git-svn

克隆Subversion存储库
git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp

这将执行标准的git-svn转换(使用您在步骤1中创建的authors-transform.txt文件)并将git存储库放在主目录中的“〜/ temp”文件夹中。

第3。将svn:ignore属性转换为.gitignore

如果您的svn repo使用svn:ignore属性,您可以使用以下命令轻松将其转换为.gitignore文件:

cd ~/temp
git svn show-ignore > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'

<强> 4。将存储库推送到裸git存储库

首先,创建一个裸存储库并使其默认分支匹配svn的“trunk”分支名称。

git init --bare ~/new-bare.git
cd ~/new-bare.git
git symbolic-ref HEAD refs/heads/trunk

然后将临时存储库推送到新的裸存储库。

cd ~/temp
git remote add bare ~/new-bare.git
git config remote.bare.push 'refs/remotes/*:refs/heads/*'
git push bare

您现在可以安全地删除〜/ temp存储库。

<强> 5。将“trunk”分支重命名为“master”

您的主开发分支将命名为“trunk”,它与Subversion中的名称相匹配。您需要使用以下命令将其重命名为Git的标准“主”分支:

cd ~/new-bare.git
git branch -m trunk master

<强> 6。清理分支和标签

git-svn将所有Subversions标签放入Git中的“tags / name”形式的非常短的分支中。您将要使用以下命令将所有这些分支转换为实际的Git标记:

cd ~/new-bare.git
git for-each-ref --format='%(refname)' refs/heads/tags |
cut -d / -f 4 |
while read ref
do
  git tag "$ref" "refs/heads/tags/$ref";
  git branch -D "tags/$ref";
done

这一步将需要一些打字。 :-)但是,别担心;你的unix shell会提供一个&gt;以git for-each-ref。

开头的超长命令的辅助提示符

答案 12 :(得分:6)

使用git,SVN和bash稍微扩展一下。它包括SVN存储库的步骤,这些存储库不使用带有trunk / branches / tags目录布局的传统布局(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文件,您可以使用git config属性user.name属性user.emailgit svn clone --authors-file=authors --stdlayout svn://example.org/Folder/projectroot将svn用户名映射到用户名和电子邮件(请注意,像GitHub这样只有匹配电子邮件的服务就足够了。

然后让git svn将svn存储库克隆到git存储库,告诉它有关映射的信息:

git svn rebase --continue

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

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

恢复它

svn copy

在很多情况下,你在这里完成了。但是如果你的SVN repo有一个非传统的布局,你只需要在SVN中有一个目录,你想放入一个git分支,你可以做一些额外的步骤。

最简单的方法是在您的服务器上创建一个符合约定的新SVN仓库,并使用git svn将您的目录放在trunk或分支中。这可能是唯一的方法,如果你的目录一直在回购的根目录,当我上次尝试这个git svn clone时,只是拒绝办理结账。

您也可以使用git执行此操作。对于git branch --set-upstream master git-svn git svn rebase ,只需使用您想要放在git分支中的目录。

运行后

{{1}}

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

答案 13 :(得分:6)

GitHub现在具有import from an SVN repository的功能。但我从未尝试过。

答案 14 :(得分:5)

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

简短版本:

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

如果您想了解更多详情,请阅读我的post或者问我。

答案 15 :(得分:5)

我们可以使用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,branches和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命令的一个很好的包装器。

有关完整示例,请参阅我的blog entry

答案 16 :(得分:4)

TortoiseGit这样做。请参阅此博文:http://jimmykeen.net/articles/03-nov-2012/how-migrate-from-svn-to-git-windows-using-tortoise-clients

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

答案 17 :(得分:3)

如果您使用的是SourceTree,可以直接从应用程序执行此操作。转到文件 - &gt; New / Clone然后执行以下操作:

  1. 输入远程SVN URL作为“源路径/ URL”。
  2. 出现提示时输入您的凭据。
  3. 输入本地文件夹位置作为“目标路径”。
  4. 给它起个名字。
  5. 在高级选项中,从“创建本地”下拉列表中选择“Git” “。
  6. 类型的存储库
  7. 您可以选择指定要克隆的修订版。
  8. 点击克隆。
  9. 在SourceTree中打开repo,您​​将看到您的提交消息也已迁移。

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

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

答案 18 :(得分:3)

对于 GitLab 用户,我已经详细说明了我如何从SVN迁移到这里:

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

从SVN迁移到GitLab的步骤

设置

  • SVN托管在svn.domain.com.au
  • 可以通过http访问SVN(其他协议应该可以使用)。
  • 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)
  • git version 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-projectgit svn fetch将从停止的位置继续。
  • 需要SVN存储库的标准trunk - tags - branches布局。
  • git svn clone命令的SVN网址位于trunk/tags/branches/的正上方。
  • git svn clone命令产生大量输出,包括顶部的一些警告;我忽略了警告。

答案 19 :(得分:3)

我强烈推荐我刚刚发现的这个short series of screencasts。作者将引导您完成基本操作,并展示一些更高级的用法。

答案 20 :(得分: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)。

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

答案 21 :(得分:2)

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

一个典型的过程:

  1. 设置git repo
  2. 对不同的文件做一些工作
  3. 决定使用git
  4. 检查一些工作
  5. 决定svn-dcommit
  6. 得到可怕的“无法使用脏索引提交”错误。
  7. 解决方案(需要git 1.5.3+):

    git stash; git svn dcommit ; git stash apply
    

答案 22 :(得分:2)

我在Windows机器上做了一个小批处理,通过调用

将带有历史记录(但没有分支)的SVN仓库转移到GIT仓库

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

也许任何人都可以使用它。它创建一个TMP文件夹,用git检出SVN repo并添加新的原点并将其推送...并再次删除该文件夹。

@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>

答案 23 :(得分:1)

我只想将我的贡献添加到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

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

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

答案 24 :(得分:0)

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

  • 安装svn2git
  • 开始菜单 - &gt;所有节目 - &gt; Ruby - &gt;使用Ruby
  • 启动命令提示符
  • 然后输入“gem install svn2git”并输入

    迁移Subversion存储库

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

    然后svn2git http://[domain name] / svn / [repository root]

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

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

    SVN(/ Project_components)主干 - &gt; Git大师 SVN(/ Project_components)分支 - &gt; Git分支 SVN(/ Project_components)标签 - &gt; Git标签

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

答案 25 :(得分:0)

GitHub有一个进口商。创建存储库后,您可以通过其URL从现有存储库导入。如果适用,它会要求您提供凭证并从那里开始。

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

我现在已将它用于一些存储库,而且它非常准确且速度也快得多!对于一个拥有~4000次提交的存储库花了10分钟,之后我的朋友花了四天时间!

答案 26 :(得分:0)

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

设置它的工作稍微多一些,但完成后,转换本身对我来说花费了几分钟,其他脚本花了几个小时。

答案 27 :(得分:0)

有不同的方法来实现这一目标。我已经尝试了其中一些,并且发现在Windows操作系统上安装了git和svn之后真正工作了。

先决条件:

  1. git on windows(我已经使用过这个)https://git-scm.com/
  2. 安装了控制台工具的svn(我用过tortoise svn)
  3. 您的SVN存储库的转储文件。 svnadmin dump /path/to/repository > repo_name.svn_dump
  4. 实现最终目标的步骤(将历史记录移动到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:/// ......?由于答案https://stackoverflow.com/a/6300968/4953065

    4. ,导致下一个命令将失败并显示Unable to open ... to URL:
    5. 创建新文件夹SOURCE_GIT_FOLDER

    6. cd SOURCE_GIT_FOLDER
    7. git svn clone svn:// localhost /等待此操作。
    8. 最后,我们得到了什么?

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

      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
      

      在我的情况下,我不需要标签命令,因为我的回购没有标签。

      祝你好运!

答案 28 :(得分:0)

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

答案 29 :(得分:0)

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

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

答案 30 :(得分: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推送更改。

答案 31 :(得分:0)

首先,记下@cmcginty的答案。对我来说,这是一个很好的起点,我在这里发布的很多内容都是从中借鉴而来的。但是,我要搬迁的回购协议已有多年历史,导致在答复该信件后出现了一些问题(数百个分支和标签需要手动移动一个;以后再阅读)。

因此,在经过数小时的搜索和反复试验之后,我能够整理一个脚本,使我可以轻松地将多个项目从SVN迁移到GIT,并且我决定在这里分享我的发现,以防其他人进入我的研究范围鞋子。

让我们开始吧


首先,创建一个“作者”文件,它将基本的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存储库遵循标准的/ trunk / branches / tags布局
  • -no-metadata告诉git不要在每个git提交上标记与svn提交有关的元数据。如果这不是单向转换,请删除此标签
  • -r854:HEAD仅从854版本开始获取历史记录。这是我遇到的第一个障碍。我正在转换的存储库在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。

现在是查看新存储库的好时机,并确保您拥有要保留的任何内容的 local 分支或标签,因为稍后会删除远程分支。 / p>

好吧,现在让我们将签出的所有内容克隆到一个干净的仓库中(这里命名为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,则可能需要为初始推送禁用或调整该设置。 / p>

答案 32 :(得分:0)

多合一 - 用于 SVNGIT 迁移的 shell 脚本。使用占位符 GIT

提及 SVN<> 详细信息
#!/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 存储库中看到所有 branchestags

答案 33 :(得分:-1)

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

  

sudo apt-get install git-core git-svn ruby​​
  sudo gem install svn2git
  svn log --quiet | grep -E&#34; r [0-9] + \ | 。+ \ |&#34; | cut -d&#39; |&#39; -f2 | sed&#39; s / // g&#39; |排序| uniq&gt; 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