从SVN迁移后断开GIT分支

时间:2017-08-23 14:34:25

标签: git git-svn

试图看几十个帖子但仍然没有得到我想要的东西。

前言: 我们最初有一个非常大的SVN存储库,没有主干(标准结构)等。所以,我工作的项目也没有结构(在子文件夹内)。我在这个项目上工作了大约几个月,然后遇到了我需要一个分支进行生产修复的情况。因此,我只将我的项目代码重组为主干,标签和分支(即SVN存储库中的子目录)。然后从历史记录中我创建了一个名为 Live 的分支,并对生产进行了修复并进行了部署。然后我将此修复程序合并到我的 trunk 中,没有任何问题。我们继续处理 trunk 并继续部署,但由于SVN的不必要的复杂性,并没有将 trunk 合并到 Live 虽然我们的部署很少。 (这都是SVN)

移植: 我们最近决定设置一个新的TFS服务器并通过GIT进行版本控制。因此,在安装完成后,我有一项任务是仅将此项目的代码迁移到GIT。我开始在我的本地PC上使用" git svn clone"我很高兴看到我的所有历史都被迁移了。分支机构为:

  • master :源自trunk,我可以看到我在SVN中重新构建它的历史。
  • Live :从SVN存储库的开头(项目文件夹创建日期)返回并正确标记为分支名称。

问题是分支断开连接(没有加入节点): - (

请参阅下图:

enter image description here

根据上图,主分支从突出显示的提交(节点)开始,但实时分支刚刚从SVN第一次提交开始。

理想情况下,我希望将master和Live上的所有内容显示为master的分支,当它真正创建时。此外,当我尝试检查Live分支时,我收到警告,它是分离的HEAD,我可能无法将提交/推送到主(即HEAD)分支。

有人可以告诉我修复此方案的步骤吗?

可能的解决方案,我认为:

  • 重命名为 svn-trunk ,将直播重命名为 SVN-Live
  • 然后在我完成重组时在提交时从 SVN-Live 创建一个名为 master 的分支(在远程会有任何冲突吗?) "直播2656")。
  • 在Master上合并 SVN-trunk
  • 从此HEAD创建名为 Live 的新分支(目前最终代码正在生产中)。

这个过程可能会产生负面影响,所以我要谨慎。

  • 我唯一担心的是它是否允许我将从断开的 SVN-trunk 的提交合并到我的新? (现在Git Extensions向我展示了将Live合并到Master而不是其他方式的选项。
  • 此外,如果我在本地进行反复试验并搞砸了事情,应该如何重置回当前状态?

更新: 根据" Live @ 2656"重命名分支和Created master。现在,尝试合并" Svn-trunk"掌握(新分支) - 我得到以下错误:

fatal: refusing to merge unrelated histories
Done

3 个答案:

答案 0 :(得分:1)

也许从一个新的git svn clone开始,因为它可以省去一些头痛。将这样获得的git存储库的副本保存在安全的地方也是一个坏主意:)

你可以尝试两种方式......

可能性#1 - 修复结构

更简洁的方法是重建存储库的真实结构。如果我理解正确,trunk是在历史的某个时刻创建的。如果您能够在历史记录中找到该位置,则可以使用git rebase <SHA of that spot in branch Live>将历史记录重新连接在一起。但是可能会出现一些冲突。

但是,如果您在SVN上将某些开发进度合并回Live,则合并时可能会遇到困难。为了避免这种情况,您可以将这些合并重建为正确的合并提交,但如果您没有合适的历史记录可能不值得花时间......

可能性#2 - 只是变基

如果你根本不关心正确的历史,那么这个解决方案就更简单了......

git checkout master
git rebase Live

你唯一需要确定的是解决可能的冲突。

答案 1 :(得分:0)

对于一次性迁移,git-svn 是用于转储存储库或部分存储库的正确工具。如果您想将Git用作现有SVN服务器的前端,这是一个很棒的工具,但对于一次性转换,您应该使用git-svn,但svn2git是更适合这种用例。

有很多名为svn2git的工具,最好的工具是来自https://github.com/svn-all-fast-export/svn2git的KDE工具。我强烈建议您使用svn2git工具。这是我所知道的最好的,它可以非常灵活地使用它的规则文件。

