具有非标准布局的Git-SVN迁移不显示合并 [英] Git-svn migration with non-standard layout doesn't show merges

查看:68
本文介绍了具有非标准布局的Git-SVN迁移不显示合并的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试了该网站的一些选项和大量提示以及其他建议之后,我陷入了困境.我的主要问题是:我想将SVN存储库(的一部分)迁移到Git,以保留历史记录.SVN布局是非标准的,在 git svn clone 之后,我确实看到了正确的分支出现,但是当我尝试例如将 master 合并到一个分支中,我发现冲突都说都添加了一组文件.如果我看看例如 gitg 我看到了分支,但它们似乎从未从 master /trunk分支(因此从这个角度看,两者都添加"的冲突似乎是合乎逻辑的),我也看不到任何分支图中的合并(例如,从主干到分支)(提交在那里,它们只是不链接到 gitg 的图形显示中的分支).实际上,对于某些分支,我什至看到两个相同的提交,一个接一个,另一个提交给master,一个提交给分支.我在SVN中创建分支的方式是使用 svn copy .

更多详细信息:

存储库布局: SVN存储库布局的略微简化的示意图(结构相同,名称不同,某些目录已被省略)

  pkg项目1项目2解放分行专案1-功能1项目1解放Project1-修补程序项目1解放库功能标签项目1v0.1.0v0.2.0项目1解放项目2v0.1.0 

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

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

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

这里有-ignore-paths 选项,因此我只保留两个目录( Project Lib )我有兴趣.我没有过滤分支,因为只有一个分支与 Project1 不直接相关.

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

编辑开始:对提交进行更仔细的检查后发现,我有很多空的提交.事实证明,这是由于-ignore-paths 选项所致:空的提交是在目录树中被忽略的部分中完成的.因此,此选项的行为并不符合我的预期.回到绘图板...编辑结束

EDIT2 实际上,使用 git filter-branch --tag-name-filter cat --prune-empty---all ,我设法删除了空提交 EDIT2 END

合并问题的可能原因:分支/标记不是单个SVN提交,因为它们首先包含一个在其中创建 branches/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 SVN2GitMigrationgit config svn.authorsfile ../authors.txt 

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

  [核心]repositoryformatversion = 0filemode = true裸=假logallrefupdates = true[svn-remote"svn"]网址= svn + ssh://user@svn.r-forge.r-project.org/svnroot/MyTool \提取= pkg/Project1:refs/remotes/svn/trunk[svn]authorsfile = ../authors.txt 

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

  [核心]repositoryformatversion = 0filemode = true裸=假logallrefupdates = true[svn-remote"svn"]网址= svn + ssh://user@svn.r-forge.r-project.org/svnroot/MyTool \提取= pkg/Project1:refs/remotes/svn/trunk标签=标签/Project1/{v0.4.2,v0.4.1,v0.4.0,v0.3.0,v0.2.2,v0.2.0}/Project1:refs/remotes/svn/tags/*标签=标签/项目1/{v0.2.1,v0.1-9e,v0.1.3}:引用/远程处理/svn/标签/*分支=分支/{Project1-v0.4.2-fixes,Project1-v0.4.1-fixes,Project1-refactor,Project1-feature1}/Project1:refs/remotes/svn/*分支=分支/{Project1-feature2}:引用/远程/svn/*[svn]authorsfile = ../authors.txt 

请注意,每行 branch tags 行如何在 {} 中包含目录名称列表,即使其中仅包含一个目录名称也是如此.没有这个,获取将无法进行.

下载SVN数据

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

  git svn提取 

后处理

此后,需要一些后处理.要将删除标记和分支转换为适当的本地标记和分支并删除远程标记和分支,请运行:

  for`git branch -r | grep -v标签|中的分支|grep -v干|sed's/svn \///'`;做git branch $ branch遥控器/svn/$ branch;完毕用于`git branch -r | grep标签|中的标签sed's; svn/tags/;;'`;做git tag $ tag remotes/svn/tags/$ tag;完毕对于`git branch -r`中的br;做git branch -d -r $ br完毕 

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

  git svn show-ignore>.gitignoregit添加.gitignoregit commit -m基于svn:ignore属性添加了.gitignore文件" 

使用 gitg gitk 检查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.gitgit push --mirror https://github.com/mygithubuser/Project1.git 

参考文献

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

After trying several options and a bunch of hints from this site and others I'm stuck. My main question is the following: I'd like to migrate (part of) an SVN repository to Git, preserving history. The SVN layout is non-standard and after git svn clone I do see the right branches appear, but when I try to e.g. merge master into a branch, I get conflicts that say both added a set of files. If I take a look in e.g. gitg I see the branches, but they never seem to branch from master/trunk (so the "both added" conflicts seem logical from that perspective), nor do I see any of the merges (e.g. from trunk to a branch) in the graph (the commits are there, they just don't link to branches in the graphical display of gitg). In fact, for some branches I even see two identical commits one after the other (one for master, one for the branch). The way I created the branches in SVN was using svn copy.

Some more details:

Repository layout: A slightly simplified schematic of the SVN repo layout (the structure is the same, names are different, some directories have been omitted)

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

The Lib directory is closely associated with Project1, but also used by others. That is why I (starting with v0.2.0) created to Project1 and Lib subdirectory structure in the branches and tags.

My git svn workflow: This is the most promising command I used to clone the 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

The --ignore-paths option is there so that I keep only the two directories (Project and Lib) in which I'm interested. I do not filter on branches since there is only one branch not directly related to Project1.

After that I convert the remote branches to local branches (and remove the remote branches), then convert the tags to proper Git tags.

EDIT START: Closer inspection of the commits reveals that I have many empty commits. These turn out to be due to the --ignore-paths option: the empty commits are done in parts of the directory tree that are ignored. So this option doesn't really behave as I expected. Back to the drawing board... EDIT END

EDIT2 Actually, using git filter-branch --tag-name-filter cat --prune-empty -- --all I managed to remove the empty commits EDIT2 END

Possible cause of my merge problems: Branches/Tags are not single SVN commits because they first consist of a commit in which I create the branches/Project1-featureX directory, followed by two svn copy lines in which I copy the Project1 and Lib directories from trunk.

Suggestions on how to properly convert this SVN repo are very welcome! If, somehow this means loosing Lib that isn't a big deal. I'm planning to separate the two anyway once the migration has finished.

解决方案

After a lot of trial and error I solved my problem in the following way:

Preparation

First I initialised a repository without any branches or tags:

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

Next I added the author information:

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

After this, my .git/config file had the following contents:

[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

In order to get the branches and tags I changed that file to:

[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

Notice how each branches and tags line has a list of directory names in {}, even if it only contains one directory name. Without this, the fetching won't work.

Download the SVN data

To download and convert the SVN repository run:

git svn fetch

Postprocessing

After this, some post-processing is required. To convert the remove tags and branches to proper local tags and branches and delete the remote ones run:

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

Convert the svn:ignore properties to a .gitignore file

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

After inspecting the git repo with gitg or gitk it turned out that many merges were missing (not show in the graph), so I had to graft those by hand by adding the parent commit hashes to the .git/info/grafts file (the file format is merge_hash parent1_hash parent2_hash). Note that gitk shows the grafts, whereas gitg doesn't until they are made permanent.

To make the commits permanent use

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

and to remove the backups created by git filter-branch run:

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

Wrapping up

Now that everything is converted, clone the repository into a bare one:

git clone --bare SVN2GitMigration Project1.git

and push that to Github:

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

References

Thanks to the following sites for pointing to the right directions:

这篇关于具有非标准布局的Git-SVN迁移不显示合并的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