Python社区  »  Git

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

community wiki 9 revs, 5 users • 6 月前 • 131 次点击  

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

我不希望它如此简单,也不希望它只是一个命令。但我希望它不会试图解释任何事情——只是在给出这个例子的情况下说应该采取什么步骤。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/30772
 
131 次点击  
分享到微博
文章 [ 30 ]  |  最新文章 6 月前
community wiki PShetty
Reply   •   1 楼
community wiki PShetty    3 年前

将SVN子模块/文件夹“mymodule”转换为具有历史记录且不带标记或分支的Git。

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

community wiki 2 revs Ruslan M
Reply   •   2 楼
community wiki 2 revs Ruslan M    2 年前

实现这一目标有不同的方法。我已经尝试了其中的一些方法,发现真正有效的方法是在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_文件夹中创建空存储库(使用控制台工具或Tortoissesvn) cd REPO_NAME_PARENT_FOLDER ,将dumpfile.dump放入repo_name_parent_文件夹

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

  3. 这个命令是无声的,所以打开第二个命令窗口: svnserve -d -R --root REPO_NAME_FOLDER 为什么不直接使用文件:///……?因为下一个命令将失败 Unable to open ... to URL: 谢谢你的回答 https://stackoverflow.com/a/6300968/4953065

  4. 创建新文件夹源Git文件夹

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

最后,我们得到了什么?

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

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

在我的例子中,我不需要tags命令,因为我的repo没有tags。

祝你好运!

community wiki Zitrax
Reply   •   3 楼
community wiki Zitrax    3 年前

这里的几个答案是指 https://github.com/nirvdrum/svn2git 但对于大型存储库来说,这可能很慢。我试过用 https://github.com/svn-all-fast-export/svn2git 相反,它是一个具有完全相同名称的工具,但用于将kde从svn迁移到git。

设置它的工作稍微多一点,但当完成转换后,我自己花了几分钟时间完成了另一个脚本花费数小时的转换。

community wiki 2 revs, 2 users
Reply   •   4 楼
community wiki 2 revs, 2 users    3 年前

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

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

我现在已经在一些存储库中使用了它,而且它非常准确,速度也快得多!一个提交了大约4000次的存储库需要10分钟,之后我的朋友花了4天时间!

community wiki 3 revs, 2 users
Reply   •   5 楼
community wiki 3 revs, 2 users    3 年前

下载Ruby Installer for Windows并安装最新版本。将Ruby可执行文件添加到您的路径中。

  • 安装Svn2GIT
  • 「开始」菜单->所有程序->ruby->使用ruby启动命令提示符
  • 然后键入gem install svn2git并输入

    迁移Subversion存储库

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

    Svn2GIT http://[domain 名称]/svn/[存储库根目录]

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

  • 这个主要步骤有助于创建下面提到的Git存储库结构。

    svn(/project_components)主干-->git master SVN(/project_components)分支-->Git分支 svn(/project_components)标记-->git标记

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

community wiki 2 revs, 2 users
Reply   •   6 楼
community wiki 2 revs, 2 users    3 年前

Effectively using Git with Subversion 是对Git SVN的温和介绍。对于现有的SVN存储库,Git SVN使这变得非常容易。如果您正在启动一个新的存储库,那么首先创建一个空的SVN存储库,然后使用Git SVN导入要比向相反的方向导入要容易得多。可以创建一个新的Git存储库,然后导入到SVN中,但这有点痛苦,特别是如果您刚接触Git并希望保留提交历史记录的话。

community wiki cljk
Reply   •   7 楼
community wiki cljk    1 年前

我在一台Windows机器上做了一个小批量,只需调用

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%

您仍然需要用户映射为

User1 = User One <u.1@xxx.com>
community wiki Jason Huntley
Reply   •   8 楼
community wiki Jason Huntley    7 年前

我只是想增加我对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 .
community wiki 2 revs NateS
Reply   •   9 楼
community wiki 2 revs NateS    5 年前

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

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

在大约30行脚本中:使用git svn克隆,从svn::ignore属性创建一个.git ignore文件,将其推入一个空的git存储库,将svn主干重命名为master,将svn标记转换为git标记,并将其推送到github,同时保留标记。

我费了很大的劲才把十几个SVN存储库从谷歌代码转移到了Github。我用窗户没用。Ruby在我的旧Debian盒子上有各种各样的损坏,让它在Windows上工作是个笑话。其他解决方案无法使用cygwin路径。即使我得到了一些有用的东西,我也不知道如何让标签出现在Github上(秘密是——跟踪标签)。

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

