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

时间:2020-03-05 18:57:42  来源:igfitidea点击:

我阅读了Git手册,常见问题解答,Git SVN崩溃课程等,它们都对此进行了解释,但是在任何地方都找不到像以下这样的简单说明:

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

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 svn clone http://svn/repo/here/trunk

Git和SVN的操作非常不同。我们需要学习Git,并且如果我们想从SVN上游跟踪更改,则需要学习git-svn。 git-svn手册页有一个很好的示例部分:

$ git svn --help

回答

将Subversion存储库干净地迁移到Git存储库。首先,我们必须创建一个文件,将Subversion提交作者名称映射到Git提交者,例如〜/ authors.txt

jmaddox = Jon Maddox <[email protected]>
bigpappa = Brian Biggs <[email protected]>

然后,我们可以将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-core + svn从MacPorts获得git-svn

如果Subversion存储库与所需的git存储库位于同一台计算机上,
那么我们可以在初始化步骤中使用此语法,否则全部相同:

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

回答

请参见git-svn官方手册。特别是,在"基本示例"下查看:

Tracking and contributing to an entire Subversion-managed project (complete
      with a trunk, tags and branches):
# Clone a repo (like git clone):
    git svn clone http://svn.foo.org/project -T trunk -b branches -t tags

回答

我建议在尝试不断使用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 [email protected]:user/project-name.git

然后,有选择地同步主分支,以便在两者都包含新内容时,拉操作将自动将远程主服务器与本地主服务器合并:

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

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

第一个说明性文章:" Git远程分支机构"

最新版本的后续版本:"与git_remote_branch进行git协作的时间"

回答

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

回答

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

典型过程:

  • 设置git repo
  • 在不同的文件上做一些工作
  • 决定使用git检查一些工作
  • 决定svn-dcommit
  • 获取可怕的"无法提交带有脏索引的错误"错误。

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

git stash; git svn dcommit ; git stash apply

回答

在Subversion中有效地使用Git是git-svn的简要介绍。对于现有的SVN存储库,git-svn使其非常简单。如果我们要启动一个新的存储库,则首先创建一个空的SVN存储库,然后使用git-svn进行导入比在相反的方向上容易得多。创建一个新的Git存储库然后导入SVN可以完成,但是这有点麻烦,特别是如果我们不熟悉Git并且希望保留提交历史记录。

回答

创建一个用于将SVN用户映射到Git的用户文件(即" users.txt"):

user1 = First Last Name <[email protected]>
user2 = First Last Name <[email protected]>
...

我们可以使用此单行代码从现有的SVN存储库中构建模板:

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", ); sub(" $", "", ); print " = "" <"">"}' | 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 /,branchs /,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/ <分支名称/主干> @ <版本号> <存储库UUID>`)

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

cd dest_dir-tmp
git svn fetch

如果我们有大型项目,则可能必须重复执行最后一个命令几次,直到获取所有Subversion提交为止:

git svn fetch

完成后,Git将把SVNtrunk签出到新分支中。任何其他分支都设置为远程。我们可以使用以下方法查看其他SVN分支:

git branch -r

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

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

我们先前从远程分支创建的本地分支将仅作为远程分支复制到新的克隆存储库中。 (跳过中继/主机。)对于要保留的每个分支:

git checkout -b local_branch origin/remote_branch

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

git remote rm origin