您将可以轻松配置svn2git的规则文件,以便从当前的SVN布局中生成您想要的结果,包括可能存在的任何复杂历史记录,包括从一个SVN回购中生成多个Git回购或者如果你愿意,可以在一次运行中将不同的SVN repos合并到一个Git repo中。

如果您不是100%关于存储库的历史记录,那么http://blog.hartwork.org/?p=763中的svneverever是一个很好的工具,用于在将SVN存储库迁移到Git时调查其历史记录。

尽管git-svn更容易入手,但除了灵活性之外,以下是使用KDE svn2git代替git-svn优于其他原因的其他原因:

  • 历史由svn2git重建得更好更清洁(如果使用了正确的历史记录),对于更复杂的分支和合并历史记录来说尤其如此,等等
  • 标签是真正的标签,而不是Git中的分支
  • 使用git-svn标记包含一个额外的空提交,这也使它们不属于分支,因此正常fetch将不会获得它们,直到您将--tags作为命令提供给默认情况下,仅提取指向已获取分支的标记。正确的svn2git标签是他们所属的地方
  • 如果您在SVN中更改了布局,则可以使用svn2git轻松配置,git-svn最终会丢失历史记录
  • 使用svn2git您还可以轻松地将一个SVN存储库拆分为多个Git存储库
  • 或将同一SVN根目录中的多个SVN存储库轻松组合到一个Git存储库中
  • 使用正确svn2git比使用git-svn
  • ,转化速度快了数十倍

你知道,git-svn更糟糕且KDE svn2git更优越的原因有很多。 : - )

答案 2 :(得分:0)

我遇到了类似的问题,其中一些(不是全部)SVN分支和标签已从中继断开。

Rebase不适用于我,但是我通过重写历史记录来修复它们。

  1. 在树干中找到应该附加分支/标签的点。
  2. 对于标签,只需删除现有标签并在正确的提交上重新创建即可。
  3. 对于分支,您需要使用cherry-pick报告所有提交。我想保留原始提交日期,以便在查看历史记录时看起来不像两天前那样。为此,您可以使用GIT_COMMITTER_DATE变量。

您首先需要导出变量:

# create and checkout a new branch where the disconnected branch should be inserted in trunk
git checkout -b <name of the branch> <sha where to insert>

# generate the list of commands to execute
git log <your_disconnected_branch> | grep -P "(^commit|^Date:)" | tac | sed 's/commit /git cherry-pick /g' | sed 's/Date:   \(.*\)$/GIT_COMMITTER_DATE="\1"/g'

# copy the output of the previous command

# export the GIT_COMMITTER_DATE variable
export GIT_COMMITTER_DATE

# paste the output of the log command, it should look like the following (without leading # sign):
#GIT_COMMITTER_DATE="Wed Jun 1 17:18:55 2016 +0000"
#git cherry-pick 54f30ac8071b5f935bf12595ab922542ce9d348e
#GIT_COMMITTER_DATE="Wed Jun 1 17:20:08 2016 +0000"
#git cherry-pick 5188d54f6d4bf09b06a108a887fdc6ec84f68919
#GIT_COMMITTER_DATE="Wed Jun 1 17:21:22 2016 +0000"
#git cherry-pick d47cbcfbd3fbd4c92e68fa2cfe92b555c7abaf8c

git log命令的说明:

  1. git log your_disconnected_branch ---->获取断开连接分支中所有提交的列表。
  2. grep -P“(^ commit | ^ Date :)” ---->删除除包含提交ID和日期的行以外的所有行。
  3. tac ---->颠倒文件的顺序,以便以相反的顺序插入提交。这样做还有一个好处,就是在进行提交之前设置提交日期。
  4. 's / commit / git cherry-pick / g'---->将提交ID行转换为Cherry-pick
  5. sed's / Date:(。*)$ / GIT_COMMITTER_DATE =“ \ 1” / g'---->将日期行转换为GIT_COMMITTER_DATE变量的赋值

最后,不要忘了用

清除GIT_COMMITTER_DATE。
GIT_COMMITTER_DATE=

以防止您以后的所有操作显得过时。