我经常看,汞(和Git和...)处于比SVN合并更好,但我从来没见过哪里哪里SVN失败(或者SVN需要人工干预)汞/ GIT中可以合并一些实际的例子。 你可以发布的几个一步一步名单分支/修改/提交/...-操作显示了在何处,而汞/ GIT中愉快地继续前进SVN会失败? 实用,没有高度特殊的情况下,请...
一些背景:我们有几十个开发人员工作使用SVN的项目,并在自己的仓库中为每个项目(或类似项目组)。 我们知道如何应用释放-和功能分支,所以我们就不会遇到的问题很多时候(即,我们已经在那里,但我们已经学会了克服Joel的问题的“一个程序员造成创伤整个团队”或“需要6个开发商两周复兴分支”)。 我们有发布分支,是非常稳定的,只用于申请错误修正。 我们有树干,应该是足够稳定,能够在一周内创建一个发布。 我们有功能的支链的开发人员开发单或组可以工作。 是的,他们重返社会后,所以他们不会弄乱库中删除。 ;)
所以,我仍然试图找到在SVN汞/ GIT中的优势。 我很想获得一些实践经验,但目前还没有任何我们可以移动到汞/ GIT中还没有更大的项目,所以我坚持用只含有少量由文件小型人工玩的项目。 我正在寻找一个少数情况下,你可以感受到汞/ GIT中令人印象深刻的动力,因为到目前为止,我还经常读到他们,但没能找到他们自己。
我不使用颠覆自己,但是从发行说明,颠覆1.5:合并跟踪(基础),它看起来像有从如何在全合并跟踪工作如下区别DAG如Git或Mercurial的版本控制系统。
合并主干分支为分支合并到主干不同:由于某种原因,合并主干分支需要--reintegrate
选项svn merge
。
在如Git或Mercurial的分布式版本控制系统有干线和支线之间没有差异的技术 :所有部门都是一样的(有可能是社会差异,虽然)。 在任一方向被合并的方式相同。
您需要提供新的-g
( --use-merge-history
)选项svn log
和svn blame
采取合并追踪考虑在内。
在Git和Mercurial的合并跟踪显示历史(日志)和指责时,会自动考虑。 在Git中,你可以要求按照第一个父只--first-parent
(我想类似的选项也为水银存在的话)“丢弃”在合并跟踪信息git log
。
从我了解svn:mergeinfo
属性存储有关冲突的每个路径信息(颠覆是变更集为主),而在Git和水银它只是犯,可以有一个以上的父对象。
“已知问题”小节合并在Subversion的跟踪表明,重复/循环/反射合并可能无法正常工作。 这意味着,具有以下历史第二合并可能不会做正确的事(“A”可以是主干或分支,和“B”可分别分支或主干):
* --- * --- --- X * --- ---Ý* --- * --- * --- M2 < - 甲 \ \ / - * ---- --- M1 * --- --- * / < - 乙
的情况下的上述ASCII艺术得到打破:分支“B”被创建(叉形)从分支“A”在修订的“x”,则后面的分支“A”是在修订的“y”合并到分支“B”作为合并“M1”,最后分支“B”被合并到分支“A”作为合并“M2”。
* --- * --- --- X * ----- M1 - * --- * --- M2 < - 甲 \ / / \ - * --- ---Ÿ* --- --- * / < - 乙
的情况下的上述ASCII艺术得到打破:分支“B”被创建(叉形)从分支“A”在修订的“x”,它被合并到分支“A”在“Y”作为“M1”,后来再次合并到分支“A”为“M2”。
颠覆可能不支持的情况下,先进的纵横交错的合并 。
* --- b ----- B1 - M1 - * --- M3 \ \ / / \ X / \ / \ / \ - B2 - M2 - *
Git的使用“递归”合并策略处理这种情况只是在实践中很好。 我不知道水银。
在“已知问题”有警告说,合并跟踪migh不能与文件重命名工作,例如,当一方重命名文件(或许对其进行修改),和第二侧修改文件,而不(在旧名)重命名。
双方Git和水银处理这种情况下,只是在实践罚款:使用Git的重命名检测 ,使用水银重命名跟踪 。
HTH
我也一直在寻找的地方,比如说,颠覆无法将分支合并和Mercurial的情况下(和Git,集市,...)做正确的事。
svn书介绍如何重命名的文件不正确地被合并 。 这适用于颠覆1.5 , 1.6 , 1.7和1.8 ! 我曾试图重新在下列情况:
cd /tmp
rm -rf svn-repo svn-checkout
svnadmin create svn-repo
svn checkout file:///tmp/svn-repo svn-checkout
cd svn-checkout
mkdir trunk branches
echo 'Goodbye, World!' > trunk/hello.txt
svn add trunk branches
svn commit -m 'Initial import.'
svn copy '^/trunk' '^/branches/rename' -m 'Create branch.'
svn switch '^/trunk' .
echo 'Hello, World!' > hello.txt
svn commit -m 'Update on trunk.'
svn switch '^/branches/rename' .
svn rename hello.txt hello.en.txt
svn commit -m 'Rename on branch.'
svn switch '^/trunk' .
svn merge --reintegrate '^/branches/rename'
根据这本书,合并应干净完成,但在重命名的文件,因为在更新错误的数据trunk
被遗忘。 相反,我得到一个树冲突(这是使用Subversion 1.6.17,在写作的时候在Debian的最新版本):
--- Merging differences between repository URLs into '.':
A hello.en.txt
C hello.txt
Summary of conflicts:
Tree conflicts: 1
不应该有任何冲突都 - 更新应该合并到文件的新名称。 虽然颠覆失败,水银正确处理这样的:
rm -rf /tmp/hg-repo
hg init /tmp/hg-repo
cd /tmp/hg-repo
echo 'Goodbye, World!' > hello.txt
hg add hello.txt
hg commit -m 'Initial import.'
echo 'Hello, World!' > hello.txt
hg commit -m 'Update.'
hg update 0
hg rename hello.txt hello.en.txt
hg commit -m 'Rename.'
hg merge
在合并之前,库看起来像这样(从hg glog
):
@ changeset: 2:6502899164cc
| tag: tip
| parent: 0:d08bcebadd9e
| user: Martin Geisler
| date: Thu Apr 01 12:29:19 2010 +0200
| summary: Rename.
|
| o changeset: 1:9d06fa155634
|/ user: Martin Geisler
| date: Thu Apr 01 12:29:18 2010 +0200
| summary: Update.
|
o changeset: 0:d08bcebadd9e
user: Martin Geisler
date: Thu Apr 01 12:29:18 2010 +0200
summary: Initial import.
合并的输出是:
merging hello.en.txt and hello.txt to hello.en.txt
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
换句话说:水银从了修订版1的变化,并把它合并进从版本2(新的文件名hello.en.txt
)。 处理这种情况下,为了支持重构和重构正是这种事情,你会想在树枝做的当然是必不可少的。
没有谈到平时的优势(离线提交, 发布流程 ,...)这里是“合并”比如我喜欢:
主要场景我一直看到的是上一个分支... 两个不相关的任务实际上是发展
(它从一个功能开始,但是导致这种其他要素的发展。
或者,它从一个补丁起家,但它会导致另一个特点的发展)。
如何你只合并两个特征上的主要分支之一?
或者你如何隔离在自己的分支机构两个特征?
你可以试着产生某种补丁,与这个问题是你不知道的了的函数依赖可能之间已经存在:
- 在你的补丁中使用的提交(或修订版SVN)
- 其他承诺没有补丁的一部分
Git的(和Mercurial过我想)提出重订--onto选项变基(重置分支的根)一个分支的一部分:
从Jefromi的帖子
- x - x - x (v2) - x - x - x (v2.1)
\
x - x - x (v2-only) - x - x - x (wss)
你能解开这个情况下,你有补丁的V2,以及一个新的WSS的功能为:
- x - x - x (v2) - x - x - x (v2.1)
|\
| x - x - x (v2-only)
\
x - x - x (wss)
,让您可以:
- 隔离测试每个分支来检查,如果一切编译/工作按预期
- 只有你想什么主要合并。
其他功能我喜欢(这影响合并)是能力壁球提交以目前(在尚未推到另一个回购分支):
- 清洁历史
- 提交这是更连贯的(而不是commit1的功能1,commit2的功能2,commit3再次功能1 ...)
确保合并它们是轻松了很多,用更少的冲突。
我们最近从SVN迁移到Git的,面对这种不确定性相同。 有很多的传闻证据表明,GIT是更好的,但是这是很难遇到的任何实例。
我可以告诉你,虽然,GIT处于比SVN合并好了很多 。 这显然是传闻,但有一个表来跟随。
下面是一些我们发现的东西:
- SVN用完就扔了很多树的冲突在这似乎是不应该的情况。 我们从来没有这个底部,但它并没有在GIT发生。
- 虽然较好,GIT是显著更复杂。 花费在训练一段时间。
- 我们分别用龟SVN,这是我们很喜欢。 龟GIT也没有那么好,这可以把你赶走。 不过我现在用的GIT命令行,我更喜欢乌龟SVN或任何GIT GUI的。
当我们正在评估GIT我们跑了下面的测试。 这些数据显示GIT成为赢家当谈到合并,但没有那么多。 在实践中,不同的是更大的,但是我想我们还没有成功地复制这种SVN处理严重的情况。
其他已经覆盖的这个更多的理论方面。 也许我可以借给一个更实际的角度。
我目前正在为使用SVN在“特性分支”的发展模式的公司。 那是:
- 没有工作单位的树干上做
- 每个开发人员可以创建有自己的分支机构
- 分行应持续任务开展的持续时间
- 每个任务应该有它自己的分支
- 合并到主干需要被授权(通常通过Bugzilla的)
- 有时需要高层次的控制时,合并可以由网守完成
在一般情况下,它的工作原理。 SVN可以用于这样的流量,但它并不完美。 有SVN的一些方面得到的方式,塑造人的行为。 这给它的一些负面影响。
- 我们已经有相当多的问题,人们低于点分支
^/trunk
。 这窝在整个树合并信息的记录,并最终打破了合并跟踪。 假矛盾开始出现,并且混乱统治。 - 拿起从主干变成一个分支是相对直线前进。
svn merge
你想要做什么。 合并更改回需要(我们被告知) --reintegrate
上合并命令。 我从来没有真正了解这个开关,但它意味着该分支不能再合并到主干。 这意味着它是一个死的分支,你必须创建一个新的继续工作。 (见说明) - 创建在服务器上通过URL做操作和删除分支的全业务确实迷惑和恐慌的人。 因此,他们避免它。
- 分支之间的切换是很容易出错,留下了树的一部分看着分支A,同时使另一部分看分支B.所以人们喜欢做所有的工作在一个分支。
什么往往发生的是一个工程师创建第1天的一个分支,他开始了他的工作,忘掉它。 一段时间后,老板走来,问他能释放他的工作树干。 工程师一直害怕这一天,因为重返方式:
- 合并他的长寿命分支回主干和解决所有冲突,并释放无关的代码应该是在一个单独的分支,但没有。
- 删除他的分行
- 创建一个新的分支
- 交换他的工作副本新的分支
......因为工程师将此作为小,因为他们可以,他们可以不记得“魔法咒语”做每一个步骤。 错了开关和URL发生,突然他们正处在一个烂摊子,他们去得到“专家”。
最终,这一切平息下来,人们学会如何应对缺点,但每一个新的首发经历了同样的问题。 最终的事实(而不是什么我阐述了在他开始)为:
- 没有工作的树干上做
- 每个开发者都有一个主要分支
- 分行一直持续到工作需要被释放
- 凭票入场bug修复往往会得到自己的分公司
- 合并到主干被授权完成时
...但...
- 有时工作使得它的时候它不应该,因为它是在同一分支为别的东西主干。
- 人们避免所有合并(甚至简单的东西),所以人们常常在自己的小气泡工作
- 大合并趋于发生,并造成混乱的一个有限的量。
值得庆幸的是球队小到足以应付,但它无法扩展。 事情是,这一切都不是CVCS一个问题,但更多的是因为合并并不像DVCS一样重要,他们是不一样光滑。 这“合并摩擦”导致的行为,这意味着一个“特性分支”的模式开始打破。 良好的合并必须是所有VCS,而不只是DVCS的一个特征。
根据这个现在有一个--record-only
可用于解决开关--reintegrate
问题, 显然 V1.8选择时自动做了复兴,它不会导致分支已经死了之后
在此之前颠覆1.5(如果我没有记错),颠覆了,它不会记得合并历史显著dissadvantage。
让我们来看看由VonC介绍的情况:
- x - x - x (v2) - x - x - x (v2.1)
|\
| x - A - x (v2-only)
\
x - B - x (wss)
公告修订A和B.假设你从合并版本A的变化对“WSS”跳转到“V2只”修订版B(无论何种原因)的分支,但使用两个分支继续。 如果你试图使用水银再次合并两个分支,它只会合并修订版A和B.随着颠覆后的变化,你必须合并的一切,因为如果你没有做之前合并。
这是从我自己的经验,在从B到A合并了,由于代码量几个小时的例子:这将是一个真正的痛苦经历一遍 ,这已经与颠覆前1.5的情况。
从合并行为的另一个,可能更多相关差异颠覆再教育:Hginit :
想象一下,你和我的一些代码的工作,我们分支代码,和我们每个人都走下车到我们的独立的工作区,并分别做出许许多多改变代码的,所以他们有分歧不少。
当我们要合并时,Subversion会尝试一下这两个版本,我修改后的代码,并且您的修改后的代码,并试图猜测如何将它们放在一起打碎在一个大的邪恶混乱。 它通常会失败,产生并不是真正的冲突,只是地方颠覆未能找出我们做了“合并冲突”的页面和页面。
相反,当我们在水银分开工作,水银正忙着维持了一系列的变更的。 所以,当我们要合并在一起我们的代码,水银实际上有一大堆更多的信息:它知道我们每个人的改变,可以重新应用这些变化,而不是仅仅着眼于最终产品,并试图猜测如何把它一起。
总之,Mercurial的分析差异的方法是(是?)优于颠覆的。
文章来源: Merging: Hg/Git vs. SVN