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

时间:2012-10-18 12:26:31

标签: git svn

我使用git svn将现有的Subversion repo导入git。然后我把它推到git服务器上的git repo。在过去几个月中,Subversion和git存储库都对软件进行了更改。不幸的是,我的本地副本与svn和git之间的链接已被删除。

我尝试再次使用git svn重新创建本地副本,但是当我从git服务器执行拉取时,它会抱怨warning: no common conflicts并最终合并两个具有相同提交的单独分支开始。像这样:

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

如何才能让svn更改像原始仓库中的分支一样?

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

5 个答案:

答案 0 :(得分:19)

默认情况下git-svn存储SVN修订版与Git提交映射的提交消息。您是否在原始Git存储库中看到了旧版提交的这些git-svn-id行?这里我的意思是Git存储库托管在Git服务器上,不是最近从SVN获取的。

如果是这样,你实际上没有丢失任何链接,git-svn应该能够从历史记录中恢复必要的数据。虽然由于不同版本的git-svn之间存在一些兼容性问题,但这可能有点棘手:

  1. 克隆原始Git存储库:

    $ git clone $GIT_SERVER repo
    $ cd repo
    
  2. 更新.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. 现在你必须使用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...
    

    正如你所看到的,commit D没有git-svn-id行,但是commit C有一行而该行引用trunk,所以你必须更新refs / remotes / trunk来提交C:

    $ git update-ref refs/remotes/trunk 4df9f21346526c6505a954d8310637864710308d
    
  4. 如果您有许多分支和标记,请针对我们上面指定的映射重复相同的步骤:

    • branches / foo =>参/遥控器/富

    • tags / 1.0 =>参/遥控器/标签/ 1.0

  5. 最后一步是恢复.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 (X.Y.Z) 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
    
  6. 最后一个命令也从SVN服务器获取新版本。命令完成后,您有一个Subversion存储库的git-svn克隆。此存储库中的历史记录有所不同,因此您必须通常在SVN和Git存储库之间同步更改:

    $ git svn rebase
    $ git svn dcommit
    

    希望有所帮助。

答案 1 :(得分:3)

首先,我检查git svn info命令的输出。你在那里看到一些奇怪的东西吗?

其次,问题是将git svn与除本地git存储库之外的辅助git存储库一起使用并不是一个好主意。

原因是在每个git svn dcommit git后自动重写您之前创建的所有提交:首先它将它们提交回svn,然后为提交添加svn修订号(in一个名为git-svn-id)的唯一标识符。

在您创建新dcommit

的存储库中应该是这样的
$ git log -1
commit 1234abc...
Author: ...
Date:   ...

Some commit message

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

关于详细信息,此处为section from the ProGit book

您写的错误消息可能是warning: no common commits(不是conflicts,正如您在问题中所写的那样),我的印象是git没有将这些元数据推送到远程仓库。

我认为你可以从死机中提升这个SVN链接,但要小心,将它放在repo的单独克隆上,并仔细阅读文档,了解它需要什么元数据。在git中,你可以使用管道工具做很多事情,看看它们。

顺便说一句,你不能简单地克隆远程git repo并使用它吗?

希望这会有所帮助,或者至少可以为您提供一些可以开始寻找解决方案的想法。

答案 2 :(得分:1)

来自提交图

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

使用以下命令

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

完成。无论如何,我还没有尝试过。首先备份您的存储库。

答案 3 :(得分:1)

最简单的解决方案是将本地git-svn分支推送到您的git服务器,如下所示:

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

它将使用您的本地分支覆盖git-server分支。

只有在您确定git-svn分支具有git服务器具有的所有提交时才这样做。

答案 4 :(得分:1)

这个怎么样:

  • 备份!
  • 将svn历史记录重新导入git
  • 将旧分支和新分支放入同一个仓库
  • F
  • 之前将您的分支倒回到提交
  • 自新{svn导入的C
  • 之后的C重新启动分支机构中的所有更改
  • 重新尝试合并

如果这不起作用,您可以尝试Git replace,但这可能不是一个好主意。