Gregg Lind
Reply   •   10 楼
Gregg Lind    10 年前

另一方面,当使用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
community wiki 2 revs, 2 users
Reply   •   11 楼
community wiki 2 revs, 2 users    4 年前

为了 吉特实验室 我在这里介绍了如何从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 创建于 新鲜的 命名空间。
  • 文件 users.txt 包含表单的相关用户详细信息,每行一个用户 username = First Last <address@domain.com.au> 在哪里 username 是SVN日志中给定的用户名。(有关详细信息,请参阅参考资料部分的第一个链接,尤其是用户凯西的回答)。

版本

  • Subversion版本1.6.17(R1128011)
  • Git版本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

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

笔记

  • 如果有未知用户,则 git svn clone 命令将停止,在这种情况下,更新 用户交换机 , cd favourite-project git svn fetch 将从停止的位置继续。
  • 标准 trunk - tags - branches SVN存储库的布局是必需的。
  • 提供给 GIT-SVN克隆 命令在紧接着上方的级别停止 trunk/ , tags/ branches/ .
  • 这个 GIT-SVN克隆 命令产生大量输出,包括顶部的一些警告;我忽略了这些警告。
community wiki Craig Myles
Reply   •   12 楼
community wiki Craig Myles    5 年前

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

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

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

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

准备好后,将代码推到新的远程回购,并自由编码。

community wiki ripper234
Reply   •   13 楼
community wiki ripper234    8 年前

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

community wiki 3 revs Pablo Be
Reply   •   14 楼
community wiki 3 revs Pablo Be    3 年前

我贴了一个循序渐进的指南( here )将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

如果你想了解更多细节,请阅读我的 post 或者问我。

community wiki CAD bloke
Reply   •   15 楼
community wiki CAD bloke    6 年前

乌龟是这样做的。查看此日志: http://jimmykeen.net/articles/03-nov-2012/how-migrate-from-svn-to-git-windows-using-tortoise-clients

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

community wiki Pankaj
Reply   •   16 楼
community wiki Pankaj    3 年前

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

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

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

  • 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存储库。

问题是它不会将分支和标记转换为push。你必须手动操作。例如下面的分支:

$ 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、分支和标记推送到远程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克隆 命令。

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

community wiki Valarpirai
Reply   •   17 楼
community wiki Valarpirai    5 年前

你必须安装

git
git-svn

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

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

Subversion只列出每个提交的用户名。Gits提交有更丰富的数据,但最简单的是,提交作者需要列出姓名和电子邮件。默认情况下,git svn工具只会在author和email字段中列出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文件夹中。

三。转换svn:忽略属性到.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主干分支名称匹配。

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。将主干分支重命名为master

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

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

6。清理树枝和标签

GitSvn将所有Subversion标签制作成格式为tags/name的Git中非常短的分支。您将希望使用以下方法将所有这些分支转换为实际的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将为以git for-each-ref开头的超长命令提供一个>辅助提示。

community wiki 2 revs thoutbec
Reply   •   18 楼
community wiki 2 revs thoutbec    5 年前

只使用git、svn和bash的扩展回答。它包括SVN存储库的步骤,这些步骤不使用传统布局和主干/分支/标签目录布局(SVN完全不执行这种布局)。

首先,使用此bash脚本扫描SVN repo以查找贡献的不同人员,并生成映射文件的模板:

#!/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

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

在同一个网络或同一个服务器上运行此命令也可以真正加快速度。另外,如果由于某种原因,这个过程被中断,那么 可以 重新使用它

git svn rebase --continue

在很多情况下,你都在这里完成了。但是,如果您的SVN回购有一个非常传统的布局,您只需在SVN中有一个目录,您希望将其放入Git分支,那么您可以执行一些额外的步骤。

最简单的方法是在服务器上创建一个新的SVN repo,它遵循约定并使用 svn copy 把目录放在主干或分支中。如果您的目录一直在repo的根目录中,这可能是唯一的方法,当我上次尝试此方法时 GIT-SVN 只是拒绝结账。

你也可以用git来实现。为了 git svn clone 只需使用要放入Git分支的目录。

运行后

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

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

webmat
Reply   •   19 楼
webmat    10 年前

Github现在有一个功能 import from an SVN repository . 不过,我从未尝试过。

community wiki Andrew B
Reply   •   20 楼
community wiki Andrew B    5 年前

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

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

这个工具- https://bitbucket.org/atlassian/svn-migration-scripts -对于生成authors.txt和其他内容也非常有用。