将现有Git存储库推送到SVN

我一直在用Git做我所有的工作,并将其推送到GitHub。我对软件和网站都很满意,我不希望在这一点上改变我的工作实践。

我的博士导师要求所有学生将作业保存在学校托管的SVN存储库中。我发现了大量关于将现有的SVN存储库下拉到Git中的文档和教程,但没有关于将Git存储库推到新的SVN存储库中的文档和教程。我希望通过结合Git -svn、一个新的分支和rebase以及所有这些美妙的术语来实现这一点,但我是Git新手,对其中任何一个都没有信心。

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

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

116223 次浏览

新建SVN存储库。导出您的Git项目(充实. Git文件)。将其添加到SVN存储库中(使用Git中现有的内容初始化存储库)。 然后在新的Git项目中使用导入SVN存储库的说明

但是这会丢失之前的Git历史记录。

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

我还没有尝试git到SVN的转换,但SVN -> SVN的示例请参见这个答案

在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,你应该完成了。不过,这会严重打乱你的提交日期。

我也需要这个,在Bombe的回答的帮助下,再加上一些摆弄,我让它工作了。下面是食谱:

导入Git -> Subversion

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时,你可能会发生冲突。通过添加状态为“unmerged”的文件并恢复rebase来解决这些问题。最终,你会完成;然后使用dcommit同步回SVN存储库。这是所有。

保持存储库同步

您现在可以使用以下命令从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

如果你不小心用错误的URL运行git svn init,并且你不够聪明,没有备份你的工作(不要问…),你不能再次运行相同的命令。但是,您可以通过发出以下命令来撤销更改:

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

并删除section [svn-remote "svn"] section。

然后你可以重新运行git svn init

直接使用git rebase将丢失第一次提交。Git以不同的方式对待它,并且不能对它进行重基。

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

我将在这里转录解决方案,但学分是Björn。

初始化git-svn:

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

前缀为您提供远程跟踪分支,如"svn/trunk"这很好,因为如果你只称你的本地分支机构为“主干”,你就不会得到模棱两可的名称。然后。-s是标准trunk/tags/branches布局的快捷方式。

从SVN中获取初始的东西:

git svn fetch

现在查看你的根提交的散列(应该显示一个单独的提交):

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

然后获取空trunk的哈希值commit:

git rev-parse svn/trunk

创建嫁接:

git replace --graft <root-commit-hash> <svn-trunk-commit-hash>

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

使移植物永久化:

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

掉落移植物:

git replace -d <root-commit-hash>

gitk仍然应该在master的祖先中显示svn/trunk

在树干顶部线性化你的历史:

git svn rebase

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

git svn dcommit

下面是我们如何做到的:

在你的机器上克隆你的Git存储库。

打开.git/config并添加以下内容(来自维护Git存储库的只读SVN镜像):

[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

注意:我总是在事后丢弃那个文件夹。

我会建议使用SubGit用4个命令组成一个非常短的指令。详见帖子

如果你不需要使用任何特定的SVN,你正在使用GitHub,你可以使用他们的SVN连接器。

更多信息在这里:在GitHub上与Subversion合作

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

< a href = " http://evansolomon。my /notes/ Git - WordPress -plugins-and- bit-of-sanity-scatter/" rel="nofollow noreferrer">Git WordPress plugins and a bit of sanity scatter .

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

我需要将现有的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属性。

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

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

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

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

这样我就不需要做任何重基,因为重基就像冻结。

我只是想分享一些我的经验和公认的答案。我做了所有的步骤,在我运行最后一步之前,一切都很好:

git svn dcommit

$ git SVN dcommit

使用未初始化的值$u替换/usr/lib/perl5/vendor_perl/5.22/Git/SVN。下午101线。

在/usr/lib/perl5/vendor_perl/5.22/Git/SVN中使用未初始化的值$u(.)或字符串。下午101线。 refs/remotes/origin/HEAD: 'https://192.168.2.101/svn/PROJECT_NAME' not found in "

. db_blank . db_blank . db_blank . db_blank . db_blank . db_blank . db_blank

我找到了线程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";
}

这解决了我的问题。

在我的例子中,我必须从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

> SVN,具有完整的提交历史

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

