20

我曾经git svn将现有的 Subversion 存储库导入 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
4

5 回答 5

22

默认情况下git-svn,将 SVN 修订版和 Git 提交之间的映射存储在提交消息中。git-svn-id您是否在原始 Git 存储库中看到旧提交的这些行?这里我指的是托管在 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...
    

    如您所见,提交 D 没有 git-svn-id 行,但提交 C 有一个,并且该行指的是主干,因此您必须更新 refs/remotes/trunk 以提交 C:

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

    • 分支/foo => refs/remotes/foo

    • tags/1.0 => refs/remotes/tags/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
    

最后一个命令还从 SVN 服务器获取新修订。命令完成后,您将拥有 Subversion 存储库的 git-svn 克隆。此存储库中的历史已经不同,因此您必须像往常一样在 SVN 和 Git 存储库之间同步更改:

$ git svn rebase
$ git svn dcommit

希望有帮助。

于 2012-10-28T00:38:48.013 回答
3

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

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

原因是在每个git svn dcommitgit 自动重写您之前所做的所有提交之后:首先它将它们提交回 svn,然后添加提交的 svn 修订号(在一个名为 的唯一标识符中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

关于细节,这里是ProGit book 中的一个部分

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

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

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

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

于 2012-10-21T12:06:45.657 回答
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

完毕。反正我还没试过。首先备份您的存储库。

于 2012-10-23T09:28:04.377 回答
1

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

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

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

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

于 2012-10-23T18:17:11.077 回答
1

这个怎么样:

  • 备份!
  • 将 svn 历史重新导入 git
  • 将旧分支和新分支放到同一个仓库中
  • 将分支倒回到之前的提交F
  • 重新设置分支中的所有更改,因为您C在新导入的 svn 之上C
  • 重新尝试合并

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

于 2012-10-26T22:19:26.867 回答