dvcs 部分合并(git、hg 合并跟踪)
我有一个关于一般 DVCS 的问题,包括 Git 和 Hg。
在 Git 和 Hg 中,合并跟踪都是在“提交”级别而不是“文件/目录”级别完成的。
“副作用”之一是你不能轻松地进行“部分合并”:
- 你已经修改了分支“feature_branch_x”中的 30 个文件
- 你只想合并(比方说)/kernel/gui 下的
文件“基于项目的合并跟踪”(Perforce、ClearCase、Plastic SCM <= 3.0)您只需选择几个要合并的文件,然后签入,然后重复合并,待处理的文件就会显示。
使用 Hg、Git:一旦合并(有一些方法可以在不合并的情况下保留文件),就会设置“跟踪”,如果您重复合并,则不会留下要合并的候选者。
我的问题是你对此感觉如何??
在某些情况下您认为“部分合并”是强制性的吗?没有它你还能活吗? (与提交/cset级别跟踪合并要快得多)。
免责声明:我在 Plastic SCM 工作,我们已在 4.0 中转向“cset”级别跟踪,但我们想知道保留“项目级别合并跟踪”或者甚至允许两者是否是一个好主意。
I've one question about general DVCS, including Git and Hg.
In both Git and Hg merge tracking is done at the "commit" level instead of the "file/directory" level.
One of the "side effects" is that you can't easily do a "partial merge":
- You've modified 30 files in your branch "feature_branch_x"
- You want to merge ONLY the files under (let's say) /kernel/gui
With "item based merge tracking" (Perforce, ClearCase, Plastic SCM <= 3.0) you can just select a few files to merge, then checkin, then later repeat the merge and the pending files will show up.
With Hg, Git: once you merge (there're ways to keep files out without being merged) the "tracking" is set and if you repeat the merge no candidates to merge are left.
My question is how do you feel about it??
Are there cases where you feel "partial merge" is mandatory? Can you live without it? (merge with commit/cset level tracking is much faster).
DISCLAIMER: I work for Plastic SCM and we've moved to "cset" level tracking in 4.0, but we're wondering whether it could be a good idea to stay with "item level merge tracking" or even allow both.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我的感觉是,想要对分支进行部分合并是一个迹象,表明一开始就在一个分支中放入了太多内容。处理这种情况的正确方法是将分支分成两个分支,从而纠正原始错误,而不是通过尝试跟踪部分合并来加剧错误。我更喜欢 SCM 功能,它可以使分支的拆分变得更容易。
My feeling is that wanting to do a partial merge of a branch is a sign that too much was put in one branch in the first place. The correct way to deal with that situation is to split the branch into two branches, thereby correcting the original error, not compounding the error by trying to keep track of a partial merge. I would favor an SCM feature that made splitting a branch easier to do.
Mercurial 和 Git 的这种全树合并源于两者仅跟踪整树状态的哲学。 Mercurial 和 Git 都无法在其元数据中存储部分合并的情况,因为这两个 SCM 都会跟踪合并的父级以及生成的树。这种观点的优点是,通过提交不成熟的合并而使存储库处于不稳定状态的可能性要小得多。
考虑一种情况,文件从一个子目录移动到另一个子目录,并且该路径也被编码到源文件中。现在,当您仅合并子目录中的文件时,文件会在合并过程中正确移动,但源文件中的引用仍然指向旧目录。当您现在提交此部分合并时,您在 VCS 中处于失效状态。您需要以某种方式将最终合并提交标记为完成提交(我不知道 Plastic SCM 是否具有这样的语义),以防止其他人检查这种正在进行的工作状态。
当然,合并长期转移的分支是令人讨厌的。在 DVCS 世界中,试图减轻这种怪物合并的影响,以合并早期和持续转移的分支(假设一个是功能分支,一个是稳定分支,经常合并稳定->功能是一个好主意)。 git 还能够跟踪合并冲突解决方案(称为 rerere ),当您尝试多次进行相同的合并时(例如在最终完成之前何时“练习”合并),这有助于减轻合并的痛苦。
This whole-tree merge of mercurial and Git comes from the philosophy of both to track only the state of a whole tree. Neither Mercurial nor Git can store in their metadata that there was a partial merge, since both SCM track the parents of the merge, and the resulting tree. The advantage of this kind of view is that it is much less likely to get the repo in an unstable state by committing half-baked merges.
Think of a situation where files where moved from one subdir into another, and also this paths are coded into a source file. Now when you merge the files in a subdirectory only, the files get correctly moved during the merge, but the references in the source files are still pointing to the old directory. When you now commit this partial merge, you have a defunct state in the VCS. You would need to somehow mark the final merge commit as the completing one (I don't know if Plastic SCM has such a semantic), to prevent others to check out such a work-in-progress state.
Of course it is nasty to merge branches which are diverted over a long time. In the DVCS world this monster-merges are tried to be mitigated to merge early and continuously diverting branches (say one is a feature branch, and a stable one, it is a good idea to often merge stable->feature). Also git has the ability to track merge conflict solutions (called rerere), which helps to mitigate merge pains when you try to do the same merge several times (like when to "practice" the merge before the final finish).
Pablo,这是一个支持项目级合并的真实案例:让我们将主
M
分支设置为客户分支C
。分支C
不久前就分叉了,可能是几周或几个月前,而M
同时也发生了显着的发展。现在您需要为客户进行热修复,从而修改C
中的代码。另外,您还需要引入M
中的更改。我们的工作流程是在
M
中进行全面、正确的修复,测试M
并交付产品的新通用版本。然后,我需要将修复的相关部分合并到C
中,以便能够为受问题影响的客户提供自定义构建。因此,我需要将一些更改从M
传输到C
。这样的操作将有以下几个方面:M
合并的文件不必来自M
中的最新变更集记录器,它们可能跨越多个变更集。因此,为了能够在检查存储库的历史记录时跟踪此类操作,文件之间的“数据(代码)流”应逐个文件记录。生成的“合并变更集”将包含 1:1 自动合并以及手动调整的合并。
更新:速度与可用性权衡:据我了解您的产品,您押注于诸如非常好的合并之类的功能。我敢打赌,大多数用户不会关心超速度 - 但他们会关心真正好的合并。
大约十年前,将 1000 个文件添加到 ClearCase 中需要 10 分钟。将它们添加到 Subversion 需要 1 分钟。这就是我们选择 Subversion 而不是 ClearCase 的原因。然而,如果 ClearCase 需要 2 分钟,我们很可能会选择 ClearCase,因为它具有更好的功能。
如果我获得支持现实世界商业软件开发场景的良好工作功能,我不会关心它是否会比我当前的 VCS (Subversion) 快或慢 50%。但是,另一方面,如果您提供的功能较差和/或与其他 VCS 工具相比存在可用性障碍,用户就不会切换。
总结变更集级别与项目级别合并:坚持自由 - 至少从我的角度来看,这就是项目级别合并。
Pablo, here's a real world case supporting item-level merge: let's have the main
M
branch a customer branchC
. The branchC
was forked a while ago, possibly weeks or months ago, andM
evolved significantly meanwhile. Now you need to do a hot fix for the customer and hence modify code inC
. Also, you need to introduce the change inM
.Our workflow would be to do full, proper fix in
M
, testM
and deliver a new general-purpose release of the product. Then I'd need to merge relevant parts of the fix intoC
to be able to provide a custom build to the customer affected by the problem. Hence I need to transfer some changes fromM
intoC
. Such operation will have the following aspects:M
need not be from the latest changeset recorder inM
, they may span several changesets.So, to able to track such operation when inspecting the repository's history, 'data (code) flows' between files shall be recorded on a file-by-file case. The resulting 'merge changeset' would consist of 1:1 automatic merges as well as manually adjusted merges.
UPDATE: Speed vs. usability tradeoff: As I understand your product you bet on features like really good merge. And I bet most users won't care of superspeed — but they do will care of a really good merge.
About a decade ago adding 1000 files into ClearCase took 10 minutes. It took 1 minute to add them into Subversion. That's why we chose Subversion over ClearCase. However, if it took ClearCase 2 minutes we would — most likely — choose ClearCase because of it's then-better features.
If I get good, working features that support real world commercial software development scenarios I won't care whether it will be 50 % faster or slower than my current VCS (Subversion). But, on the other hand, if you provide poor features and/or something that's a usability blocker in comparison to other VCS tools users won't switch.
To conclude on changeset-level vs. item-level merge: stick to freedom — and that's, at least from my point of view, item-level merge.
来自现在合并一些文件,稍后合并一些文件:
考虑提交由子提交组成,每个子提交仅更改一个文件,然后支持基于文件的操作。很明显,人们在分支/提交时不知道他们将来想要合并什么,这可以解决这个问题。 git 可以是一个内容和文件跟踪器。
from Merge some files now and some later:
consider commits to be made up of sub-commits with changes to only one file each, and then support file-based operations. it's clear that people don't know at branch/commit-time what they will want to merge in the future, and this would solve that. git could be a content AND file tracker.
恕我直言,最“适合”分支/合并的 SCM 是 PRCS,它支持无痛的部分合并和完整的每项历史记录。它允许您拥有诸如每个平台分支之类的东西并在它们之间进行合并,而不必担心特定于平台的更改“渗透”到其他分支中。这里描述了它使用的算法;
http://prcs.sourceforge.net/merge.html
我最怀念的是合并基础和两个分支不同的地方,它会对每个文件进行三向合并,第一次它会提示您输入“您的”,“他们的”或“合并”,并且它会记住您的默认响应为了下一次合并。
当我使用它时,我发现分支/合并如此轻松且直观,我一直使用它们,并且从未感觉复杂。由于某种原因,使用 hg 和 git 进行分支/合并从未感觉如此轻松。
IMHO the SCM that got branch/merge most "right" for this was PRCS, which supported painless partial merges with full per-item history. It allowed you to have things like per-platform branches and merge between them without fear of platform-specific changes "bleeding" into the other branch. The algorithm it used is described here;
http://prcs.sourceforge.net/merge.html
The thing I most miss is on merges where the basis and both branches differed, it would do a three-way-merge per file and the first time it would prompt you for "yours", "theirs", or "merge" and it would remember your response as the default for the next merge.
When I was using it I found branch/merge so painless and intuitive I used them all the time and it never felt complicated. For some reason branch/merge with hg and git have never felt quite so painless.