Pushing an existing Git repository to SVN
我在Git做了所有的工作,一直在推动Github。我对这个软件和这个网站都很满意,我不想在这一点上改变我的工作实践。
我的博士顾问要求所有学生将他们的工作保存在大学主办的SVN资源库中。我已经找到了大量的文档和教程,它们将把一个现有的SVN存储库拉入Git中,而不是将一个Git存储库推到一个新的SVN存储库中。我希望有一些方法可以做到这一点,结合Git SVN和一个新的分支,重新平衡和所有这些美妙的条款,但我是一个Git新手,并没有任何信心。
然后,当我选择时,我只想运行几个命令来将提交推送到SVN存储库。我希望继续使用Git,让SVN存储库镜像Git中的内容。
如果这有什么不同的话,我将是唯一一个致力于SVN的人。
我也需要这个,在庞贝的回答的帮助下,再加上四处闲逛,我就成功了。食谱如下:
导入Git->Subversion1 2 3 4 5 6 7 8 9 10 | 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之后,您会收到这样一条神秘的信息:
Using higher level of URL:
protocol:///path/to/repo/PROJECT => protocol:///path/to/repo
号
忽略这一点。
当你跑5时,你可能会遇到冲突。通过添加状态为"未合并"的文件并恢复REBASE来解决这些问题。最后,您将完成;然后使用
现在可以使用以下命令从SVN同步到Git:
1 2 | git svn fetch git rebase trunk |
。
要从Git同步到SVN,请使用:
1 | git svn dcommit |
最后说明
在应用到活动存储库之前,您可能希望在本地副本上尝试此操作。您可以将Git存储库复制到临时位置;只需使用
1 | svnadmin create /home/name/tmp/test-repo |
。
并检查一份工作副本,使用:
1 | svn co file:///home/name/tmp/test-repo svn-working-copy |
。
这将允许你在做出任何持久的改变之前,玩弄事物。
附录:如果你搞砸了如果您不小心用错误的URL运行了
1 2 | rm -rf .git/svn edit .git/config |
拆下
然后您可以重新运行
我们的工作原理如下:
在计算机上的某个地方克隆Git存储库。
打开.git/config并添加以下内容(从维护Git存储库的只读SVN镜像开始):
1 2 3 | [svn-remote"svn"] url = https://your.svn.repo fetch = :refs/remotes/git-svn |
现在,从控制台窗口键入以下内容:
1 2 3 | git svn fetch svn git checkout -b svn git-svn git merge master |
号
现在,如果它因任何原因在此处中断,请键入以下三行:
1 2 3 | git checkout --theirs . git add . git commit -m"some message" |
最后,您可以向SVN提交:
1 | git svn dcommit |
。
注意:以后我总是把那个文件夹扔掉。
直接使用
有一个过程可以保存完整的历史记录:http://kerneltrap.org/mailarchive/git/2008/10/26/3815034
我将在这里转录解决方案,但学分是为北京?氡
初始化git svn:
1 | git svn init -s --prefix=svn/ https://svn/svn/SANDBOX/warren/test2 |
。
前缀为您提供远程跟踪分支,如"svn/trunk",这很好,因为如果您只将本地分支称为"trunk",则不会得到不明确的名称。
从SVN获取初始资料:
1 | git svn fetch |
现在查找根提交的散列(应该显示单个提交):
1 | git rev-list --parents master | grep '^.\{40\}$' |
。
然后获取空主干提交的哈希值:
1 | git rev-parse svn/trunk |
号
创建移植:
1 | echo <root-commit-hash> <svn-trunk-commit-hash> >> .git/info/grafts |
号
现在,"gitk"应该将
永久移植:
1 | git filter-branch -- ^svn/trunk --all |
号
放弃移植:
1 | rm .git/info/grafts |
号
Gitk仍应在主人的祖先中显示
在主干上线性化您的历史:
1 | git svn rebase |
号
现在"git svn-dcommit-n"应该告诉您它将提交到主干。
1 | git svn dcommit |
在Subversion存储库中为项目创建一个新目录。
1 | # svn mkdir --parents svn://ip/path/project/trunk |
更改为Git管理的项目并初始化Git SVN。
1 2 | # git svn init svn://ip/path/project -s # git svn fetch |
号
这将创建一个提交,因为您的SVN项目目录仍然是空的。现在把所有的事情都放在承诺上,
git->svn,具有完整的提交历史记录
我有一个Git项目,必须将它转移到SVN。这就是我如何做到的,保持了整个提交历史。唯一会丢失的是原始提交时间,因为libsvn将在执行
Howto:
有一个SVN存储库,我们希望在其中导入我们的资料并使用Git SVN进行克隆:
1 | git svn clone https://path.to/svn/repository repo.git-svn` |
去那里:
1 | cd repo.git-svn |
号
添加git存储库的远程版本(在本例中,我使用的是c:/projects/repo.git)。你想推到svn并给它起一个名字old git:
1 | git remote add old-git file:///C/Projects/repo.git/ |
从旧git存储库的主分支获取信息到当前存储库:
1 | git fetch old-git master |
。
将旧git-remote的主分支签入当前存储库中名为old的新分支:
1 | git checkout -b old old-git/master` |
重新定位以将头部放在旧git/master的顶部。这将保持你所有的承诺。它的基本功能是将您在Git中完成的所有工作放在您从SVN访问的工作之上。
1 | git rebase master |
。
现在回到主分支:
1 | git checkout master |
。
你可以看到你有一个干净的提交历史。这就是你想要推给SVN的。
将您的工作推至SVN:
1 | git svn dcommit |
这就是全部。它非常干净,没有黑客攻击,而且所有东西都是开箱即用的。享受。
我建议在使用subgit的4个命令中使用一个非常短的指令。详情请参阅本帖。
我需要将现有的Git存储库提交到一个空的SVN存储库。
我就是这样做到的:
1 2 3 4 5 6 7 8 | $ 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存储库(我的
如果您想继续使用Git作为您的主存储库,并且只需要不时"导出"对SVN的修订,那么您可以使用Tailt来保持SVN存储库的同步。它可以在不同的源代码管理系统之间复制修订,并使用在Git中所做的更改来更新SVN。
我没有尝试过Git-to-SVN转换,但是对于SVN->SVN示例,请参阅这个答案。
我想分享一个在WordPress社区中使用的很棒的工具,叫做分散。
Git WordPress插件和一些健全的分散
这使用户能够自动将其Git存储库发送到wordpress.org svn。理论上,此代码可以应用于任何SVN存储库。
如果您不必使用任何特定的SVN,并且您使用的是Github,那么您可以使用它们的SVN连接器。
这里有更多信息:在Github上与Subversion协作
您可以创建一个新的SVN存储库。导出Git项目(充实.git文件)。将其添加到SVN存储库中(使用Git中的内容初始化存储库)。然后使用说明在新的Git项目中导入SVN存储库。
但这将丢失您以前的Git历史。
有三种方法:
重新平衡:就像其他答案一样
commit id:找到svn first commit id和git first commit id,回传到.git/info/grafts:
签出每个git提交,将文件复制到svn_repo,svn commit
Bash演示:Github演示
v1.x:使用rebase和commit id
V2.X:使用复制文件,然后SVN提交
我只想和大家分享我的一些经验。在跑最后一步之前,我做了所有的步骤,一切都很好:
1 | git svn dcommit |
。
$ git svn dcommit
Use of uninitialized value $u in substitution (s///) at /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm line 101.
Use of uninitialized value $u in concatenation (.) or string at /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm line 101.
refs/remotes/origin/HEAD: 'https://192.168.2.101/svn/PROJECT_NAME' not found in ''
号
我找到了这个线程https://github.com/nirvdrum/svn2git/issues/50,最后找到了我在下面的文件101行中应用的解决方案。/usr/lib/perl5/vendor_perl/5.22/git/svn.pm
我换了
1 | $u =~ s!^\Q$url\E(/|$)!! or die |
。
具有
1 2 3 4 5 6 7 8 | if (!$u) { $u = $pathname; } else { $u =~ s!^\Q$url\E(/|$)!! or die "$refname: '$url' not found in '$u' "; } |
这解决了我的问题。
在我的情况下,我必须从SVN发起一个清洁项目。
1 2 | $ Project> git svn init protocol://path/to/repo -s $ Project> git svn fetch |
。
添加所有项目源…
1 2 3 | $ Project> git add . $ Project> git commit -m"Importing project sources" $ Project> git svn dcommit |
我最近不得不将几个Git存储库迁移到SVN,在尝试了所有我能找到的解决方案之后,最终对我起作用的是mercurial(是的,使用第三个VCS)。使用本指南,我提出了以下过程(在Linux上,但基本思想也应该在Windows上工作)。
必要的包装:
1 | $ sudo apt-get install git subversion mercurial python-subversion |
。
Mercurial需要通过在
1 2 | [extensions] hgext.convert= |
创建一些临时工作目录(我有几个要迁移的存储库,因此我为SVN和Git版本创建了目录,以使它们保持独立):
1 2 | $ mkdir svn $ mkdir git |
。
生成空的本地SVN存储库:
1 | $ svnadmin create svn/project |
号
克隆现有的Git存储库:
1 | $ git clone server/path/project.git git/project |
号
让Mercurial做它的事:
1 | $ hg convert --dest-type svn git/project svn/project |
号
现在,SVN存储库应该包含完整的提交历史记录,但不包含原始时间戳。如果这不是问题,请跳过下一部分到步骤11。
只要做一点工作,就可以更改每次提交的日期和时间。因为我的存储库相当小,所以我可以手动操作。首先,在SVN存储库中创建一个包含以下内容的
1 2 | #!/bin/bash exit 0; |
号
必须使此脚本可执行:
1 | $ chmod +x svn/project/hooks/pre-revprop-change |
号
Mercurial创建了一个名为project wc的SVN存储库的工作副本,因此切换到它并编辑提交时间:
1 2 | $ cd project-wc $ svn propedit svn:date --revprop -r 1 |
号
输入正确的日期和时间(注意时区!)然后保存。您应该会收到一条消息,说明"为属性svn设置新值:修订版1上的日期"。现在冲洗并对其他版本重复。
或者检查提交历史记录以确保一切正常:
1 | $ svn log -r 1:HEAD |
号
然后返回一个级别:
1 | $ cd .. |
号
转储存储库:
1 | $ svnadmin dump svn/project > project.dump |
号
并将转储文件加载到Subversion服务器上。完成!
这个过程也可能直接在远程存储库之间工作,但我发现使用本地存储库更容易。修复提交时间是一项艰巨的工作,但总的来说,这个过程比我发现的任何其他方法都要简单得多。
另一个有效的序列(每一步都有一些注释):
安装
1 | sudo apt-get install git-svn subversion |
1 | cd PROJECT_FOLDER |
号
在Subversion服务器上创建项目路径(不幸的是,与Tortoissvn相比,当前的
svn mkdir--parents protocol:///path/to/repo/project_folder/trunk-m"创建git repo占位符"
这是路径末端的
初始化
1 | git svn init -s protocol:///path/to/repo/PROJECT_FOLDER |
这是一个不需要
获取空的
1 | git svn fetch |
。
此步骤有助于将Subversion服务器与
在
1 | git rebase origin/trunk |
添加要提交的新的/修改过的文件(此步骤对于git活动是常规的,并且是可选的)
1 | git add . |
。
将新添加的文件提交到本地Git存储库(此步骤是可选的,仅在使用步骤7时适用):
1 | git commit -m"Importing Git repository" |
。
将所有项目更改历史推送到Subversion服务器中:
1 | git svn dcommit |
如果您不想将在Git中所做的每个提交提交到SVN存储库,该怎么办?如果您只想有选择地向管道发送提交,该怎么办?嗯,我有更好的解决办法。
我保留了一个本地Git存储库,我所做的就是从SVN中获取和合并。这样我就可以确保我包含了与SVN相同的所有更改,但是我将提交历史与SVN完全分开。
然后我将单独的SVN本地工作副本保存在单独的文件夹中。这就是我从SVN提交的内容,我只是使用SVN命令行实用程序。
当我准备将本地Git存储库的状态提交给SVN时,我只需将所有混乱的文件复制到本地SVN工作副本中,然后使用SVN而不是Git从那里提交。
这样我就不必再做任何重新平衡,因为重新平衡就像自由基一样。