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

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

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

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


当前回答

直接使用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”这样的远程跟踪分支,这很好,因为如果您只将本地分支称为“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"应该告诉你它将提交到trunk。

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

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

直接使用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”这样的远程跟踪分支,这很好,因为如果您只将本地分支称为“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"应该告诉你它将提交到trunk。

git svn dcommit

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

我也需要这个,在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。

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

Git WordPress插件和一点理智的分散

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