从 SVN 迁移后断开 GIT 个分支
Disconnected GIT branches after migrating from SVN
尝试了几十个帖子,但仍然没有得到我想要的。
前言:
我们最初有一个非常大的 SVN 存储库,没有主干(标准结构)等。因此,我正在工作的项目也没有结构(在子文件夹内)。我在这个项目上工作了大约几个月,然后遇到了我需要一个分支来进行生产修复的情况。因此,我只将我的项目代码重组为主干、标签和分支(即 SVN 存储库中的子目录)。然后根据历史,我创建了一个名为 Live 的分支,并为生产做了一个修复并部署了它。然后,我将此修复合并到我的 trunk 中,没有任何问题。我们继续致力于 trunk 并继续部署,但由于 SVN 不必要的复杂性,我们没有将 trunk 合并到 Live 尽管我们的部署很少。 (这一切都在 SVN 中)
迁移:
我们最近决定设置一个新的 TFS 服务器并通过 GIT 进行版本控制。所以,在安装完成后,我有一个任务是将这个项目的代码迁移到 GIT。我开始使用 "git svn clone" 在我的本地 PC 上执行此操作,很高兴看到我的所有历史记录都已迁移。分支机构为:
- master: 起源于trunk,可以看到我在svn中重构后的历史
- Live: 从 SVN 存储库开始(项目文件夹创建日期)返回并正确标记为分支名称。
问题是分支断开(没有加入节点):-(
请看下图:
根据上图,master 分支从突出显示的提交(节点)开始,但 Live 分支仅从 SVN 第一次提交开始。
理想情况下,当真正创建时,我希望将 master 和 Live 上的所有内容都显示为来自 master 的分支。此外,当我尝试检查 Live 分支时,我收到警告,它是分离的 HEAD,我可能不会 get/push 提交到主(即 HEAD)分支。
有人可以向我发送解决此问题的步骤吗?
我认为可能的解决方案:
- 将 master 重命名为 svn-trunk 并将 Live 重命名为 SVN-Live
- 然后在提交时从SVN-Live创建一个名为master的分支(远程会不会有冲突?)已经完成重组(突出显示之前的一个,即"Live 2656")。
- 在 Master 上合并 SVN-trunk。
- 从这个 HEAD 创建名为 Live 的新分支(因为目前最终代码正在生产中)。
这个过程可能会有负面影响,所以我很谨慎。
- 我唯一担心的是它是否允许我将断开连接的 SVN-trunk 的提交合并到我的新 master? (现在 Git 扩展程序向我展示了将 Live 合并到 Master 的选项,但不是其他方式。
- 此外,如果我在本地反复试验并搞砸了,应该如何重置回当前状态?
更新:
根据 "Live@2656" 重命名分支并创建主控。现在,尝试将 "Svn-trunk" 合并到 master(新分支)- 我得到以下错误:
fatal: refusing to merge unrelated histories
Done
也许从一个新的 git svn clone
开始,因为这样可以避免一些头痛。此外,将此类获得的 git 存储库的副本保存在安全的地方也不是一个坏主意:)
还有两种方法您可以尝试...
可能性 #1 - 修复结构
更简洁的方法是重建存储库的真实结构。如果我没理解错的话,trunk
是在历史的某个时刻创建的。如果您能够在历史记录中找到那个点,您也许可以使用git rebase <SHA of that spot in branch Live>
将历史记录重新连接在一起。不过,可能会出现一些冲突。
但是,如果您在 SVN 上将一些开发进度合并回 Live
,您在合并时可能会遇到困难。为了避免这种情况,您可以将这些合并重建为适当的合并提交,但如果您不必拥有适当的历史记录,这可能不值得花时间...
可能性 #2 - 只是变基
如果您根本不关心正确的历史记录,或者更简单的解决方案...
git checkout master
git rebase Live
您唯一需要确定的是解决可能的冲突。
对于一次性迁移 git-svn
不是 转换存储库或部分存储库的正确工具。如果您想使用 Git 作为现有 SVN 服务器的前端,这是一个很好的工具,但是对于一次性转换,您应该 而不是 使用 git-svn
,但是svn2git
更适合这个用例。
有很多名为 svn2git
的工具,最好的可能是来自 https://github.com/svn-all-fast-export/svn2git 的 KDE。我强烈建议使用 svn2git
工具。这是我所知道的最好的可用规则文件,而且您可以非常灵活地使用它的规则文件。
您将能够轻松地配置 svn2git
s 规则文件以从当前 SVN 布局中生成您想要的结果,包括可能存在的任何像您这样的复杂历史,并包括生成多个 Git从一个 SVN 存储库中提取一个存储库,或者将不同的 SVN 存储库合并为一个 Git 个存储库,如果你愿意,可以在一个 运行 中干净利落地。
如果您不是 100% 了解存储库的历史,http://blog.hartwork.org/?p=763 中的 svneverever
是一个很好的工具,可以在将 SVN 存储库迁移到 Git 时调查其历史.
尽管 git-svn
更容易入手,但除了它的灵活性之外,还有一些其他原因说明为什么使用 KDE svn2git
而不是 git-svn
更好:
svn2git
(如果使用了正确的),历史重建得更好更干净,对于具有分支和合并等的更复杂的历史尤其如此
- 标签是真正的标签,而不是 Git
中的分支
- with
git-svn
标签包含一个额外的空提交,这也使它们不属于分支,因此正常的 fetch
将不会得到它们,直到您将 --tags
给命令,因为默认情况下也只获取指向已获取分支的标签。使用正确的 svn2git 标签是它们所属的地方
- 如果您更改了 SVN 中的布局,您可以使用
svn2git
轻松配置它,使用 git-svn
您最终将丢失历史记录
- 使用
svn2git
您还可以轻松地将一个 SVN 存储库拆分为多个 Git 个存储库
- 或将同一个 SVN 根中的多个 SVN 存储库轻松合并为一个 Git 存储库
- 正确
svn2git
的转换速度比 git-svn
快无数倍
你看,git-svn
更差而 KDE svn2git
更优越的原因有很多。 :-)
我有一个类似的问题,其中一些(不是全部)SVN 分支和标签与主干断开连接。
Rebase 对我不起作用,但我通过重写历史修复了它们。
- 在树干中找到 branches/tags 应该连接的点。
- 对于标签,只需删除现有标签并在正确的提交上重新创建它。
- 对于分支,您需要使用 cherry-picks 报告所有提交。我想保留原始提交日期,以便在查看历史提交时看起来不像是 2 天前完成的。为此,您可以使用 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=""/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日志命令的解释:
- git log your_disconnected_branch ----> 获取断开连接分支中所有提交的列表。
- grep -P "(^commit|^Date:)" ----> 删除除包含提交 ID 和日期的行之外的所有行。
- tac ----> 反转文件的顺序,以便以相反的顺序插入提交。这具有在提交之前设置提交日期的额外好处。
- 's/commit /git cherry-pick /g' ----> 将 commit id 行转换为 cherry-pick
- sed 's/Date: (.*)$/GIT_COMMITTER_DATE=""/g' ----> 将日期行转换为 GIT_COMMITTER_DATE 变量的赋值
最后,别忘了用
清除你的 GIT_COMMITTER_DATE
GIT_COMMITTER_DATE=
以防止您以后的所有操作都显得非常陈旧。
尝试了几十个帖子,但仍然没有得到我想要的。
前言: 我们最初有一个非常大的 SVN 存储库,没有主干(标准结构)等。因此,我正在工作的项目也没有结构(在子文件夹内)。我在这个项目上工作了大约几个月,然后遇到了我需要一个分支来进行生产修复的情况。因此,我只将我的项目代码重组为主干、标签和分支(即 SVN 存储库中的子目录)。然后根据历史,我创建了一个名为 Live 的分支,并为生产做了一个修复并部署了它。然后,我将此修复合并到我的 trunk 中,没有任何问题。我们继续致力于 trunk 并继续部署,但由于 SVN 不必要的复杂性,我们没有将 trunk 合并到 Live 尽管我们的部署很少。 (这一切都在 SVN 中)
迁移: 我们最近决定设置一个新的 TFS 服务器并通过 GIT 进行版本控制。所以,在安装完成后,我有一个任务是将这个项目的代码迁移到 GIT。我开始使用 "git svn clone" 在我的本地 PC 上执行此操作,很高兴看到我的所有历史记录都已迁移。分支机构为:
- master: 起源于trunk,可以看到我在svn中重构后的历史
- Live: 从 SVN 存储库开始(项目文件夹创建日期)返回并正确标记为分支名称。
问题是分支断开(没有加入节点):-(
请看下图:
根据上图,master 分支从突出显示的提交(节点)开始,但 Live 分支仅从 SVN 第一次提交开始。
理想情况下,当真正创建时,我希望将 master 和 Live 上的所有内容都显示为来自 master 的分支。此外,当我尝试检查 Live 分支时,我收到警告,它是分离的 HEAD,我可能不会 get/push 提交到主(即 HEAD)分支。
有人可以向我发送解决此问题的步骤吗?
我认为可能的解决方案:
- 将 master 重命名为 svn-trunk 并将 Live 重命名为 SVN-Live
- 然后在提交时从SVN-Live创建一个名为master的分支(远程会不会有冲突?)已经完成重组(突出显示之前的一个,即"Live 2656")。
- 在 Master 上合并 SVN-trunk。
- 从这个 HEAD 创建名为 Live 的新分支(因为目前最终代码正在生产中)。
这个过程可能会有负面影响,所以我很谨慎。
- 我唯一担心的是它是否允许我将断开连接的 SVN-trunk 的提交合并到我的新 master? (现在 Git 扩展程序向我展示了将 Live 合并到 Master 的选项,但不是其他方式。
- 此外,如果我在本地反复试验并搞砸了,应该如何重置回当前状态?
更新: 根据 "Live@2656" 重命名分支并创建主控。现在,尝试将 "Svn-trunk" 合并到 master(新分支)- 我得到以下错误:
fatal: refusing to merge unrelated histories
Done
也许从一个新的 git svn clone
开始,因为这样可以避免一些头痛。此外,将此类获得的 git 存储库的副本保存在安全的地方也不是一个坏主意:)
还有两种方法您可以尝试...
可能性 #1 - 修复结构
更简洁的方法是重建存储库的真实结构。如果我没理解错的话,trunk
是在历史的某个时刻创建的。如果您能够在历史记录中找到那个点,您也许可以使用git rebase <SHA of that spot in branch Live>
将历史记录重新连接在一起。不过,可能会出现一些冲突。
但是,如果您在 SVN 上将一些开发进度合并回 Live
,您在合并时可能会遇到困难。为了避免这种情况,您可以将这些合并重建为适当的合并提交,但如果您不必拥有适当的历史记录,这可能不值得花时间...
可能性 #2 - 只是变基
如果您根本不关心正确的历史记录,或者更简单的解决方案...
git checkout master
git rebase Live
您唯一需要确定的是解决可能的冲突。
对于一次性迁移 git-svn
不是 转换存储库或部分存储库的正确工具。如果您想使用 Git 作为现有 SVN 服务器的前端,这是一个很好的工具,但是对于一次性转换,您应该 而不是 使用 git-svn
,但是svn2git
更适合这个用例。
有很多名为 svn2git
的工具,最好的可能是来自 https://github.com/svn-all-fast-export/svn2git 的 KDE。我强烈建议使用 svn2git
工具。这是我所知道的最好的可用规则文件,而且您可以非常灵活地使用它的规则文件。
您将能够轻松地配置 svn2git
s 规则文件以从当前 SVN 布局中生成您想要的结果,包括可能存在的任何像您这样的复杂历史,并包括生成多个 Git从一个 SVN 存储库中提取一个存储库,或者将不同的 SVN 存储库合并为一个 Git 个存储库,如果你愿意,可以在一个 运行 中干净利落地。
如果您不是 100% 了解存储库的历史,http://blog.hartwork.org/?p=763 中的 svneverever
是一个很好的工具,可以在将 SVN 存储库迁移到 Git 时调查其历史.
尽管 git-svn
更容易入手,但除了它的灵活性之外,还有一些其他原因说明为什么使用 KDE svn2git
而不是 git-svn
更好:
svn2git
(如果使用了正确的),历史重建得更好更干净,对于具有分支和合并等的更复杂的历史尤其如此- 标签是真正的标签,而不是 Git 中的分支
- with
git-svn
标签包含一个额外的空提交,这也使它们不属于分支,因此正常的fetch
将不会得到它们,直到您将--tags
给命令,因为默认情况下也只获取指向已获取分支的标签。使用正确的 svn2git 标签是它们所属的地方 - 如果您更改了 SVN 中的布局,您可以使用
svn2git
轻松配置它,使用git-svn
您最终将丢失历史记录 - 使用
svn2git
您还可以轻松地将一个 SVN 存储库拆分为多个 Git 个存储库 - 或将同一个 SVN 根中的多个 SVN 存储库轻松合并为一个 Git 存储库
- 正确
svn2git
的转换速度比git-svn
快无数倍
你看,git-svn
更差而 KDE svn2git
更优越的原因有很多。 :-)
我有一个类似的问题,其中一些(不是全部)SVN 分支和标签与主干断开连接。
Rebase 对我不起作用,但我通过重写历史修复了它们。
- 在树干中找到 branches/tags 应该连接的点。
- 对于标签,只需删除现有标签并在正确的提交上重新创建它。
- 对于分支,您需要使用 cherry-picks 报告所有提交。我想保留原始提交日期,以便在查看历史提交时看起来不像是 2 天前完成的。为此,您可以使用 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=""/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日志命令的解释:
- git log your_disconnected_branch ----> 获取断开连接分支中所有提交的列表。
- grep -P "(^commit|^Date:)" ----> 删除除包含提交 ID 和日期的行之外的所有行。
- tac ----> 反转文件的顺序,以便以相反的顺序插入提交。这具有在提交之前设置提交日期的额外好处。
- 's/commit /git cherry-pick /g' ----> 将 commit id 行转换为 cherry-pick
- sed 's/Date: (.*)$/GIT_COMMITTER_DATE=""/g' ----> 将日期行转换为 GIT_COMMITTER_DATE 变量的赋值
最后,别忘了用
清除你的 GIT_COMMITTER_DATEGIT_COMMITTER_DATE=
以防止您以后的所有操作都显得非常陈旧。