简体   繁体   English

Git-svn合并了两个SVN分支

[英]Git-svn merge two SVN branches

I have read numerous SO questions and blogs on git-svn and merging. 我已经阅读了很多关于git-svn和合并的SO问题和博客。 Some of them (notably git-svn man page) warns against using merge anywhere near the branch I plan to dcommit from. 有些人(尤其是中git-svn手册页)警告不要使用我打算分支附近的任何地方合并dcommit从。

Others, like this SO answer , state that merging is fine as long as I use one-off feature branches that I delete before dcommitting . 其他的,像这样的SO回答 ,状态合并是罚款,只要我用我以前删除一个关机功能分支dcommitting

I have a setup with two long-living SVN (and git) branches: 我有两个长寿SVN(和git)分支的设置:

  • trunk (git-svn: svn/trunk , git: master ) - the stable branch trunk (git-svn: svn/trunk ,git: master ) - 稳定分支
  • branches/devel (git-svn: svn/devel , git: devel ) - the main development branch from which I fork off feature branches (and I can live with rebasing them back into devel instead of merging). branches / devel (git-svn: svn/devel ,git: devel ) - 我从中分支特征分支的主要开发分支(我可以将它们重新定位到devel而不是合并)。

源树中当前状态的快照

In the picture above, (1) shows past SVN history, where branches/devel has been merged into trunk . 在上图中, (1)显示了过去的SVN历史,其中branches/devel已合并到trunk

(2) shows that I have successfully dcommitted my current development back into SVN. (2)表明我已成功dcommitted当前的开发重新dcommitted回SVN。

The question: can I use git-svn to merge two SVN branches so that history shows the merge point (as SVN itself can do)? 问题:我可以使用git-svn合并两个SVN分支,以便历史显示合并点(如SVN本身可以做到的)? In other words: what happens if I were to dcommit from master as shown in (3) ? 换句话说:如果我如(3)所示从master那里dcommit ,会发生什么?

Will this mess up my SVN (or git) history? 这会弄乱我的SVN(或git)历史吗? Or will this just plain forget that devel was merged into master at all? 或者这只是简单地忘记了devel被合并为master

EDIT: If git just forgets that devel was merged into master , is there a difference between dcommiting from point (3) and applying all the commits as a single patch ? 编辑:如果git只是忘记了devel被合并到masterdcommiting从点(3)进行dcommiting并将所有提交应用为单个补丁之间有区别吗?

Digging some more into the matter, I found out that git supports setting svn:mergeinfo property on the SVN branch when dcommit 'ing: 再深入研究一下这个问题,我发现当dcommit时,git支持在SVN分支上设置svn:mergeinfo属性:

git svn dcommit --mergeinfo "/branches/somebranch:1-3"

NB! NB! the svn:mergeinfo is overwritten with whatever is given on the command-line, so be careful to list previous merges too . svn:mergeinfo被命令行中给出的任何内容覆盖 ,因此请小心列出以前的合并

While more recent git version added the config parameter to automatically set this property: 虽然更新的git版本添加了config参数来自动设置此属性:

config key: svn.pushmergeinfo

I had some troubles with the automatic mergeinfo - for one reason or the other GIT calculated it wrong and I couldn't get it to work. 我对自动mergeinfo有一些麻烦 - 由于一个原因或其他GIT计算错误而我无法使其工作。

SOLUTION: git-merge-svn 解决方案: git-merge-svn

To automate the process, I wrote a shell script git-merge-svn which can be used to merge two SVN branches with correct svn:mergeinfo set on the dcommit. 为了自动化这个过程,我编写了一个shell脚本git-merge-svn ,它可以用来合并两个SVN分支,并在dcommit上设置正确的svn:mergeinfo

The script handles both situations: 该脚本处理两种情况:

  • the branch is not merged in git - will do git merge beforehand 分支没有在git中合并 - 将事先进行git merge
  • the branches have been already merged in git (but not in SVN) - will traverse until previous ancestor for the merged commit revisions. 分支已经在git中合并(但不在SVN中) - 将遍历前一个祖先的合并提交修订。

With this script I was able to produce these merges solely on git-side and retain the merge info so that GIT graph shows the log nicely: 使用这个脚本,我只能在git端生成这些合并并保留合并信息,以便GIT图很好地显示日志:

git-merge-svn结果

Example usage: 用法示例:

  1. Make some commits on devel6 devel6上做一些提交
  2. dcommit devel6 to SVN ( required to get SVN revision numbers for the commits) dcommit devel6 to SVN( 需要获取提交的SVN修订号)
  3. check out testtunk6 - yes, I know I made a typo in the name ;-) 看看testtunk6 - 是的,我知道我在名字上写了一个拼写错误;-)
  4. git merge-svn devel6

The last commant outputs: 最后的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

Git and Svn have different data structure to keep a history. Git和Svn有不同的数据结构来保存历史记录。

Svn uses a simple tree. Svn使用一棵简单的树。 Ie each commit has only one parent, but one commit could have several childs (branches). 即每个提交只有一个父,但一个提交可能有几个子(分支)。 So, Svn doesn't support merges. 所以,Svn不支持合并。 The thing they call as "merge" is actually changeset porting, the closest analogy in git is rebase or maybe cherry-pick . 他们称之为“合并”的东西实际上是变更集移植,git中最接近的类比是rebase或者也许是cherry-pick From version 1.5 Svn supports a metainfo property svn:mergeinfo which helps somehow to track what was "merged", however it looks mostly as a workaround, that explains why branches in Svn are so hard to use. 从版本1.5开始,Svn支持元信息属性svn:mergeinfo ,它有助于以某种方式跟踪“合并”的内容,但它看起来主要是一种解决方法,这解释了为什么Svn中的分支如此难以使用。 Merge point is a commit which squashes all merged changesets and conflict resolution into one changeset, probably annotated with the svn:mergeinfo property. 合并点是一个提交,它将所有合并的变更集和冲突解决方案压缩为一个变更集,可能使用svn:mergeinfo属性进行注释。

Git uses Directed acyclic graph which is very natural way to describe history merging and branching. Git使用Directed非循环图 ,这是描述历史合并和分支的非常自然的方式。 A merge point is just another commit with two (or more!) parents. 合并点只是另外两个(或更多!)父项的提交。 So, your (3) on the picture is a merge commit. 所以,你的(3)图片是合并提交。 So, all history looks natural, it has all commits reachable on a history graph from the current point. 因此,所有历史记录看起来都很自然,它可以在当前点的历史图表上访问所有提交。

Git-Svn bridge tries do the best to handle Svn design drawback, before doing dcommit it usually rebases all merged commits on the top of the current Svn branch. Git-Svn网桥尝试尽力处理Svn设计缺陷,在进行dcommit之前,它通常会dcommit当前Svn分支顶部的所有合并提交。 Asof ~2 years ago, git-svn was not able to supply svn:mergeinfo , so the thing you are asking is impossible. 〜2年前,git-svn无法提供svn:mergeinfo ,所以你要问的是不可能的。 Moreover, when you are dcommit ing, git creates a "twin" commit "hardly" linked to a svn commit, so it rewrites original commit. 此外,当您dcommit ,git会创建一个“双”提交“几乎”链接到svn提交,因此它会重写原始提交。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM