简体   繁体   English

如何将git存储库与svn存储库重新连接?

[英]How can I reconnect a git repository with a svn repository?

I used git svn to import an existing Subversion repo into git. 我使用git svn将现有的Subversion repo导入git。 I then pushed this to git repo on a git server. 然后我把它推到git服务器上的git repo。 Over the last few months changes to the software have been made in both Subversion and git repositories. 在过去几个月中,Subversion和git存储库都对软件进行了更改。 Unfortunately, my local copy with the links between svn and git has been deleted. 不幸的是,我的本地副本与svn和git之间的链接已被删除。

I've tried to recreate the local copy using git svn again, but when I do a pull from the git server it complains warning: no common conflicts and I end up merging two separate branches with the same commits at the start. 我曾尝试再次使用git svn重新创建本地副本,但是当我从git服务器执行拉取时,它会warning: no common conflicts ,我最终会在开始时将两个单独的分支合并到相同的提交中。 Like this: 像这样:

F
|\
| \
E  D
|  |
C  C
|  |
B  B
|  |
A  A

How can I get it to treat the svn changes like they happened on a branch from the original repo? 我怎样才能让它处理svn变化,就像它们发生在原始仓库的分支上一样?

F
|\
| \
E  D
| /
|/
C
|
B
|
A

By default git-svn stores mapping between SVN revisions and Git commits in commit messages. 默认情况下, git-svn存储SVN版本与提交消息中的Git提交之间的映射。 Do you see these git-svn-id lines for older commits in your original Git repository? 您是否在原始Git存储库中看到这些git-svn-id行用于旧提交? Here I mean that Git repository hosted on the Git server and not that one you've fetched from SVN recently. 这里我的意思是Git存储库托管在Git服务器上,而不是最近从SVN获取的那个。

If so, you actually didn't loose any links and git-svn should be able to restore the necessary data from the history. 如果是这样,你实际上没有松开任何链接,git-svn应该能够从历史记录中恢复必要的数据。 Though due to some compatibility issues between different versions of git-svn this may be a bit tricky: 虽然由于git-svn的不同版本之间存在一些兼容性问题,但这可能有点棘手:

  1. Clone your original Git repository: 克隆原始的Git存储库:

     $ git clone $GIT_SERVER repo $ cd repo 
  2. Update git-svn configuration in .git/config: 更新.git / config中的git-svn配置:

     $ git config svn-remote.svn.url $SVN_URL $ git config svn-remote.svn.fetch trunk:refs/remotes/trunk $ git config svn-remote.svn.branches branches/*:refs/remotes/* $ git config svn-remote.svn.tags tags/*:refs/remotes/tags/* 
  3. Now you have to update refs/remotes/* refs to the latest commits with git-svn-id line: 现在你必须使用git-svn-id行更新refs / remotes / * refs到最新的提交:

     $ git log --first-parent refs/heads/master commit d566edf5f77ae0a2f7418c40949757e75ef8e83c D commit 4df9f21346526c6505a954d8310637864710308d C git-svn-id: $SVN_URL .../trunk@3... commit 116a6760d3e278aa4d54f5bb22e531d30d731661 B git-svn-id: $SVN_URL .../trunk@2... commit d8bb201c6fd55ea5e645f2d8a07248593d177910 A git-svn-id: $SVN_URL .../trunk@1... 

    As you can see commit D does not have git-svn-id line, but commit C has one and that line refers to trunk, so you have to update refs/remotes/trunk to commit C: 正如你所看到的,commit D没有git-svn-id行,但是commit C有一行而该行指的是trunk,所以你必须更新refs / remotes / trunk来提交C:

     $ git update-ref refs/remotes/trunk 4df9f21346526c6505a954d8310637864710308d 
  4. If you have many branches and tags, repeat the same steps for them with respect to the mapping we've specified above: 如果您有许多分支和标记,请针对我们上面指定的映射重复相同的步骤:

    • branches/foo => refs/remotes/foo branches / foo => refs / remotes / foo

    • tags/1.0 => refs/remotes/tags/1.0 tags / 1.0 => refs / remotes / tags / 1.0

  5. The final step is to restore the mapping in .git/svn directory: 最后一步是恢复.git / svn目录中的映射:

     $ git svn fetch Migrating from a git-svn v1 layout... Data from a previous version of git-svn exists, but .git/svn (required for this version (XYZ) of git-svn) does not exist. Done migrating from a git-svn v1 layout Rebuilding .git/svn/refs/remotes/trunk/.rev_map.694389ff-b137-4359-84f9-4d1a25628e89... r1 = d8bb201c6fd55ea5e645f2d8a07248593d177910 r2 = 116a6760d3e278aa4d54f5bb22e531d30d731661 r3 = 4df9f21346526c6505a954d8310637864710308d Done rebuilding .git/svn/refs/remotes/trunk/.rev_map.694389ff-b137-4359-84f9-4d1a25628e89 

The last command also fetches new revisions from SVN server. 最后一个命令也从SVN服务器获取新的修订版。 After the command is done you have a git-svn clone of Subversion repository. 命令完成后,您有一个Subversion存储库的git-svn克隆。 The history in this repository has diverged, so you have to synchronize changes between SVN and Git repositories as usually: 此存储库中的历史记录有所不同,因此您必须通常在SVN和Git存储库之间同步更改:

$ git svn rebase
$ git svn dcommit

Hope that helps. 希望有所帮助。

First, I'd check the output of the git svn info command. 首先,我检查git svn info命令的输出。 Do you see some strange things there? 你看到一些奇怪的东西吗?

Second, the thing is that it is not a good idea to use git svn with a secondary git repository other than your local one. 其次,问题是将git svn与除本地git存储库之外的辅助git存储库一起使用并不是一个好主意。

The reason is that after each git svn dcommit git automatically rewrites all the commits you made previously: first it commits them back to svn and then adds the svn revision number for the commit (in a unique identifier called git-svn-id ). 原因是在每个git svn dcommit git会自动重写你之前做的所有提交 :首先它将它们提交回svn,然后为提交添加svn修订号(在一个名为git-svn-id的唯一标识符中)。

It should be something like this in a repository where you made a new dcommit : 在您创建新dcommit的存储库中应该是这样的:

$ git log -1
commit 1234abc...
Author: ...
Date:   ...

Some commit message

git-svn-id: http://your.svn.repo/svn/trunk@10 1234abc

About the details, here is a section from the ProGit book . 关于细节,这是ProGit书中的

The error message you wrote is probably warning: no common commits (not conflicts as you wrote in the question), and my impression is that git did not pushed these metadata into the remote repo. 您编写的错误消息可能是warning: no common commits (不是您在问题中写的conflicts ),我的印象是git没有将这些元数据推送到远程仓库。

I think you can raise this SVN link from the dead, but be careful, make it on a separate clone of the repo, and read the documentation carefully about what metadata it needs. 我想你可以从死机中提升这个SVN链接,但要小心,将它放在repo的单独克隆上,并仔细阅读文档,了解它需要什么元数据。 In git, you can do quite a lot of things with the plumbing tools, take a look on them. 在git中,你可以用管道工具做很多事情,看看它们。

Btw cannot you simply clone the remote git repo and use that? 顺便说一下你不能简单地克隆远程git仓库并使用它吗?

Hope this helps something, or at least give you a few ideas where you can start looking for a solution. 希望这有所帮助,或至少给你一些想法,你可以开始寻找解决方案。

From the commit graph 从提交图表

F
|\
| \
E   D
|   |
C1  C2
|   |
B1  B2
|   |
A1  A2

use the following command 使用以下命令

git checkout <SHA1-B1>
git checkout -b new
git cherry-pick <SHA1-C2> <SHA1-D>
git checkout <SHA1-F>
git checkout -b position_f
git merge new

Done. 完成。 Anyway, I haven't try it yet. 无论如何,我还没有尝试过。 Backup your repository at first. 首先备份您的存储库。

The simplest solution is to push your local git-svn branches to your git server, like this: 最简单的解决方案是将本地git-svn分支推送到您的git服务器,如下所示:

git push <git-server> <branch-name>:<branch-name>

It will override git-server branches with your local ones. 它将使用您的本地分支覆盖git-server分支。

Do that only if you are certain that git-svn branches have all the commits that git server has. 只有当你确定git-svn分支具有git服务器具有的所有提交时才这样做。

How about this: 这个怎么样:

  • Take a backup! 做个备份!
  • Re-import the svn history into git 将svn历史重新导入git
  • Get your old branch and the new branch into the same repo 将旧分支和新分支放入同一个仓库
  • Rewind your branch to the commit before F 将您的分支倒回到F之前的提交
  • Rebase all the changes in your branch since your C on top of the newly-svn-imported C 重新启动分支中的所有更改,因为您的C在新svn导入的C之上
  • Re-attempt the merge 重新尝试合并

If this doesn't work, you could try Git replace , but it might be a bad idea. 如果这不起作用,你可以尝试Git替换 ,但这可能是一个坏主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM