将现有的 Git 存储库推送到 SVN

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/661018/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:17:17  来源:igfitidea点击:

Pushing an existing Git repository to SVN

svngitgit-svn

提问by cflewis

I've been doing all my work in Git and pushing to GitHub. I've been very happy with both the software and the site, and I have no wish to change my working practices at this point.

我一直在 Git 中完成我的所有工作并推送到 GitHub。我对软件和网站都非常满意,目前我不想改变我的工作习惯。

My PhD adviser is asking all students to keep their work in an SVN repository that's hosted at the university. I've found tons of documentation and tutorials about to pull down an existing SVN repository into Git, but nothing about pushing a Git repository to a fresh SVN repository. I expect there must be some way to do this with a combination of git-svn and a fresh branch and rebasing and all those wonderful terms, but I'm a Git newbie and don't feel confident with any of them.

我的博士导师要求所有学生将他们的工作保存在大学托管的 SVN 存储库中。我发现了大量关于将现有 SVN 存储库拉入 Git 的文档和教程,但没有将 Git 存储库推送到新的 SVN 存储库。我希望一定有某种方法可以通过将 git-svn 和一个新的分支和 rebase 以及所有这些美妙的术语结合起来来做到这一点,但我是一个 Git 新手,对它们中的任何一个都没有信心。

I then want to just run a couple of commands to push commits to that SVN repository when I choose. I wish to keep using Git and just have the SVN repository mirror what's in Git.

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

I'll be the only person ever committing to SVN, if this makes any difference.

如果这有什么不同的话,我将是唯一一个承诺使用 SVN 的人。

回答by troelskn

I needed this as well, and with the help of Bombe's answer + some fiddling around, I got it working. Here's the recipe:

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

Import Git -> Subversion

导入 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

After #3 you'll get a cryptic message like this:

在 #3 之后,您将收到一条像这样的神秘消息:

Using higher level of URL: protocol:///path/to/repo/PROJECT => protocol:///path/to/repo

使用更高级别的 URL: protocol:///path/to/repo/PROJECT => protocol:///path/to/repo

Just ignore that.

只是忽略它。

When you run #5, you mightget conflicts. Resolve these by adding files with state "unmerged" and resuming rebase. Eventually, you'll be done; then sync back to the SVN repository, using dcommit. That's all.

当你运行 #5 时,你可能会遇到冲突。通过添加状态为“未合并”的文件并恢复变基来解决这些问题。最终,你会完成;然后同步回 SVN 存储库,使用dcommit. 就这样。

Keeping repositories in sync

保持存储库同步

You can now synchronise from SVN to Git, using the following commands:

您现在可以使用以下命令从 SVN 同步到 Git:

git svn fetch
git rebase trunk

And to synchronise from Git to SVN, use:

并且要从 Git 同步到 SVN,请使用:

git svn dcommit

Final note

最后说明

You might want to try this out on a local copy, before applying to a live repository. You can make a copy of your Git repository to a temporary place; simply use cp -r, as all data is in the repository itself. You can then set up a file-based testing repository, using:

在应用到实时存储库之前,您可能希望在本地副本上尝试此操作。您可以将您的 Git 存储库复制到一个临时位置;只需使用cp -r,因为所有数据都在存储库本身中。然后,您可以使用以下方法设置基于文件的测试存储库:

svnadmin create /home/name/tmp/test-repo

And check a working copy out, using:

并检查工作副本,使用:

svn co file:///home/name/tmp/test-repo svn-working-copy

That'll allow you to play around with things before making any lasting changes.

这将允许您在进行任何持久更改之前玩弄事物。

Addendum: If you mess up git svn init

附录:如果你搞砸了 git svn init

If you accidentally run git svn initwith the wrong URL, and you weren't smart enough to take a backup of your work (don't ask ...), you can't just run the same command again. You can however undo the changes by issuing:

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

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

And remove the section [svn-remote "svn"]section.

并删除部分[svn-remote "svn"]部分。

You can then run git svn initanew.

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

回答by Alex Rouillard

Here's how we made it work:

以下是我们如何使它工作:

Clone your Git repository somewhere on your machine.

将您的 Git 存储库克隆到您机器上的某个位置。

Open .git/config and add the following (from Maintaining a read-only SVN mirror of a Git repository):

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

[svn-remote "svn"]
    url = https://your.svn.repo
    fetch = :refs/remotes/git-svn

Now, from a console window, type these:

现在,从控制台窗口中键入以下内容:

git svn fetch svn
git checkout -b svn git-svn
git merge master

Now, if it breaks here for whatever reason, type these three lines:

现在,如果它因任何原因在这里中断,请输入以下三行:

git checkout --theirs .
git add .
git commit -m "some message"

And finally, you can commit to SVN:

最后,您可以提交到 SVN:

git svn dcommit

Note: I always scrap that folder afterwards.

注意:事后我总是报废该文件夹。

回答by Alex Rouillard

Using git rebasedirectly will lose the first commit. Git treats it different and can't rebase it.

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

There is a procedure that will preserve full history: http://kerneltrap.org/mailarchive/git/2008/10/26/3815034

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

I will transcribe the solution here, but credits are for Bj?rn.

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

Initialize git-svn:

初始化 git-svn:

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

The --prefix gives you remote tracking branches like "svn/trunk" which is nice because you don't get ambiguous names if you call your local branch just "trunk" then. And -sis a shortcut for the standard trunk/tags/branches layout.

--prefix 为您提供远程跟踪分支,例如“svn/trunk”,这很好,因为如果您将本地分支称为“trunk”,则不会得到模糊的名称。并且-s是标准主干/标签/分支布局的快捷方式。

Fetch the initial stuff from SVN:

从 SVN 获取初始内容:

git svn fetch

Now look up the hash of your root commit (should show a single commit):

现在查找您的根提交的哈希值(应显示单个提交):

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

Then get the hash of the empty trunk commit:

然后获取空主干提交的哈希值:

git rev-parse svn/trunk

Create the graft:

创建移植:

echo <root-commit-hash> <svn-trunk-commit-hash> >> .git/info/grafts

Now, "gitk" should show svn/trunkas the first commit on which your master branch is based.

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

Make the graft permanent:

使移植物永久化:

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

Drop the graft:

丢弃移植物:

rm .git/info/grafts

gitk should still show svn/trunkin the ancestry of master.

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

Linearize your history on top of trunk:

在主干顶部线性化您的历史记录:

git svn rebase

And now "git svn dcommit -n" should tell you that it is going to commit to trunk.

现在“git svn dcommit -n”应该告诉你它将提交到主干。

git svn dcommit

回答by Bombe

Create a new directory in the Subversion repository for your project.

在 Subversion 存储库中为您的项目创建一个新目录。

# svn mkdir --parents svn://ip/path/project/trunk

Change to your Git-managed project and initialize git-svn.

更改为您的 Git 管理的项目并初始化 git-svn。

# git svn init svn://ip/path/project -s
# git svn fetch

This will create a single commit because your SVN project directory is still empty. Now rebase everything on that commit, git svn dcommitand you should be done. It will seriously mess up your commit dates, though.

这将创建一个提交,因为您的 SVN 项目目录仍然是空的。现在重新基于该提交的所有内容,git svn dcommit您应该完成。但是,它会严重弄乱您的提交日期。

回答by codingdave

Git -> SVN with complete commit history

Git -> 具有完整提交历史的 SVN

I had a Git project and had to move it to SVN. This is how I made it, keeping the whole commit history. The only thing that gets lost is the original commit time since libSVN will set the local time when we do git svn dcommit.

我有一个 Git 项目,不得不将它移到 SVN。我就是这样做的,保留了整个提交历史。唯一丢失的是原始提交时间,因为 libSVN 会在我们执行时设置本地时间git svn dcommit

Howto:

