15

我正在尝试使用svn2git将 SVN 项目迁移到 git。但是,我在保存所有历史时遇到了问题。原因似乎是因为行李箱被移动了过去。我正在使用的命令是:

$ svn2git http://mysvnserver.com/myproject/iPhone/ --no-minimize-url --authors ../authors.txt

但这只是让我的历史可以追溯到 2011 年。该项目实际上是在 2010 年开始的。预计开始时看起来像这样:

myproject
   trunk
   branches
   tags

但在 2011 年,它变成了这样:

myproject
   iPhone
     trunk
     branches
     tags
   Android
      trunk
      branches
      tags

旧的树干和树枝在 iPhone 目录下。我从这一举动完成时开始的历史。如果我svn log在 iPhone 目录中这样做,我会得到缩短的历史记录。但是,如果我cd trunk; svn log得到完整的历史记录。

我不知道如何把这段历史弄出来。我的想法是以某种方式创建一个 git 存储库,其中只有主干的历史可以追溯到 2010 年。然后我稍后会将它作为我的主存储库中的一个分支,并做一个 rebase 以使历史正确。但我没有运气为主干创建这个回购。我试过了:

$ svn2git http://mysvnserver.com/myproject/ --rootistrunk --authors ../authors.txt

$ svn2git http://mysvnserver.com/myproject/ --rootistrunk -no-minimize-url --authors ../authors.txt

没有任何成功。

4

2 回答 2

15

我自己也遇到了同样的问题。这是我解决它的方法。

分别克隆两个存储库。

git svn clone -s [original-svn-location] [original-clone-directory]
git svn clone -s [new-svn-location] [new-clone-directory]

将旧的克隆数据添加到新的存储库中。

cd [new-clone-directory]
git remote add oldstuff ../[original-clone-directory]
git fetch oldstuff

现在是棘手的部分...... Do git logof masterand of oldstuff/master(或者可能trunkolstuff/trunk- 无论你如何设置)并写下新克隆的第一个提交 sha 和旧克隆的最后一个提交 sha(就在移动之前) .

git replace [first-commit-sha-from-new-clone] [last-commit-sha-from-old-clone]

并重写 SHA 哈希,使一切都符合要求,您不再需要替换 ref ...

git filter-branch

现在清理不再需要的引用。

git remote rm oldstuff
rm -rf .git/refs/replace

您将丢失历史记录中的第一次提交,但由于这应该是最初的举动(即:实际文件内容没有更改),因此对您来说可能无关紧要。

现在仍应维护所有历史记录,并且git blame报告会记住回购的旧历史记录,从而再次为您提供准确的信息。

您应该能够根据需要经常重复此操作(取决于您的项目更改其根位置的次数和/或有多少分支在移动的两侧都有提交)。

PS - 我根据我在这里找到的一个解决方案调整了这个解决方案(我无法让他的移植方法为我的存储库工作 - 但使用 replace 似乎工作得很好)。

于 2014-06-18T23:54:01.007 回答
3

您可以使用SubGit转换您的 SVN 存储库。

不幸的是,1.0 版不支持您所拥有的复杂布局。但是有1.1 EAP 版本可以很好地处理它。1.0 和 1.1 版本都适用于本地 SVN 存储库,因此您必须具有对 SVN 存储库的管理访问权限。

请执行以下操作以将 SVN 存储库转换为 Git:

  1. 生成初始配置。

    $ subgit configure SVN_REPO
    
  2. SubGit 很可能会检测到此存储库中的两个项目。AFAIU,您只需要一个 Git 存储库。因此,您必须在配置文件中只保留一个“git”部分。在那里指定您需要转换的所有分支。

    $ EDITOR SVN_REPO/conf/subgit.conf
    [core]
        ...
    [git "default"]
        repository = .git
        ...
        trunk = trunk:refs/heads/master
        branches = branches/*:refs/heads/*
        tags = tags/*:refs/tags/*
        shelves = shelves/*:refs/shelves/*
        branches = iPhone/trunk:refs/heads/iPhone/master
        branches = iPhone/branches/*:refs/heads/iPhone/*
        tags = iPhone/tags/*:refs/tags/iPhone/*
        branches = Android/trunk:refs/heads/Android/master
        branches = Android/branches/*:refs/heads/Android/*
        tags = Android/tags/*:refs/tags/Android/*
        ...
    [daemon]
        ...
    
  3. 将 SVN 转换为 Git。

    $ subgit install SVN_REPO
    
  4. 此时 SubGit 将所有版本从 SVN 转换为 Git。您可以在 SVN_REPO/.git 找到转换后的 Git 存储库。此外,SubGit 保持 SVN 和 Git 存储库同步,它安装了特殊的钩子来实现这一点。如果需要,摆脱这些钩子。

    $ subgit uninstall --purge SVN_REPO
    

就这样。现在您已经转换了 Git 存储库并保留了整个历史记录。

请注意,SubGit 是一种商业产品,但这种一次性转换是免费的。希望,它对你很有效。

于 2012-11-22T16:26:35.667 回答