帮助理解 Mercurial 中分支的好处
我一直在努力理解分支的好处。我无法推送到具有 2 个头或 2 个分支的存储库...那么我为什么需要/使用它们呢?
I've struggled to understand how branching is beneficial. I can't push to a repo with 2 heads, or 2 branches... so why would I ever need/use them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,您甚至可以用两个头进行推送,但由于您可能不想这样做,因此默认行为是阻止您这样做。但是,您可以强制推动进行。
现在,对于分支,我们以非分布式版本控制系统(例如 Subversion)中的一个简单场景为例。
假设您有一位同事与您在同一个项目中工作。 Subversion 存储库中当前最新的变更集是修订版 100,你们都在本地更新到此版本,以便现在你们都拥有相同的文件。
好吧,现在你的同事已经花了几个小时致力于他的更改,所以他做出了承诺。这会将中央存储库升级到修订版 101。您在本地仍处于修订版 100,并且仍在进行更改。
在某个时刻,您完成了,并且想要提交,但 Subversion 不允许您这样做。它说您必须先更新,因此您开始更新过程。
更新过程想要接受您的更改,并假装您实际上从修订版 101 而不是 100 开始。如果您的更改与您同事提交的内容不冲突,那么一切都很好,但如果您的更改< /em> 发生冲突,你就有问题了。
现在你必须将你的更改与他的更改合并,事情可能会变得混乱。例如,您可能最终合并了一个文件,OK,第二个文件,或者您认为如此,然后是第三个文件,然后您突然发现有些细节错误,最好是以不同方式合并第二个文件。
除非您在更新之前备份了更改,否则您迟早会忘记,否则您会遇到问题。
现在,上述场景其实很常见。好吧,也许不是合并部分,这取决于有多少人同时在同一区域或文件中工作,但“提交之前必须更新”部分在 Subversion 中很常见。
那么 Mercurial 是如何做到的呢?
好吧,Mercurial 在本地提交,它根本不与任何远程存储库通信,因此它不会阻止您提交。
那么,让我们再次尝试上述场景,这次只是在 Mercurial 中。
远程存储库中最重要的变更集是修订版 100。你们都已克隆了此版本,并且都开始处理修订版 100 中的更改。
您的同事在本地完成了更改并提交。然后,他将他的变更集推送到中央存储库,将提示更新到修订版 101。
然后,您完成更改并在本地提交,然后您想要推送,但收到了您已经发现的错误消息,并且正在询问。
那么这有什么不同呢?
好吧,您的更改现在已提交,没有办法,除非您非常努力不小心丢失或破坏它们。
以下是正在运行的 3 个存储库及其当前状态:
如果您要推送,并且被允许执行此操作(或强制推送),则中央存储库将如下所示:
两个头。如果你的同事现在退出,他应该继续从哪一个工作?这个问题就是 Mercurial 默认情况下阻止您造成这种情况的原因。
因此,您可以拉取,并在您自己的存储库中获得上述状态。
换句话说,您可以选择影响自己的存储库并在那里创建多个头,但是您不会将该问题强加给其他任何人。
然后,您可以合并,这与您在 Subversion 中必须执行的操作类型相同,只是您的变更集是安全的,它已提交,并且您不会意外损坏或破坏它。如果在合并过程中你想重新开始,你可以,没有任何损失,也没有造成任何伤害。
合并后,您的本地存储库如下所示:
现在可以安全地推送,如果您的同事现在拉取,他知道他必须从 M 变更集(合并了他和您的更改的变更集)继续。
上面的描述是由于 Mercurials 的分布式特性而发生的情况。
您还可以命名分支,以使它们更加永久。例如,您可能希望将一个分支命名为“稳定”,以表明该分支上的任何变更集都已经过彻底测试,并且可以安全地发布给客户或投入生产。然后,只有在所述测试完成后,您才会将更改合并到该分支上。
然而,本质与上面的描述相同。每当有多个人使用 Mercurial 处理同一个项目时,您就会获得分支,这是一件好事。
First of all, you can push even with two heads, but since you probably don't want to do that, the default behavior is to prevent you from doing it. You can, however, force the push to go through.
Now, as for branching, let's take a simple scenario in a non-distributed version control system, like Subversion.
Let's assume you have a colleague that is working in the same project as you. The current latest changeset in the Subversion repository is revision 100, you both update to this locally so that now both of you have the same files.
Ok, now your colleague has already been working on his changes for a couple of hours now, and so he commits. This brings the central repository up to revision 101. You're still on revision 100 locally, and you're still working on your changes.
At some point, you complete, and you want to commit, but Subversion won't let you. It says you have to update first, so you start the update process.
The update process wants to take your changes, and pretend you actually started with revision 101 instead of 100. If your changes are not in conflict with whatever it was your colleague committed, all is hunky dory, but if your changes are in conflict, you have a problem.
Now you have to merge your changes with his changes, and things can go haywire. For instance, you might end up merging one file OK, the second file OK, or so you think, and then the third file, and you suddenly discover that you've got some of the details wrong, it would've been better to merge the second file differently.
Unless you made a backup of your changes before updating, and sooner or later you will forget, you have a problem.
Now, the above scenario is actually quite common. Well, perhaps not the merging part, it depends on how many is working in the same area or files at the same time, but the "must update before committing" part is quite common with Subversion.
So how does Mercurial do it?
Well, Mercurial commits locally, it doesn't talk to any remote repository at all, so it won't stop you from committing.
So, let's try the above scenario again, just in Mercurial this time.
The tipmost changeset in the remote repository is revision 100. You both have cloned this down, and you're both starting to work on the changes, from revision 100.
Your colleague completes his changes and commits, locally. He then pushes his changeset up to the central repository, bringing the tip there up to revision 101.
You then complete your changes, and commit, also locally, and then you want to push, but you get the error message you've already discovered, and is asking about.
So how is this different?
Well, your changes are now committed, there is no way, unless you try really hard to accidentally lose them or destroy them.
Here's the 3 repositories in play and their current state:
If you were to push, and was allowed to do this (or force the push through), the Central repository would look like this:
Two heads. If your colleague now pulled, which one should he continue working from? This question is the reason Mercurial will by default prevent you from causing this.
So instead you pull, and you get the above state in your own repository.
In other words, you can chose to impact your own repository and create multiple heads there, but you are not imposing that problem on anyone else.
You then merge, the same type of operation you had to do in Subversion, except your changeset is safe, it was committed, and you won't accidentally corrupt or destroy it. If, mid-merge, you want to start over, you can, nothing lost, no harm done.
After the merge, your local repository looks like this:
This is now safe to push, and if your colleague now pulls, he knows that he has to continue from the M changeset, the one that merged his and your changes.
The above description is what happens due to Mercurials distributed nature.
You can also name branches, to make them more permanent. For instance, you might want to name a branch "stable", to signal that any changesets on that branch have been thoroughly tested and is safe for release to customers or to put into production. Then you would only merge changes onto that branch when said testing has been completed.
The nature, however, is the same as the above description. Whenever more than one person works on a project with Mercurial, you will get branches, and that's a good thing.
每当创建多个存储库克隆并在这些克隆中进行提交时,就会发生分支,无论您是否使用 hgbranch 命令命名它们。我的哲学是,你不妨给它们起个名字。它让事情变得不那么混乱。
Mercurial 分支的一个很好的解释: http://stevelosh .com/blog/2009/08/a-guide-to-branching-in-mercurial/
Whenever more than one clone of a repo is made and commits are made in those clones, branches happen, whether you name them by using the
hg branch
command or not. My philosophy is, you might as well give them a name. It makes things less confusing.A good explanation of mercurial branches: http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/