具有非标准布局的Git svn迁移不';不显示合并

具有非标准布局的Git svn迁移不';不显示合并,git,svn,version-control,merge,git-svn,Git,Svn,Version Control,Merge,Git Svn,在尝试了本网站和其他网站的几个选项和一系列提示后,我陷入了困境。我的主要问题是:我想将SVN存储库的一部分迁移到Git,以保存历史。SVN布局是非标准的,在git SVN clone之后,我确实看到出现了正确的分支,但当我尝试将master合并到一个分支中时,会出现冲突,即两者都添加了一组文件。如果我查看一下,例如,gitg,我会看到分支,但它们似乎从未从master/trunk分支(因此从该角度看,“添加的”冲突似乎是合乎逻辑的),也没有在图中看到任何合并(例如从trunk到分支)(提交在那里

在尝试了本网站和其他网站的几个选项和一系列提示后,我陷入了困境。我的主要问题是:我想将SVN存储库的一部分迁移到Git,以保存历史。SVN布局是非标准的,在
git SVN clone
之后,我确实看到出现了正确的分支,但当我尝试将
master
合并到一个分支中时,会出现冲突,即两者都添加了一组文件。如果我查看一下,例如,
gitg
,我会看到分支,但它们似乎从未从
master
/trunk分支(因此从该角度看,“添加的”冲突似乎是合乎逻辑的),也没有在图中看到任何合并(例如从trunk到分支)(提交在那里,它们只是在
gitg
的图形显示中没有链接到分支)。事实上,对于一些分支,我甚至看到两个相同的提交,一个接一个(一个用于主分支,一个用于分支)。 我在SVN中创建分支的方法是使用
svncopy

更多详情:

存储库布局:稍微简化的SVN回购布局示意图(结构相同,名称不同,省略了一些目录)

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

我的
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 path
选项存在,因此我只保留我感兴趣的两个目录(
Project
Lib
)。我不筛选分支,因为只有一个分支与
Project1
没有直接关系

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

编辑开始:仔细检查提交发现我有许多空提交。这些都是由于
--忽略路径
选项造成的:空提交是在目录树中被忽略的部分中完成的。因此此选项的行为与我预期的不符。 回到绘图板上。。。 编辑结束

EDIT2 实际上,使用git filter branch--tag name filter cat--prune empty--all我成功地删除了空提交 EDIT2结束

合并问题的可能原因:分支/标记不是单个SVN提交,因为它们首先由一个提交组成,我在其中创建
branchs/Project1 featureX
目录,然后是两行
SVN copy
行,我在其中从主干复制
Project1
Lib
目录


关于如何正确转换此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
请注意,每个
分支
标记
行在
{}
中都有一个目录名列表,即使它只包含一个目录名。如果不这样做,获取将无法工作

下载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"
在使用
gitg
gitk
检查git repo后,发现许多合并丢失(图中未显示),因此我不得不手动移植这些合并,将父提交哈希添加到
.git/info/grafts
文件(文件格式为
merge\u hash parent1\u hash parent2\u 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
工具书类 感谢以下指向正确方向的站点:


我想你可以尝试使用单独的
Project1
Project2
Lib
。毕竟,在git中它们应该被分割成单独的存储库。分割项目确实是我的意图。事实上,其他项目很容易,因为它们没有分支,只有一些项目有标记(线性历史)因此有一个简单的
git svn克隆--prefix=svn/--trunk=pkg/Project3-a authors.txt$SVNURL Project3\u git
。Project1的复杂问题可能是我创建分支的方式。或者我误解了你的观点吗?git svn在匹配分支时支持通配符,所以你可以尝试类似
--branchs=branchs/Proje的方法ct1-*
对于您的
项目1
Hmmm,仔细检查上面的
git svn
命令的结果,我发现我有许多提交是空的。我认为
--ignore path
选项是原因。所以…回到原点。。。
cd Project1.git
git push --mirror https://github.com/mygithubuser/Project1.git