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

我不希望它这么简单,也不希望它是一个命令。但我确实希望它不要试图解释任何事情——只是说在这个例子中应该采取什么步骤。


当前回答

我只是想把我的贡献加入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 .

其他回答

我们可以使用git-svnclone命令,如下所示。

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

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

svn日志—复制时停止<svn_URL>

创建SVN项目时,上面的命令将为您提供第一个修订号。

git svn clone-r<svn_REV_NO>:HEAD--无最小化url--stdlayout--无元数据--作者文件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和标记推送到远程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实用程序删除了带有分支和标记的手动工作。

使用命令sudogeminstallsvn2git安装它。之后运行以下命令。

$svn2git<SVN_URL>--authors.txt--修订版<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-svnclone命令包装器。

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

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,妈妈。gitsvn让我成为蓝屏死亡。只是不断。git-svn让我厌烦git的“文件名太长”致命错误。

步骤

1.下载SubGit

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

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

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

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

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

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

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

技巧1:使用--最小修订版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存储

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

配置遥控器

Run:

$ git remote add origin url://your/repo.git

准备将巨大的本地Git存储库首次发送到远程存储库

默认情况下,Git无法发送大块数据。致命:远端意外挂断

让我们跑吧:

git config --global http.postBuffer 1073741824

524288000-500 MB1073741824-1 GB等。

修复本地证书问题。如果您的git服务器使用了损坏的证书。

我已禁用证书。

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

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

使用本地Git运行:

git push origin --mirror

(git push origin“*:*”用于旧git版本)

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

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

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

用于SVN到GIT迁移的一体式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只复制分支(包括主分支),如果有标记或主干,则忽略。现在再次运行脚本。您可以在git存储库中看到所有分支和标记。

有效地将Git与Subversion结合使用是对Git-svn的简单介绍。对于现有的SVN存储库,git-SVN使其变得非常简单。如果您正在启动一个新的存储库,那么首先创建一个空的SVN存储库,然后使用git-SVN导入要比相反的方向容易得多。创建一个新的Git存储库,然后导入到SVN中是可以做到的,但这有点痛苦,特别是如果您是Git新手,希望保留提交历史记录。

我建议在尝试经常使用Git-svn之前,先熟悉Git,即保持svn作为集中存储库并在本地使用Git。

然而,对于具有所有历史记录的简单迁移,以下是几个简单步骤:

初始化本地回购:

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

标记要开始导入修订的时间:

git svn fetch -r42

(或仅对所有版本使用“gitsvn-fetch”)

事实上,从那时起,获取一切:

git svn rebase

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

gitk

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

首先创建空的远程存储库(可能在GitHub上?):

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

然后,可选地同步您的主分支,这样当远程主机和本地主机都包含新内容时,拉操作将自动合并远程主机:

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

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

第一篇解释文章:“Git远程分支”

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