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

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

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

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


当前回答

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

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

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

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

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

其他回答

我也需要这个,在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”这样的远程跟踪分支,这很好,因为如果您只将本地分支称为“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

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

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

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

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

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

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

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

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

最近我不得不将几个Git存储库迁移到SVN上,在尝试了我能找到的所有解决方案之后,最后对我有用的是Mercurial(是的,使用了第三种VCS)。根据这份指南,我提出了以下流程(适用于Linux,但基本思路也适用于Windows)。

The necessary packages: $ sudo apt-get install git subversion mercurial python-subversion Mercurial needs to be configured by adding the following to ~/.hgrc: [extensions] hgext.convert= 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 Make an empty local SVN repository: $ svnadmin create svn/project Clone the existing Git repository: $ git clone server/path/project.git git/project Let Mercurial do its thing: $ hg convert --dest-type svn git/project svn/project 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. 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; This script has to be made executable: $ chmod +x svn/project/hooks/pre-revprop-change 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 Enter the correct date and time (pay attention to timezones!) and save. You should get a message saying "Set new value for property svn:date on revision 1". Now rinse and repeat for every other revision. Optionally check the commit history to make sure everything looks OK: $ svn log -r 1:HEAD Then go back up one level: $ cd .. Dump the repository: $ svnadmin dump svn/project > project.dump And load the dump on your Subversion server. Done!

这个过程可能也可以直接在远程存储库之间工作,但是我发现与本地存储库一起工作更容易。修正提交时间需要做很多工作,但总的来说,这个过程比我发现的任何其他方法都要简单得多。