代码之家  ›  专栏  ›  技术社区  ›  cflewis

将现有Git存储库推送到SVN

  •  375
  • cflewis  · 技术社区  · 17 年前

    我在Git做了所有的工作,一直在推动Github。我对这个软件和这个网站都很满意,现在我不想改变我的工作实践。

    我的博士顾问要求所有学生将他们的工作保存在大学主办的SVN资源库中。我已经找到了大量的文档和教程,它们将把一个现有的SVN存储库拉入Git,但并没有把一个Git存储库推到一个新的SVN存储库中。我希望有一些方法可以做到这一点,结合Git svn和一个新的分支,重新平衡和所有这些美妙的条款,但我是一个Git新手,并没有任何信心。

    然后,当我选择时,我只想运行几个命令来将提交推送到SVN存储库。我希望继续使用Git,让SVN存储库镜像Git中的内容。

    如果这有什么不同的话,我将是唯一一个致力于SVN的人。

    16 回复  |  直到 8 年前
        1
  •  394
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    我也需要这个,在庞贝的回答的帮助下,再加上四处闲逛,我就成功了。食谱如下:

    导入Git->子版本

    1. cd /path/to/git/localrepo
    2. svn mkdir --parents protocol:///path/to/repo/PROJECT/trunk -m "Importing git repo"
    3. git svn init protocol:///path/to/repo/PROJECT -s
    4. git svn fetch
    5. git rebase origin/trunk
    5.1.  git status
    5.2.  git add (conflicted-files)
    5.3.  git rebase --continue
    5.4.  (repeat 5.1.)
    6. git svn dcommit
    

    在3之后,您会收到这样一条神秘的信息:

    使用更高级别的URL: protocol:///path/to/repo/PROJECT => protocol:///path/to/repo

    忽略这一点。

    当你跑5时,你 可以 获取冲突。通过添加状态为“未合并”的文件并恢复REBASE来解决这些问题。最终,您将完成;然后使用 dcommit . 这就是全部。

    保持存储库同步

    现在可以使用以下命令从SVN同步到Git:

    git svn fetch
    git rebase trunk
    

    要从Git同步到SVN,请使用:

    git svn dcommit
    

    期末笔记

    在应用到活动存储库之前,您可能需要在本地副本上尝试此操作。您可以将Git存储库的副本复制到临时位置;只需使用 cp -r ,因为所有数据都在存储库本身中。然后,可以使用以下方法设置基于文件的测试存储库:

    svnadmin create /home/name/tmp/test-repo
    

    并检查一份工作副本,使用:

    svn co file:///home/name/tmp/test-repo svn-working-copy
    

    这将允许你在做出任何持久的改变之前,玩弄一些事情。

    附录:如果你搞砸了 git svn init

    如果你不小心跑了 Git Svn初始化 使用错误的URL,并且您不够聪明,无法备份您的工作(不要问…),您不能再次运行相同的命令。但是,您可以通过发出以下命令来撤消更改:

    rm -rf .git/svn
    edit .git/config
    

    然后把这部分拆下来 [svn-remote "svn"] 部分。

    你就可以跑了 Git Svn初始化 重新。

        2
  •  29
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    我们的工作原理如下:

    在计算机上的某个地方克隆Git存储库。

    打开.git/config并添加以下内容(从 Maintaining a read-only SVN mirror of a Git repository ):

    [svn-remote "svn"]
        url = https://your.svn.repo
        fetch = :refs/remotes/git-svn
    

    现在,从控制台窗口键入以下内容:

    git svn fetch svn
    git checkout -b svn git-svn
    git merge master
    

    现在,如果它因任何原因在这里中断,请键入以下三行:

    git checkout --theirs .
    git add .
    git commit -m "some message"
    

    最后,您可以向SVN提交:

    git svn dcommit
    

    注意:以后我总是把那个文件夹扔掉。

        3
  •  27
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    使用 git rebase 直接将丢失第一个提交。Git对它有不同的看法,不能重新平衡它。

    有一个程序可以保存完整的历史记录: http://kerneltrap.org/mailarchive/git/2008/10/26/3815034

    我将在这里转录解决方案,但学分是为北京奥运会注册。

    初始化git svn:

    git svn init -s --prefix=svn/ https://svn/svn/SANDBOX/warren/test2
    

    前缀为您提供了远程跟踪分支,如“svn/trunk”,这很好,因为如果您只将本地分支称为“trunk”,则不会得到不明确的名称。和 -s 是标准中继/标记/分支布局的快捷方式。

    从SVN获取初始资料:

    git svn fetch
    

    现在查找根提交的散列(应该显示单个提交):

    git rev-list --parents master | grep '^.\{40\}$'
    

    然后获取空主干提交的哈希值:

    git rev-parse svn/trunk
    

    创建移植:

    echo <root-commit-hash> <svn-trunk-commit-hash> >> .git/info/grafts
    

    现在,“Gitk”应该显示 svn/trunk 作为主分支所基于的第一个提交。

    永久移植:

    git filter-branch -- ^svn/trunk --all
    

    放弃嫁接:

    rm .git/info/grafts
    

    Gitk应该仍然显示 主干网/中继线 在主人的祖先。

    在主干上线性化您的历史:

    git svn rebase
    

    现在“git svn-dcommit-n”应该告诉您它将提交到主干。

    git svn dcommit
    
        4
  •  8
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    在Subversion存储库中为项目创建一个新目录。

    # svn mkdir --parents svn://ip/path/project/trunk
    

    更改为Git管理的项目并初始化Git SVN。

    # git svn init svn://ip/path/project -s
    # git svn fetch
    

    这将创建一个提交,因为您的SVN项目目录仍然是空的。现在把所有的事情都放在承诺上, git svn dcommit 你应该完成。不过,这会严重影响您的提交日期。

        5
  •  7
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    Git->SVN具有完整的提交历史记录

    我有一个Git项目,必须将它转移到SVN。这就是我如何做到的,保持了整个提交历史。唯一会丢失的是原始提交时间,因为libsvn将在执行此操作时设置本地时间 git svn dcommit .

    Howto:

    1. 有一个SVN存储库,我们希望在其中导入我们的资料并使用Git SVN进行克隆:

      git svn clone https://path.to/svn/repository repo.git-svn`
      
    2. 去那里:

      cd repo.git-svn
      
    3. 添加git存储库的远程(在本例中,我使用 C:/项目/repo.git )你想推到SVN,给它起个老名字:

      git remote add old-git file:///C/Projects/repo.git/
      
    4. 从旧git存储库的主分支获取信息到当前存储库:

      git fetch old-git master
      
    5. 将旧git-remote的主分支签入当前存储库中名为old的新分支:

      git checkout -b old old-git/master`
      
    6. 重新定位以将头部放在旧git/master的顶部。这将维持你所有的承诺。它的基本功能是将您在Git中完成的所有工作放在您从SVN访问的工作之上。

      git rebase master
      
    7. 现在回到主分支:

      git checkout master
      

      你可以看到你有一个干净的提交历史。这就是你想要推给SVN的。

    8. 将您的工作推至SVN:

      git svn dcommit
      

    这就是全部。它非常干净,没有黑客攻击,而且所有的东西都是开箱即用的。享受。

        6
  •  4
  •   Community Mohan Dere    9 年前

    我建议在4个命令中使用非常短的指令 SubGit . 看到这个 post 详情。

        7
  •  3
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    我需要将现有的Git存储库提交到一个空的SVN存储库。

    我就是这样做到的:

    $ git checkout master
    $ git branch svn
    $ git svn init -s --prefix=svn/ --username <user> https://path.to.repo.com/svn/project/
    $ git checkout svn
    $ git svn fetch
    $ git reset --hard remotes/svn/trunk
    $ git merge master
    $ git svn dcommit
    

    它毫无问题地工作。我希望这能帮助别人。

    因为我必须用另一个用户名授权给SVN存储库(我的 origin 使用私钥/公钥身份验证),我必须使用 --username 财产。

        8
  •  2
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    如果您想继续使用Git作为您的主存储库,并且只需要不时“导出”对SVN的修订,那么您可以使用 Tailor 使SVN存储库保持同步。它可以在不同的源代码管理系统之间复制修订,并使用在Git中所做的更改来更新SVN。

    我没有尝试过Git到SVN转换,但是对于SVN->SVN示例,请参见 this answer .

        9
  •  1
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    如果您不必使用任何特定的SVN,并且您使用的是Github,那么您可以使用它们的SVN连接器。

    更多信息如下: Collaborating on GitHub with Subversion

        10
  •  1
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    我想分享一个在WordPress社区中使用的很棒的工具,叫做分散。

    Git WordPress plugins and a bit of sanity scatter

    这使用户能够自动将其Git存储库发送到wordpress.org svn。理论上,此代码可以应用于任何SVN存储库。

        11
  •  0
  •   dangt85    10 年前

    在我的情况下,我必须从SVN发起一个清洁项目。

    $ Project> git svn init protocol://path/to/repo -s
    $ Project> git svn fetch
    

    添加所有项目源…

    $ Project> git add .
    $ Project> git commit -m "Importing project sources"
    $ Project> git svn dcommit
    
        12
  •  0
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    您可以创建一个新的SVN存储库。导出Git项目(充实.git文件)。将它添加到SVN存储库中(使用Git中的内容初始化存储库)。 然后使用说明在新的Git项目中导入SVN存储库。

    但这将丢失您以前的Git历史。

        13
  •  0
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    我只想和大家分享我的一些经验。在跑最后一步之前,我做了所有的步骤,一切都很好:

    git svn dcommit
    

    $git svn数据限制

    在/usr/lib/perl5/vendor_perl/5.22/git/svn.pm行101中使用未初始化的值$u替换(s///)。

    在/usr/lib/perl5/vendor_perl/5.22/git/svn.pm行101的串联(.)或字符串中使用未初始化的值$u。 参考/遥控/原点/头部:' https://192.168.2.101/svn/PROJECT_NAME 在“”中未找到

    我找到了线 https://github.com/nirvdrum/svn2git/issues/50 最后,我在第101行的以下文件中应用的解决方案 /usr/lib/perl5/vendor_perl/5.22/git/svn.pm

    我取代了

    $u =~ s!^\Q$url\E(/|$)!! or die
    

    具有

    if (!$u) {
        $u = $pathname;
    } 
    else {
           $u =~ s!^\Q$url\E(/|$)!! or die
          "$refname: '$url' not found in '$u'\n";
    }
    

    这解决了我的问题。

        14
  •  0
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    另一个有效的序列(每一步都有一些注释):

    1. 安装 git-svn 和 subversion 工具包:

      sudo apt-get install git-svn subversion
      
    2. 在内部切换 PROJECT_FOLDER

      cd PROJECT_FOLDER
      
    3. 在Subversion服务器上创建项目路径(不幸的是,当前 GIT-SVN 插件与Tortoissesvn相比有缺陷)。它无法将源代码直接存储到 文件夹文件夹 . 相反,默认情况下,它会将所有代码上载到 PROJECT_FOLDER/trunk .

      svn mkdir--父协议:///path/to/repo/project_folder/trunk-m“创建git repo占位符”

    这里就是 trunk 在路的尽头是 强制性的

    1. 初始化 GIT-SVN 插件上下文 .git 文件夹

      git svn init -s protocol:///path/to/repo/PROJECT_FOLDER
      

      这里就是 大旅行箱 在路的尽头是 不必要的

    2. 取空 Subversion 存储库信息

      git svn fetch
      

      此步骤有助于将Subversion服务器与 GIT-SVN 插件。此时此刻 GIT-SVN 插件建立 remotes/origin 并将其与 大旅行箱 服务器端的子文件夹。

    3. 重新设置在 GIT-SVN 插件已参与进程(此步骤是 可选择的 )

      git rebase origin/trunk
      
    4. 添加要提交的新/修改的文件(此步骤对于git活动是常规的,并且 可选择的 )

      git add .
      
    5. 将新添加的文件提交到本地Git存储库(此步骤是 可选择的 并且仅适用于已使用步骤7的情况):

      git commit -m "Importing Git repository"
      
    6. 将所有项目更改历史推送到Subversion服务器中:

      git svn dcommit
      
        15
  •  0
  •   Indrek    8 年前

    我最近不得不将几个Git存储库迁移到SVN,在尝试了所有我能找到的解决方案之后,最终对我起作用的是 Mercurial (是的,使用A 第三的 VCS)。使用 this guide ,我提出了以下过程(在Linux上,但基本思想也应该在Windows上工作)。

    1. 必要的包装:

      $ sudo apt-get install git subversion mercurial python-subversion
      
    2. Mercurial需要通过将以下内容添加到 ~/.hgrc :

      [extensions]
      hgext.convert=
      
    3. 创建一些临时工作目录(我有几个要迁移的存储库,所以我为SVN和Git版本创建了目录,以使它们保持独立):

      $ mkdir svn
      $ mkdir git
      
    4. 生成空的本地SVN存储库:

      $ svnadmin create svn/project
      
    5. 克隆现有的Git存储库:

      $ git clone server/path/project.git git/project
      
    6. 让Mercurial做它的事:

      $ hg convert --dest-type svn git/project svn/project
      
    7. 现在,SVN存储库应该包含完整的提交历史记录,但不包含原始时间戳。如果这不是问题,请跳过下一部分到步骤11。

    8. 做点小工作, the date and time of each commit can be changed . 因为我的存储库相当小,所以我可以手动完成它。首先,创建一个 pre-revprop-change 在SVN存储库中挂接以下内容,以允许修改必要的属性:

      #!/bin/bash
      exit 0;
      

      必须使此脚本可执行:

      $ chmod +x svn/project/hooks/pre-revprop-change
      
    9. Mercurial创建了SVN存储库的工作副本,名为 项目 -wc,所以切换到它并编辑提交时间:

      $ cd project-wc
      $ svn propedit svn:date --revprop -r 1
      

      输入正确的日期和时间(注意时区!)并保存。您应该会收到一条消息,说明“为属性svn设置新值:修订版1上的日期”。
      现在冲洗并重复其他版本。

    10. 或者检查提交历史记录以确保一切正常:

      $ svn log -r 1:HEAD
      

      然后回到上一级:

      $ cd ..
      
    11. 转储存储库:

      $ svnadmin dump svn/project > project.dump
      
    12. 并将转储文件加载到Subversion服务器上。完成!

    这个过程也可能直接在远程存储库之间工作,但我发现使用本地存储库更容易。修复提交时间是一项艰巨的工作,但总的来说,这个过程比我发现的任何其他方法都简单得多。

        16
  •  -1
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    如果你不想承诺呢 每一个 在Git中提交到SVN存储库?如果您只想有选择地向管道发送提交,该怎么办?嗯,我有更好的解决办法。

    我保留了一个本地Git存储库,我所做的就是从SVN中获取和合并。这样我就可以确保我包含了与SVN相同的所有更改,但是我将提交历史与SVN完全分开。

    然后我将单独的SVN本地工作副本保存在单独的文件夹中。这就是我从SVN提交的内容,我只是使用SVN命令行实用程序。

    当我准备将本地Git存储库的状态提交给SVN时,我只需将所有混乱的文件复制到本地SVN工作副本中,然后使用SVN而不是Git从那里提交。

    这样我就不必再做任何重新平衡,因为重新平衡就像自由基一样。