我一直在 Git 中完成所有工作并推送到 GitHub。我对软件和网站都非常满意,目前我不想改变我的工作习惯。
我的博士导师要求所有学生将他们的工作保存在大学托管的 SVN 存储库中。我发现了大量关于将现有 SVN 存储库拉入 Git 的文档和教程,但没有将 Git 存储库推送到新的 SVN 存储库。我希望一定有某种方法可以结合 git-svn 和一个新的分支和 rebase 以及所有这些美妙的术语来做到这一点,但我是一个 Git 新手,对它们中的任何一个都没有信心。
然后,当我选择时,我只想运行几个命令将提交推送到该 SVN 存储库。我希望继续使用 Git,并让 SVN 存储库镜像 Git 中的内容。
如果这有什么不同的话,我将是唯一一个致力于 SVN 的人。
我也需要这个,在 Bombe 的回答 + 一些摆弄的帮助下,我得到了它的工作。这是食谱:
导入 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 时,您可能会遇到冲突。通过添加状态为“未合并”的文件并恢复变基来解决这些问题。最终,您将完成;然后使用 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
并删除部分 [svn-remote "svn"]
部分。
然后您可以重新运行 git svn init
。
以下是我们如何使它工作的:
在您机器上的某处克隆您的 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
注意:我总是在之后废弃那个文件夹。
Unable to determine upstream SVN information from HEAD history.
的答案相反
git merge -s recursive -Xtheirs --allow-unrelated-histories master
。
直接使用 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
--prefix 为您提供远程跟踪分支,如“svn/trunk”,这很好,因为如果您将本地分支称为“trunk”,您不会得到模棱两可的名称。 -s
是标准主干/标签/分支布局的快捷方式。
从 SVN 获取初始内容:
git svn fetch
现在查找您的根提交的哈希(应该显示单个提交):
git rev-list --parents master | grep '^.\{40\}$'
然后获取空主干提交的哈希:
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
--root
一起使用来管理第一次提交,因此启动答案的警告可能不再正确。
在 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
,您应该完成了。但是,它会严重扰乱您的提交日期。
具有完整提交历史的 Git -> SVN
我有一个 Git 项目,不得不将其移至 SVN。我就是这样做的,保留了整个提交历史。唯一丢失的是原始提交时间,因为 libSVN 将在我们执行 git svn dcommit
时设置本地时间。
如何:
有一个 SVN 存储库,我们要在其中导入我们的东西并使用 git-svn 克隆它: git svn clone https://path.to/svn/repository repo.git-svn` 去那里: cd repo.git-svn 添加Git 存储库的远程(在此示例中,我使用 C:/Projects/repo.git)。您想推送到 SVN 并为其命名 old-git: git remote add old-git file:///C/Projects/repo.git/ 从 old-git 存储库中的 master 分支获取信息到当前存储库: git fetch old-git master 将 old-git 远程的 master 分支检出到当前存储库中名为 old 的新分支中: git checkout -b old old-git/master` rebase 将 HEAD 放在 old- 之上混帐/大师。这将维护您的所有提交。这基本上是将您在 Git 中完成的所有工作放在您从 SVN 访问的工作之上。 git rebase master 现在回到你的 master 分支: git checkout master 你可以看到你有一个干净的提交历史。这就是您要推送到 SVN 的内容。将您的工作推送到 SVN:git svn dcommit
就这样。它非常干净,没有黑客攻击,一切都开箱即用。享受。
git 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
,然后才能安装,请参阅 stackoverflow.com/questions/527037/git-svn-not-a-git-command
如果您想继续使用 Git 作为您的主存储库,并且只需要不时将修订“导出”到 SVN,您可以使用 Tailor 使 SVN 存储库保持同步。它可以在不同的源代码控制系统之间复制修订,并使用您在 Git 中所做的更改来更新 SVN。
我没有尝试过 Git 到 SVN 的转换,但是对于 SVN -> SVN 示例见 this answer。
另一个有效的序列(每个步骤都有一些评论):
安装 git-svn 和 subversion 工具包: sudo apt-get install git-svn subversion 在 PROJECT_FOLDER 里面切换 cd PROJECT_FOLDER 在 Subversion 服务器上创建项目路径(不幸的是,当前的 git-svn 插件与 TortoiseSVN 相比存在缺陷)。它无法将源代码直接存储到 PROJECT_FOLDER。相反,默认情况下,它将所有代码上传到 PROJECT_FOLDER/trunk。 svn mkdir --parents protocol:///path/to/repo/PROJECT_FOLDER/trunk -m "创建 git repo 占位符"
这是路径末尾的 trunk
必填的地方
初始化 .git 文件夹内的 git-svn 插件上下文 git svn init -s protocol:///path/to/repo/PROJECT_FOLDER 这是路径末尾不需要主干的地方 获取一个空的 Subversion 存储库信息 git svn fetch 这一步有助于将 Subversion 服务器与 git-svn 插件同步。这是 git-svn 插件建立远程/源路径并将其与服务器端的主干子文件夹相关联的时刻。在 git-svn 插件参与流程之前,重新设置旧的 Git 提交(此步骤是可选的)将新添加的文件提交到本地 Git 存储库(此步骤是可选的,仅在使用第 7 步时才适用): git commit -m "Importing Git repository" 将所有项目更改历史记录推送到 Subversion 服务器: git svn dcommit
您可以创建一个新的 SVN 存储库。导出您的 Git 项目(充实 .git 文件)。将它添加到 SVN 存储库(使用您目前在 Git 中的内容初始化存储库)。然后使用说明在新的 Git 项目中导入 SVN 存储库。
但这会丢失您之前的 Git 历史记录。
如果您不必使用任何特定的 SVN,并且您使用的是 GitHub,则可以使用他们的 SVN 连接器。
更多信息在这里:Collaborating on GitHub with Subversion
我最近不得不将几个 Git 存储库迁移到 SVN,在尝试了我能找到的所有解决方案之后,最终对我有用的是 Mercurial(是的,使用 第三个 VCS)。使用 this guide,我想出了以下过程(在 Linux 上,但基本思想也应该在 Windows 上工作)。
必要的软件包: $ sudo apt-get install git subversion mercurial python-subversion Mercurial 需要通过将以下内容添加到 ~/.hgrc 来配置: [extensions] hgext.convert= 创建一些临时工作目录(我有几个要迁移的存储库所以我为 SVN 和 Git 版本创建了目录,以保持它们分开): $ mkdir svn $ mkdir git 创建一个空的本地 SVN 存储库: $ svnadmin create svn/project 克隆现有的 Git 存储库: $ git clone server/path/project .git git/project 让 Mercurial 做它的事情: $ hg convert --dest-type svn git/project svn/project 现在 SVN 存储库应该包含完整的提交历史,但不包含原始时间戳。如果这不是问题,请跳过下一部分到第 11 步。只需稍做工作,就可以更改每次提交的日期和时间。由于我的存储库很小,因此我可以手动完成。首先,使用以下内容在 SVN 存储库中创建一个 pre-revprop-change 挂钩,以允许修改必要的属性:#!/bin/bash exit 0;这个脚本必须是可执行的: $ chmod +x svn/project/hooks/pre-revprop-change Mercurial 创建了一个名为 project-wc 的 SVN 存储库的工作副本,所以切换到它并编辑提交时间: $ cd project-wc $ svn propedit svn:date --revprop -r 1 输入正确的日期和时间(注意时区!)并保存。您应该会收到一条消息“为属性 svn:date 在修订 1 上设置新值”。现在冲洗并重复每个其他版本。可选择检查提交历史以确保一切正常: $ svn log -r 1:HEAD 然后返回上一级: $ cd .. 转储存储库: $ svnadmin dump svn/project > project.dump 并加载转储你的 Subversion 服务器。完毕!
这个过程可能也可以直接在远程存储库之间工作,但我发现使用本地存储库更容易。修复提交时间需要做很多工作,但总体而言,这个过程比我发现的任何其他方法都简单得多。
有三种方法:
rebase: 作为其他答案 commit id: find svn first commit id 和 git first commit id ,将它们回显到 .git/info/grafts:echo "git_id svn_id}" > .git/info/grafts 然后 git svn dcommit checkout each git提交,将文件复制到 svn_repo,svn 提交
bash 演示:github demo
v1.x:使用rebase和commit id
v2.x:使用复制文件,然后 svn commit
就我而言,我必须从 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
我想分享一个在 WordPress 社区中使用的很棒的工具,叫做 Scatter
Git WordPress plugins and a bit of sanity scatter
这使用户能够将他们的 Git 存储库自动发送到 wordpress.org SVN。理论上,此代码可以应用于任何 SVN 存储库。
我只是想与接受的答案分享我的一些经验。在运行最后一步之前,我完成了所有步骤,一切都很好:
git svn dcommit
$ git svn dcommit 在 /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm 第 101 行使用未初始化值 $u 替换 (s///)。在连接中使用未初始化值 $u (.) 或/usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm 第 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
我换了
$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";
}
这解决了我的问题。
这就是我会做的。假设我的本地分支称为 main
。填补空白,因为我不记得确切的 git svn
命令,因为我有一段时间没有使用它。
在 svn 中创建将用于项目的分支。
使用 git svn 克隆您想要的 svn 存储库(至少,您要使用的分支,这样您就不必获取我们不关心的其他数百万个修订)。
签出新 git repo 中的 svn 分支。
向此存储库添加一个远程,该远程指向您用于项目的原始 git 存储库。假设遥控器被称为the-real-stuff。
git fetch the-real-stuff # 这样我们就可以看到真正的 repo 中有什么
鉴于这是我们第一次将代码拉入 svn 中,我们必须欺骗 git 以便它可以“合并”该代码: git merge --allow-unrelated-histories the-real-stuff/main - m“在 svn 修订版中我想要的任何评论”。这将在本地“合并”两个分支。
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 个 repo 的想法,这样我们就不会用 svn 的东西填写原始 repo,尽管可以将整个东西保存在一个 git repo 中。
如果您不想将在 Git 中所做的每个提交都提交到 SVN 存储库怎么办?如果您只想有选择地向管道发送提交怎么办?好吧,我有一个更好的解决方案。
我保留了一个本地 Git 存储库,我所做的只是从 SVN 获取和合并。这样我可以确保我包含与 SVN 相同的所有更改,但我将提交历史记录与 SVN 完全分开。
然后我在一个单独的文件夹中保留一个单独的 SVN 本地工作副本。这就是我向 SVN 提交的那个,我只是为此使用 SVN 命令行实用程序。
当我准备好将本地 Git 存储库的状态提交到 SVN 时,我只需将整个乱七八糟的文件复制到本地 SVN 工作副本中,然后使用 SVN 而不是 Git 从那里提交。
这样我就不必做任何变基,因为变基就像自由变基。
不定期副业成功案例分享