如何:

  1. Have a SVN repository where we want to import our stuff to and clone it with 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
    

    And you can see that you have a clean commit history. This is what you want to push to SVN.

  8. Push your work to SVN:

    git svn dcommit
    
  1. 有一个 SVN 存储库,我们要将我们的东西导入其中并使用 git-svn 克隆它:

    git svn clone https://path.to/svn/repository repo.git-svn`
    
  2. 去那里:

    cd repo.git-svn
    
  3. 添加 Git 存储库的远程(在本例中,我使用的是C:/Projects/repo.git)。您想推送到 SVN 并为其命名为 old-git:

    git remote add old-git file:///C/Projects/repo.git/
    
  4. 将 master 分支中的信息从 old-git 存储库中获取到当前存储库:

    git fetch old-git master
    
  5. 将 old-git remote 的 master 分支签出到当前存储库中名为 old 的新分支中:

    git checkout -b old old-git/master`
    
  6. Rebase 将 HEAD 放在 old-git/master 之上。这将维护您的所有提交。这基本上是将您在 Git 中完成的所有工作放在您从 SVN 访问的工作之上。

    git rebase master
    
  7. 现在回到你的主分支:

    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.

就这样。它非常干净,没有黑客攻击,一切都开箱即用。享受。

回答by Dmitry Pavlenko

I would propose a very short instruction in 4 commands using SubGit. See this postfor details.

我会使用SubGit在 4 个命令中提出一个非常简短的指令。有关详细信息,请参阅此帖子

回答by Jay Linski

I needed to commit my existing Git repository to an empty SVN repository.

我需要将我现有的 Git 存储库提交到一个空的 SVN 存储库。

This is how I managed to do this:

这就是我设法做到这一点的方式:

$ 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

It worked without problems. I hope this helps someone.

它没有问题。我希望这可以帮助别人。

Since I had to authorize myself with a different username to the SVN repository (my originuses private/public key authentication), I had to use the --usernameproperty.

由于我必须使用与 SVN 存储库不同的用户名授权自己(我origin使用私钥/公钥身份验证),因此我必须使用该--username属性。

回答by sth

If you want to keep on working with Git as your main repository and just need to "export" the revisions to SVN from time to time, you could use Tailorto keep the SVN repository in sync. It can copy revisions between different source control systems and would update the SVN with the changes you make in Git.

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

I haven't tried a Git-to-SVN conversion, but for a SVN -> SVN example see this answer.

我还没有尝试过 Git 到 SVN 的转换,但是对于 SVN -> SVN 示例,请参阅此答案

回答by Oleg Kokorin

Yet another sequence that worked (with some comments on each step):

另一个有效的序列(每个步骤都有一些评论):

  1. Install git-svnand subversiontoolkits:

    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-svnplugin 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"

  1. 安装git-svnsubversion工具包:

    sudo apt-get install git-svn subversion
    
  2. 开关里面 PROJECT_FOLDER

    cd PROJECT_FOLDER
    
  3. 在 Subversion 服务器上创建项目路径(遗憾的是当前git-svn插件与 TortoiseSVN 相比存在缺陷)。无法将源代码直接存储到PROJECT_FOLDER. 相反,默认情况下,它会将所有代码上传到PROJECT_FOLDER/trunk.

    svn mkdir --parents protocol:///path/to/repo/PROJECT_FOLDER/trunk -m "创建 git repo 占位符"

This is the place where trunkat the end of the path is mandatory

这是trunk路径末尾是强制性的地方

  1. Initialize the git-svnplugin context inside the .gitfolder

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

    This is the place where trunkat the end of the path is unnecessary

  2. Fetch an empty Subversionrepository information

    git svn fetch
    

    This step is helping to synchronize the Subversion server with the git-svnplugin. This is the moment when git-svnplugin establishes remotes/originpath and associates it with the trunksubfolder on the server side.

  3. Rebase old Git commits happened before the git-svnplugin became involved in the process (this step is optional)

    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 optionaland 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. 初始化文件夹git-svn内的插件上下文.git

    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 提交(此步骤是可选的

    git rebase origin/trunk
    
  4. 添加新的/修改的文件以提交(此步骤对于 Git 活动是常规的,并且是可选的

    git add .
    
  5. 将新添加的文件提交到本地 Git 存储库中(此步骤是可选的,仅适用于已使用步骤 7 的情况):

    git commit -m "Importing Git repository"
    
  6. 将所有项目更改历史推送到 Subversion 服务器:

    git svn dcommit
    

回答by u11157051

there are three methods:

有以下三种方法:

  1. rebase: as the other answers

  2. commit id: find svn first commit id and git first commit id , echo their into .git/info/grafts:echo "git_id svn_id}" > .git/info/graftsthen git svn dcommit

  3. checkout every git commit,copy files into svn_repo, svn commit

  1. rebase:作为其他答案

  2. commit id: 找到 svn first commit id 和 git first commit id ,将它们回显到 .git/info/grafts: echo "git_id svn_id}" > .git/info/graftsthengit svn dcommit

  3. 结帐每个 git commit,将文件复制到 svn_repo,svn commit

bash demo: github demo

bash 演示: github 演示

v1.x: use rebase and commit id

v1.x:使用rebase和commit id

v2.x: use copy files,then svn commit

v2.x:使用复制文件,然后使用 svn commit