当主干移动时,如何在Git中保留SVN历史记录?

时间:2012-10-17 15:47:09

标签: svn git-svn

我正在尝试使用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目录下。我从这一举动完成后开始的历史。如果我在iPhone目录中svn log,我会得到缩短的历史记录。但是,如果我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

没有任何成功。

2 个答案:

答案 0 :(得分:14)

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

分别克隆两个回购。

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

现在棘手的部分...... git log masteroldstuff/master(或者trunkolstuff/trunk - 请你设置它并记下新克隆的第一个提交sha和旧克隆的最后一个提交sha(在移动之前)。

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

要重写SHA哈希所以一切都是犹太人,你不再需要替换参考...

git filter-branch

现在要清理不再需要的参考文献。

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

您将丢失历史记录中的第一个提交,但由于这应该是初始移动(即:没有实际文件内容已更改),因此它可能对您不利。

现在所有的历史记录都应该保留,git blame报告会记住回购曲目的历史记录,再次为您提供准确的信息。

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

PS - 这个解决方案我根据我的需求调整了here(我无法让他的移植方法为我的存储库工作 - 但使用replace似乎工作得非常漂亮)。

答案 1 :(得分:3)

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

不幸的是,版本1.0不支持您拥有的复杂布局。但是有1.1 EAP version可以很好地处理它。 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
    
  5. 这就是全部。现在你已经转换了Git存储库并保留了整个历史记录。

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