Howto:

  1. 有一个SVN存储库,我们想导入我们的东西,用git-svn克隆它:

    git svn clone https://path.to/svn/repository repo.git-svn`
    
  2. Go there:

    cd repo.git-svn
    
  3. Add the remote of the Git repository (in this example I'm using C:/Projects/repo.git). You want to push to SVN and give it the name old-git:

    git remote add old-git file:///C/Projects/repo.git/
    
  4. Fetch the information from the master branch from the old-git repository to the current repository:

    git fetch old-git master
    
  5. Checkout the master branch of the old-git remote into a new branch called old in the current repository:

    git checkout -b old old-git/master`
    
  6. Rebase to put the HEAD on top of old-git/master. This will maintain all your commits. What this does basically is to take all of your work done in Git and put it on top of the work you are accessing from SVN.

    git rebase master
    
  7. Now go back to your master branch:

    git checkout master
    

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

  8. 将您的作品推送到SVN:

    git svn dcommit
    

That's all. It is very clean, no hacking, and everything works perfectly out of the box. Enjoy.

我最近不得不将几个Git存储库迁移到SVN上,在尝试了所有我能找到的解决方案后,最后对我有效的是水银(是的,使用第三 VCS)。使用本指南,我提出了以下过程(在Linux上,但基本思想应该也适用于Windows)。

  1. 必要的包:

    $ sudo apt-get install git subversion mercurial python-subversion
    
  2. Mercurial needs to be configured by adding the following to ~/.hgrc:

    [extensions]
    hgext.convert=
    
  3. Create some temporary working directories (I had several repositories to migrate so I created directories for the SVN and Git versions, to keep them separate):

    $ mkdir svn
    $ mkdir git
    
  4. Make an empty local SVN repository:

    $ svnadmin create svn/project
    
  5. Clone the existing Git repository:

    $ git clone server/path/project.git git/project
    
  6. Let Mercurial do its thing:

    $ hg convert --dest-type svn git/project svn/project
    
  7. Now the SVN repository should contain the full commit history, but not with original timestamps. If this is not an issue, skip over the next part to step 11.

  8. With a little work, the date and time of each commit can be changed. Since my repositories are fairly small, it was feasible for me to do it manually. First, create a pre-revprop-change hook in the SVN repository with the following contents, to allow the necessary property to be modified:

    #!/bin/bash
    exit 0;
    

    这个脚本必须是可执行的:

    $ chmod +x svn/project/hooks/pre-revprop-change
    
  9. Mercurial created a working copy of the SVN repository, named project-wc, so switch to it and edit the commit times:

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

    输入正确的日期和时间(注意时区!)并保存。您应该得到一条消息说“为属性svn:date on revision 1设置新值”

  10. 可选地检查提交历史以确保一切正常:

    $ svn log -r 1:HEAD
    

    然后回到上一层:

    $ cd ..
    
  11. Dump the repository:

    $ svnadmin dump svn/project > project.dump
    
  12. And load the dump on your Subversion server. Done!

This process would probably also work directly between remote repositories, but I found it easier to work with local ones. Fixing the commit times was a lot of work, but overall the process was much more straightforward than any other method I found.

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

  1. 安装git-svnsubversion工具包:

    sudo apt-get install git-svn subversion
    
  2. Switch inside the PROJECT_FOLDER

    cd PROJECT_FOLDER
    
  3. Create the project path on the Subversion server (unfortunately the current git-svn plugin has a defect in comparison with TortoiseSVN). It is unable to store source code directly into the PROJECT_FOLDER. Instead, by default, it will upload all the code into PROJECT_FOLDER/trunk.

    svn mkdir --parents protocol:///path/to/repo/PROJECT_FOLDER/trunk -m "creating git repo placeholder"

This is the place where trunk at the end of the path is mandatory

  1. Initialize the git-svn plugin context inside the .git folder

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

    这是路径末尾的trunk不必要的

    的地方
  2. 获取空的Subversion存储库信息

    git svn fetch
    

    此步骤将帮助Subversion服务器与git-svn插件同步。这是git-svn插件建立remotes/origin路径并将其与服务器端trunk子文件夹关联的时刻

  3. git-svn插件参与到这个过程之前发生了对旧Git提交的Rebase(这一步是可选)

    git rebase origin/trunk
    
  4. Add new/modified files to commit (this step is regular for Git activities and is optional)

    git add .
    
  5. Commit freshly added files into the local Git repository (this step is optional and is only applicable if step 7 has been used):

    git commit -m "Importing Git repository"
    
  6. Pushing all the project changes history into the Subversion server:

    git svn dcommit
    

有三种方法:

  1. Rebase:与其他答案相同

  2. 提交id:查找svn的第一个提交id和git的第一个提交id,将它们回显到.git/info/grafts:echo "git_id svn_id}" > .git/info/grafts然后git svn dcommit

  3. 检查每一个git提交,复制文件到svn_repo, SVN提交

< p > bash演示: github演示 < / p >

v1。X:使用rebase和commit id

v2。X:使用复制文件,然后SVN提交

这就是我要做的。假设我的本地分支名为main。填补空白,因为我不记得确切的git svn命令,因为我有一段时间没有使用它了。

  • 创建在svn将用于项目的分支。
  • 使用git svn来克隆你想要的svn repo(至少,你想要使用的分支,这样你就不必获取其他数百万个我们不关心的修订)。
  • 在新的git repo中检出SVN分支。
  • 向这个存储库添加一个指向项目中使用的原始 git repo的遥控器。让我们说遥控器被称为the-real-stuff
  • git fetch the-real-stuff #这样我们就能看到真正的回购中有什么
  • 考虑到这是我们第一次将我们的代码拉到svn one中,我们必须欺骗git,以便它可以“合并”。代码:git merge --allow-unrelated-histories the-real-stuff/main -m "Whatever comment I want in the svn revision"。这将“合并”;两个分支都在本地。
  • git svn dcommit,这样你就可以推送项目的内容,因为它是现在。

继续处理原始 git回购。然后,当你想要推入svn时,去到git的svn clone,然后做:

git fetch the-real-stuff # get visibility to the changes in the original git repo
git merge the-real-stuff/main -m "Whatever comment I want to show on this svn revision"
git svn dcommit

这样就做完了。

我喜欢使用2个回购的想法,这样我们就不用用svn的东西来填充原始的回购,尽管有可能将整个东西保留在一个git回购中。