使用非标准布局的 Git-svn 迁移不显示合并



在尝试了这个网站和其他网站的几个选项和一堆提示之后,我卡住了。我的主要问题如下:我想将SVN存储库的(一部分)迁移到Git,以保留历史。SVN的布局是非标准的,在git svn clone之后,我确实看到了正确的分支出现,但是当我尝试将master合并到分支中时,我得到冲突,说两者都添加了一组文件。如果我看一看例如gitg我看到的分支,但他们似乎从来没有从master/主干分支(所以"两个添加"的冲突似乎从这个角度合乎逻辑),我也没有看到任何合并(例如从主干到分支)在图中(提交在那里,他们只是不链接到分支在gitg的图形显示)。事实上,对于一些分支,我甚至看到两个相同的提交一个接一个(一个用于master,一个用于分支)。我在SVN中创建分支的方式是使用svn copy

更多细节:

Repository layout:略为简化的SVN repo layout示意图(结构相同,名称不同,部分目录被省略)

pkg
    Project1
    Project2
    Lib
branches
    Project1-feature1
        Project1
        Lib
    Project1-hotfix
        Project1
        Lib
    Lib-feature
tags
    Project1
        v0.1.0
        v0.2.0
            Project1
            Lib
    Project2
        v0.1.0

Lib目录与Project1密切相关,但也被其他人使用。这就是为什么我(从v0.2.0开始)在分支和标记中创建了Project1Lib子目录结构。

我的git svn工作流:这是我用来克隆SVN repo的最有前途的命令:

git svn clone              
    --prefix=svn/ 
    --trunk=pkg 
    --branches=branches 
    --tags=tags/Project1 
    -A authors.txt 
    --ignore-paths='^pkg/(?!Project1|Lib)' 
    svn+ssh://user@svn.r-forge.r-project.org/svnroot/MyTool  SVN2GitMigration

--ignore-paths选项在那里,所以我只保留我感兴趣的两个目录(ProjectLib)。我没有对分支进行过滤,因为只有一个分支与Project1没有直接关系。

之后,我将远程分支转换为本地分支(并删除远程分支),然后将标记转换为适当的Git标记。

EDIT START:仔细检查提交,发现我有许多空提交。这是由于--ignore-paths选项:空提交是在目录树中被忽略的部分完成的。所以这个选项并不像我预期的那样。回到绘图板…<<strong>编辑结束/strong>

EDIT2 实际上,使用git filter-branch --tag-name-filter cat --prune-empty -- --all,我设法删除了空提交<<strong> EDIT2结束/strong>

我的合并问题的可能原因:分支/标签不是单个SVN提交,因为它们首先由一个提交组成,其中我创建了branches/Project1-featureX目录,然后是两个svn copy行,其中我从trunk复制了Project1Lib目录。

关于如何正确转换这个SVN仓库的建议是非常欢迎的!如果这意味着失去Lib,那也没什么大不了的。我计划在迁移完成后将两者分开。

经过反复试验,我用以下方法解决了我的问题:

准备

首先,我初始化了一个没有任何分支或标记的存储库:

git svn init 
  --prefix=svn/ 
  --trunk=pkg/Project1 
  svn+ssh://user@svn.r-forge.r-project.org/svnroot/MyTool 
  SVN2GitMigration

接下来我添加了作者信息:

cd SVN2GitMigration
git config svn.authorsfile ../authors.txt

之后,我的.git/config文件有以下内容:

[core]
       repositoryformatversion = 0
       filemode = true
       bare = false
       logallrefupdates = true
[svn-remote "svn"]
       url = svn+ssh://user@svn.r-forge.r-project.org/svnroot/MyTool 
       fetch = pkg/Project1:refs/remotes/svn/trunk
[svn]
       authorsfile = ../authors.txt

为了获得分支和标签,我将该文件更改为:

[core]
       repositoryformatversion = 0
       filemode = true
       bare = false
       logallrefupdates = true
[svn-remote "svn"]
       url = svn+ssh://user@svn.r-forge.r-project.org/svnroot/MyTool 
       fetch = pkg/Project1:refs/remotes/svn/trunk
       tags = tags/Project1/{v0.4.2,v0.4.1,v0.4.0,v0.3.0,v0.2.2,v0.2.0}/Project1:refs/remotes/svn/tags/*
       tags = tags/Project1/{v0.2.1,v0.1-9e,v0.1.3}:refs/remotes/svn/tags/*
       branches = branches/{Project1-v0.4.2-fixes,Project1-v0.4.1-fixes,Project1-refactor,Project1-feature1}/Project1:refs/remotes/svn/*
       branches = branches/{Project1-feature2}:refs/remotes/svn/*
[svn]
       authorsfile = ../authors.txt

注意branchestags行如何在{}中有一个目录名列表,即使它只包含一个目录名。如果没有这个,抓取将无法工作。

下载SVN数据

下载并转换SVN存储库,运行:

git svn fetch

后处理

之后,需要进行一些后处理。要将移除标签和分支转换为适当的本地标签和分支,并删除远程标签和分支,请运行:

for branch in `git branch -r |grep -v tags| grep -v trunk | sed 's/svn///'`; do
     git branch $branch remotes/svn/$branch;
done
for tag in `git branch -r |grep tags| sed 's;svn/tags/;;'`; do
      git tag $tag remotes/svn/tags/$tag;
done
for br in `git branch -r`; do
      git branch -d -r $br
done

svn:ignore属性转换为.gitignore文件

git svn show-ignore > .gitignore
git add .gitignore
git commit -m "Added .gitignore file based on the svn:ignore properties"

在使用gitggitk检查git repo后,结果发现许多合并都缺失了(在图中没有显示),所以我不得不通过将父提交哈希添加到.git/info/grafts文件(文件格式为merge_hash parent1_hash parent2_hash)来手工嫁接这些。请注意,gitk显示移植物,而gitg在移植物成为永久性移植物之前不会显示移植物。

要使提交永久使用

git filter-branch --tag-name-filter cat -- --all

和删除由git filter-branch创建的备份运行:

git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

结束

现在所有内容都转换完成了,将存储库克隆为裸存储库:

git clone --bare SVN2GitMigration Project1.git

并推送到Github:

cd Project1.git
git push --mirror https://github.com/mygithubuser/Project1.git
引用

感谢以下网站为您指出正确的方向:

  • http://john.albin.net/git/convert-subversion-to-git
  • http://www.sailmaker.co.uk/blog/2013/05/05/migrating-from-svn-to-git-preserving-branches-and-tags-3/
  • http://blokspeed.net/blog/2010/09/converting-from-subversion-to-git/
  • http://blog.agavi.org/post/16865375185/fixing-svn-merge-history-in-git-repositories
  • http://patrickbougie.com/2013/03/18/convert-svn-to-git-repository/
  • git svn指定分支和标签在非标准svn仓库布局

最新更新