我已经在git-svn
上阅读了许多SO问题和博客并进行了合并。其中一些(特别是git-svn
手册页)在我计划dcommit
的分支附近的任何地方使用合并警告 。
其他人,比如SO answer,只要我使用我在dcommitting
之前删除的一次性功能分支,就表示合并正常。
我有两个长寿SVN(和git)分支的设置:
svn/trunk
,git:master
) - 稳定分支svn/devel
,git:devel
) - 我从中分支功能分支的主要开发分支(我可以忍受将它们重新定位回devel
而不是合并。)
在上图中,(1)显示过去的SVN历史记录,其中branches/devel
已合并到trunk
。
(2)表明我已成功dcommitted
我当前的发展回到SVN。
问题:我可以使用git-svn
合并两个SVN分支,以便历史记录显示合并点(如SVN本身可以做到的)?换句话说:如果我dcommit
来自master
会发生什么,如(3)?
这会搞砸我的SVN(或git)历史吗?或者这简直忘记devel
完全合并到master
?
编辑:如果git
忘记devel
已合并到master
,那么dcommiting
与点之间是否存在差异(3)并将所有提交应用为单个补丁?
答案 0 :(得分:14)
进一步深入研究此事,我发现git支持在svn:mergeinfo
时在SVN分支上设置dcommit
属性:
git svn dcommit --mergeinfo "/branches/somebranch:1-3"
NB! svn:mergeinfo
被覆盖与命令行上给出的内容一样,所以要小心列出以前的合并
虽然更新的git版本添加了config参数来自动设置此属性:
config key: svn.pushmergeinfo
我在使用自动mergeinfo时遇到了一些麻烦 - 由于某种原因或其他GIT计算错误,我无法让它工作。
解决方案:git-merge-svn
为了自动完成这个过程,我写了一个shell脚本git-merge-svn,它可以用来合并两个SVN分支,并在dcommit上设置正确的svn:mergeinfo
。
该脚本处理两种情况:
git merge
使用这个脚本,我只能在git端生成这些合并并保留合并信息,以便GIT图很好地显示日志:
使用示例:
dcommit
devel6 到SVN(必需获取提交的SVN修订号)git merge-svn devel6
最后一个commant输出:
% git merge-svn devel6
About to do an SVN merge: devel6 -> testtunk6
* NEW MERGE COMMIT
|\
| * devel6 [7b71187] (r102)
* | testtunk6 [0682a45] (r101)
\|
* [273d6d6] (r100)
STEP 1: GIT merge
Executing:
git merge devel6
Continue? (y/n) [n]: y
Merge made by the 'recursive' strategy.
testfile | 1 +
1 file changed, 1 insertion(+)
STEP 2: SVN dcommit
executing:
git svn dcommit --mergeinfo
/idp/branches/devel:9-32,35-41 /idp/branches/devel6:89 /idp/branches/devel6:94 /idp/branches/devel6:93 /idp/branches/devel6:96 /idp/branches/devel6:97 /idp/branches/devel6:99 /idp/branches/devel6:100 /idp/branches/devel6:102
Continue? (y/n) [n]: y
Committing to https://my.svn.host/svn/auth/idp/branches/testtunk6 ...
M testfile
Committed r103
M testfile
Found merge parent (svn:mergeinfo prop): 7b71187fc371d3f86658c5850009e63be88157ac
r103 = 87759323cbadd38bac78087d57b6870a926287e7 (refs/remotes/svn/testtunk6)
No changes between 3fb2168cfbbe605fbd810d76513443203a85a549 and refs/remotes/svn/testtunk6
Resetting to the latest refs/remotes/svn/testtunk6
答案 1 :(得分:4)
Git和Svn有不同的数据结构来保存历史记录。
Svn使用一棵简单的树。即每个提交只有一个父,但一个提交可能有几个子(分支)。所以,Svn不支持合并。他们称之为“合并”的东西实际上是变更集移植,git中最接近的类比是rebase
或者cherry-pick
。从版本1.5开始,Svn支持元信息属性svn:mergeinfo
,它有助于以某种方式跟踪“合并”的内容,但它看起来主要是一种解决方法,这解释了为什么Svn中的分支如此难以使用。合并点是一个提交,它将所有合并的变更集和冲突解决方案压缩为一个变更集,可能使用svn:mergeinfo
属性进行注释。
Git使用Directed acyclic graph这是描述历史合并和分支的非常自然的方式。合并点只是另外两个(或更多!)父项的提交。所以,你的(3)图片是合并提交。因此,所有历史记录看起来都很自然,它可以在当前点的历史图表上访问所有提交。
Git-Svn网桥尝试尽力处理Svn设计缺陷,在执行dcommit
之前,它通常会重新绑定当前Svn分支顶部的所有合并提交。 〜2年前,git-svn无法提供svn:mergeinfo
,所以你要问的是不可能的。此外,当你dcommit
时,git会创建一个“难以”链接到svn提交的“双胞胎”提交,因此它会重写原始提交。