【问题标题】:Migrate from Subversion to git, clone all branches and push through gitolite?从 Subversion 迁移到 git,克隆所有分支并通过 gitolite 推送?
【发布时间】:2026-01-18 10:30:01
【问题描述】:

我一直致力于将我们在一个 SVN 存储库中的 9 个项目转移到 9 个单独的 git 存储库,由 gitolite 在服务器上管理,然后关闭 SVN。其中七个很简单,因为它们没有分支或标签,所以在我的工作站上我可以做一个简单的:

git svn clone --stdlayout --no-metadata -A svnauthors.txt svn+ssh://user@host/var/subversion/project tempProject

然后通过以下方式从我的工作站推送到 gitolite 服务器:

 git remote add origin ssh://gitolite@host/project
 git push -u origin master

他们都工作得很好。现在最后两个项目更加困难,每个项目大约有 30 个标签/分支。在我看到的其中一个项目上运行上述“git svn clone”后:

$ git branch -a
* master
  remotes/BatchUpload
  remotes/clarify_breadcrumb
  remotes/contact_type
  remotes/contact_upload_improvements
  remotes/file_cabinet
  remotes/mobile
  remotes/summary_tiles
  remotes/summary_updates
  remotes/tags/release-2.1.2
  remotes/tags/release-3.0.1
  remotes/tags/release-3.0.2
  remotes/tags/release-3.0.2c
  remotes/tags/release-3.1.1
  remotes/tags/release-3.1.3
  remotes/tags/release-3.1.4
  remotes/tags/release-3.1.5
  remotes/tags/release-3.1.5.UPDT
  remotes/tags/release-3.2
  remotes/tags/release-3.2.1
  remotes/tags/release-3.2.2.1
  remotes/tags/release-3.2.3
  remotes/tags/release-3.2.4
  remotes/tags/release-3.2.6
  remotes/tags/release-3.2.7
  remotes/tags/release-3.2.7.1
  remotes/trunk
  remotes/user_man_batch_upload
  remotes/user_management

现在如何将所有这些标签/分支下载到我的本地工作站,以便我可以通过 gitolite 推送它们并永久关闭 SVN 服务器?我需要在this guide 中做什么,为每个分支和标签执行“git checkout -b”吗?我应该为此使用 svn2git 还是其他工具?

【问题讨论】:

    标签: git svn migration


    【解决方案1】:

    它们已经在您的本地工作站上。您看到的只是对提交的引用,您可以随时查看跟踪它们的本地分支。

    git branch -a
    

    显示本地存储库中的信息,而不是从远程存储库中获取任何数据。您在进行克隆时获得了所有这些信息。

    所以现在我们在本地拥有一切,您只需要将数据推送到远程。您可以使用以下命令将所有标签推送到远程服务器:

    git push --tags
    

    对于每个分支,您可以将其推送到 repo:

    git push origin remotes/BatchUpload:BatchUpload
    

    【讨论】:

    • 运行 'git push --tags' 响应“一切都是最新的”并且没有其他输出,与运行 'git push origin remotes/*:refs/heads/*' 相同,这应该是你上面列出的一样吗?但是,运行这些命令后,服务器上似乎不存在任何分支或标签。
    • 嗯好的,那么您可能必须手动或使用脚本将它们转换为标签。如果您使用“git checkout remotes/tags/release-2.1.2”签出例如 remotes/tags/release-2.1.2,您会得到一个分离的 HEAD?
    • 似乎从 svn 到 git 的转换将标签创建为远程引用(但命名很奇怪),所以你可能必须做例如“git checkout 遥控器/标签/xyz;git 标签 xyz;”对于 .git/remotes/tags 文件夹中的所有文件 xyz。完成后, git push --tags 应该将它们推送到远程。对于 .git/remotes 文件夹中的所有文件 xyz,您必须对分支引用、git checkout -b xyz remotes/xyz(或简单的 git branch xyz remotes/xyz)和 git push origin xyz 执行相同的操作。完成后,您可以删除文件。
    【解决方案2】:

    freenode irc 上#git 的一位乐于助人的人给我写了一个小命令,将我的标签和分支从 SVN 复制到 Git:

    推送分支:

    printf "git push origin "; git show-ref | grep refs/remotes | grep -v '@' | grep -v remotes/tags | perl -ne 'print "refs/remotes/$1:refs/heads/$1 " if m!refs/remotes/(.*)!'; echo
    

    运行打印出来的命令

    推送标签:

    printf "git push origin "; git show-ref | grep refs/remotes/tags | grep -v '@' | perl -ne 'print "refs/remotes/tags/$1:refs/tags/$1 " if m!refs/remotes/tags/(.*)!'; echo
    

    运行打印出来的命令

    【讨论】:

    • 哦,它的输出是一个命令......谢谢我有很多让我困惑的分支......
    • 它对我有用。但是为什么没有 ootb git 命令呢?或者,为什么 git push --all 对 git svn 分支失败?
    • 有。见zionyx answer
    • 在结尾和开头添加一个`(反引号),命令将只运行而不是打印。
    【解决方案3】:

    使用 svn2git。这会将标签转换为 git 注释标签,然后使用正确推送这些标签 git push --tags

    【讨论】:

    • 能否请您详细说明如何使用 svn2git 解决 OPs 特定问题?
    【解决方案4】:

    您可以列出从 svn 迁移到 git 时创建的所有远程引用:git show-ref(可从 git 1.8.2.2 获得)。然后决定将它们推送到原点。

    将所有引用作为分支推送到原点:

    git push origin refs/remotes/*:refs/heads/*
    

    将标签推送到原点:

    git push origin refs/tags/*:refs/tags/*
    -or-
    git push origin --tags
    

    你可能需要清理这些分支,或者convert some branches to tags之前/推送之后。

    【讨论】: