 When it comes time to merge in Mercurial, we use the merge command, which doesn't work by, as you might expect, merging two chain sets together, but rather merging the working directory with some other chain set. In this merging process, Mercurial does three things. First, it reconciles the manifest of the working directory with that of the chain set. That is, it decides what files should exist in the merger of the two and what they should be called and so forth. It effectively merges the manifests together. And then the second thing Mercurial does is once it's decided what files should end up in the merger, it then has to reconcile, it has to merge the individual files together. So the file named foo in the working directory has to get merged with the file named foo from the chain set. And then the third and final thing that Mercurial does in the merge is that it updates the working directory to have the chain set as its second parent. So the working directory ends up with two parents, the one it had before the merge, but then also the chain set we just merged with. Be very clear that unlike in some other revision control systems in Mercurial, the merge does not actually make a new chain set. It doesn't do a commit. It does the merger in the working directory and then the expectation is that once you've resolved all the conflicts and then whatever fixes you need, then you can make your commit. You can commit your merge. And once that commit is done, the working directory again just has a single parent, the chain set we just made. Now, when demonstrating a merge on the command line, we'll also use the parents command, which simply just lists the current parent or parents of the working directory. First though, let's consider again this quick example. We have here a repo with two heads and generally what you want to do with separate heads is merge them together. So we're going to merge the working directory with local revision three. This merges together the state of the working directory. It's manifest and its files emerges that state with the state of change set three with its manifest and its version of the files. And the product of that merger is placed in the working directory. So now the working directory manifest and its files reflect that merger. And then very importantly, the working directory has revision three as its other parent. If we perform a commit, this creates a new chain set, which has the parents revision two and revision three. And the working directory now just has a single parent, which is the new chain set. So looking at an example merger on the command line, this time we're going to start with a new repository, one which we've cloned from some existing open source project. So first I'm changing directory back to my home directory, which is denoted with a tilde tilde. Again, it's just a special shell syntax, which is shorthand for my home directory, which is actually slash home slash Brian. Anyway, once I'm back in my home directory, I then invoke hg clone. But this time I'm cloning a remote repository, which I specify with a URL for this to work. Obviously there has to be some server which is publicly serving this repository for people to clone, which is something we'll discuss how to do later. But in any case, we're just cloning a repository. This time it just happens to be on a remote machine on the network out there on the internet. And as Mercurial tells us, it's placing this new repository in the directory grab inside my home directory, so slash home slash Brian slash grab. Grab, by the way, is a Python library that has something to do with scraping websites. If I've not used it myself, it's just a project I happened to find on Bitbucket, which is a really useful Mercurial hosting site. If you want to have an internet accessible Mercurial repository, I recommend Bitbucket. It seems to be the service which everyone uses for Mercurial. There's also for Git, there's a similar site called GitHub, which is also very popular. In any case, so I now have this new clone in my directory grab, so I change directory into grab. And then I invoke hg parents, which lists the current parents of the working directory. In this case it's just one, as normally there is. Only after merger are there two parents, usually there's just one. As you can see, the current parent is local revision number 357. If we're going to demonstrate a merge, we're going to first need a separate branch. Currently there's just one head in this repo, so we're going to create another head. And we'll do so by branching off of the parent of the current parent. So if we want to find out what the parent of 357 is, we just invoke hg parents hyphenr357, and it lists the parents of 357, which as is usually the case, has the local revision number, which is just one lower, so 356. But be clear that it wasn't necessarily 356, because 357 might be the result of some merger, or for some other reason of how the change sets got copied into this repo, the parent of revision357 might have a totally different revision number than 356. In this case though, it was just 356. So we're going to update revision356 with hg update hyphenr356, and just to demonstrate that yes, the update really did modify the parent of the working directory. If we invoke hg parents, as in the reports, well now the parent is 356. That's the current parent of the working directory. And because we just updated the 356, the content of the working directory should now reflect the content of revision356. Now I'm going to make a small modification to one of the files in the working directory. There's a file test.py in there, which I know exists because I looked earlier. And having modified test.py, if we then invoke hg status, it tells us that yes, test.py has been modified. The only reason I'm making a modification is because otherwise Mercurial wouldn't let us commit. It would abort and say hey, you can't commit. There's no differences from the parent. So we made a modification, we did our commit, and Mercurial tells us that hey, a new head has been created. In other words, we now have a new branch in the repo. And now if we invoke hg parents, it reports that hey, the parent of the working directory is currently 358, which is the next provision number available, right? But then now it's reporting the parent of our parent. It's reporting that the parent of the current parent is 356. 356 is the parent of 358. And the reason it's including that line in the output of hg parents this time is because previously the parent of the parent was just one number lower. So we didn't need to report it. It could just be assumed to be one number lower than what it's reporting is that change set. And you'll see this in hg log as well when it reports a change set, it will include a line specifying the parent in cases where the local revision number is not, as is normally the case, just one lower. So when you don't see that line, you just assume that the parent has a local revision number which is one lower. So again, here's the current state of a repository or at least a few change sets we care about. There are, of course, 356 other change sets. We're just not showing them here. And notice I said 356, not 355 because there's a change set numbered zero. So now we have our separate heads and we can perform a merge by emerging the working directory with a vision 357. Or alternatively, we can update the working directory to revision 357 and have it merge with 358. Either way would give us really exactly the same result, but for this one really small detail which we'll talk about later. For the most part, you should consider a merge to be a commutative operation. It doesn't matter if we're merging head 357 with 358 or head 358 with 357. Do be clear, though, that in Mercurial, a merge is technically not between two change sets, but between a change set and a working directory. So in fact, if we were to modify the working directory first and then do our merge, we would end up with the merger of those modifications of 358 and 357, not strictly with 358 as it exists in its pristine state. Normally, though, Mercurial will warn you. It'll normally expect the working directory to be clean relative to its parent. That is not to have any changes because normally do an otherwise merging into a dirty working directory, a directory that is no longer exactly like its parent. That's normally a mistake. It's generally not something people do intentionally. But if it's what we really want, we can do that. We can merge into a dirty working directory. When we invoke merge, we just have to specify an option telling Mercurial that, yeah, we're really sure we know what we're doing. But in our example, though, we're just going to merge our pristine working directory with a parent of 358 with change set 357. And we do set with the command hd merge, and then specify the revision with hyphen r 357. Mercurial then gives us a report of how the merge went, what it did, and if there were any conflicts that Mercurial couldn't resolve. In this case, no, there were no conflicts. So what we would normally do now is commit this merge. Though, actually, a really good practice would be to test this version of the code and make sure that the merger didn't break anything. Because again, even though there weren't any conflicts, it doesn't mean there can't be some sort of logical conflict between the two separate versions of the code. And just to demonstrate that after the merge, the working directory now has two parents. If we invoke hd parents, you'll see it's reporting both revision 358 and 357 are the current parents of the working directory. The interesting question now is how exactly does Mercurial do its merger? How does it reconcile the differences between the manifests and between competing versions of the files? Well, we won't explain the process in its entirety, but we can consider some common cases. First, understand that merges in Mercurial are three-way merges. So the common ancestor is taken into account. And here we're merging revision 357 with revision 358, or technically the working directory with 358 as its parent. But anyway, the common ancestor of 357 and 358 in this case is 356. So when reconciling the differences between 357 and 358, Mercurial looks to 356, and that factors into the decisions it makes. So in the simplest case, you have a file foo found in all three revisions. The two were merging and their common ancestor, and that file foo is the same revision in both the two change sets were merging and their common ancestor. So the obvious thing to do in this case in the merger is just to keep the file in that state. If, however, in the two change sets were merging, a file foo has changed since the common ancestor. This is the one case where Mercurial actually has to merge two versions of a file together. And it actually does so not with code in Mercurial itself, but by invoking an external program. The whatever is the standard merge tool on your system. On most Linux programs these days, as usually a program called Diff3, or a similar one called KDiff3. Diff3 is the most commonly used command line tool for performing merges, and KDiff3 is basically the graphical application equivalent of the command line tool Diff3. Now in the cases where the merge tool can't successfully merge two files without any conflicts, it will then prompt you, the user, to resolve the conflict. So here, for example, in my system is what it looks like when KDiff3 pops up and tells me that I have a conflict to resolve. What you see here in the top two panels are the two original versions of the file, and then in the bottom panel, the wide panel down there, that's the merged version. And you'll notice that in line there's a question mark and a marker of merge conflict. That's a conflict that I need to resolve manually. Once I resolve the conflict, the merge continues. Another possibility in a merge is that the file has been changed in one of the two change sets since the common ancestor, but not the other. In this case, it's that changed version which takes precedence. So in the merger, you will have the changed version, not the unchanged version. Because again, the general presumption in mergers is that you want as many of the changes as possible. In another case, it's possible that in one of the change sets you have actually removed the file, whereas in the other, it has remained untouched. And again, the removal of the file is considered a kind of change, so again, we take the change. So that file is not present in the merger. And in the last case, we'll consider, you might have in one of the change sets, the file's been removed, but in the other, it's been modified. In this case, it's left up for the user to resolve. They're prompted and asked, should the file be deleted, or should the merger take the version that was modified? Because numbered names are not terribly friendly, you can elect to give change sets in Mercurial branch names and tags. The main differences between the two being that first, the branch name is an immutable property of a change set. Once you create the change set, you can't change the branch name. Second, branch names need not be unique. That is, multiple change sets within the same repo can have the same branch name. And third, each change set has one and only one branch name. Tags, in contrast, are mutable properties of change sets. They're stored within the repo separate from the change sets themselves, and that allows them to be modified. And whereas a branch name can be shared by multiple change sets, the same is not the true of a tag. A tag within a repo is meant to only apply to just one revision. And lastly, tags are optional, so change sets need not have any tags at all, but unlike with branches, you can give a single change set multiple tags. So, we'll look at an example of branch names first because they're considerably easier to understand than tags. First off, where does a change set's branch name come from? Well, the branch name is either inherited from the parent change set, or it is explicitly set for that change set by the hgbranch command. That is, before you actually make your commit, you set in the working directory the branch name with the command hgbranch. And then when you make your commit, it will have that branch name. The null change set has the branch name default. So, when you make the first commit in the repo, assuming you haven't explicitly set the branch name to something else, the first commit will inherit the branch name default from the null change set. And in fact, if you don't ever bother changing the branch name to something other than default, then effectively all subsequent change sets will inherit default as their branch name. So, in that sense, default is the default branch name. And in fact, when listing a change set, Mercurial will not report the branch name unless it's something other than default. So, if a branch name isn't listed for some change set, you know that its branch name is default. So, here in this example, we have five change sets, three of which have the branch name default, and two of which have the branch name feature x, which presumably denotes a branch in which the coder was working on feature x. Of course, in a real example, you'd have an actual name for the feature. But in any case, just looking at the history here, we can infer how these branch names were set. The earliest change set here was 124, which has the branch name default presumably inherited ultimately from the null change set. So, this is probably the mainline branch of development. And then someone decided that they're going to work on a new feature in a new branch. So, they used the hd branch command to set the branch name of the working directory to feature x, and then they made their commit that created change set 125. And based off of that head, they continued their work on feature x and made another commit. Meanwhile, either the same coder or some other coder working on the same code, starting from an update to change set 124, they made a new commit continuing that branch with change set 126. So, in both the case of 126 and 127, the committer didn't have to set the branch name with the hd branch command. It was just inherited from the parent. Finally, the last change set here, 128, is a merger of 126 and 127. Effectively, we're merging the work we did on feature x back into the mainline of development, back into default. And the way this was done most likely is with the working directory updated to revision 126. A merge was done with revision 127, and then after resolving all the conflicts, revision 128 was committed. Now the question is, why does revision 128 have the branch name default? Well, in a merger, as I mentioned briefly before, there's one small respect in which a merger is not commutative. That is, it matters whether we're merging from 126 to 127, or from 127 to 126. And that is that the branch name is inherited from the first parent, the one which is the parent of the working directory we're merging into, not the other parent, not the other change set which we merged with. So, because the working directory was updated to revision 126, and we merged from there with 127, the inherited branch name is the one from revision 126 default. Though, of course, we could have just explicitly set the branch name with hg branch to whatever we want, whether default, feature x, or something else entirely. In this case though, because the idea is to bring the changes of feature x into our mainline of development into default, it makes most sense just to do it this way, to from default merge in that other branch. So, to demonstrate this on the command line, let's pick up where we left off, where we made our merger, but we didn't actually commit it. So, before committing it though, let's actually explicitly set the branch name. So, we do so with hg branch, and then in the quote marks, the best branch ever, that's the name of our branch. Be clear though that the branch command doesn't actually create the branch, it's just setting the branch name for the next commit. The change set doesn't actually get created until hg commit in the next line. And then after the commit, we use hg parents to confirm that yes, a new change set was just created. Notice it reports the branch name, the best branch ever, and also it shows that this has two parents, not just one, because this change set is the result of a merger. So, that's pretty much everything there is to know about branch names. Whether you end up actually using them, that's a matter of preference. Some people like to use them, some people just don't bother. It's really just an organizational tool. And as far as convenience, all it really buys you is that when you specify a revision in a command, usually with the option hyphen r, rather than provide a local revision number or a change set ID, you can refer to a change set by its branch name. And the change set which a branch name refers to is the tip most change set with that branch name. And some users find that pretty convenient. And the same can be said of tags. Once we give tags to our change sets, you can then refer to that change set by the tag name. Though in that case, you never have more than one change set with the same tag, that's the whole point of tags, is that they uniquely apply to one change set. So now, how do tags work? Well, tags in your repo are stored in a single file. They're not stored with the change sets themselves. They're stored in a file in the working directory called .hgtags. So be clear, in your repository foo, .hgtags isn't stored in the .hg subdirectory. It's stored in the directory foo itself with all the other files of your working directory. In fact, you can almost get away with treating this .hgtags like any other file in your working directory. You can create it yourself and edit it yourself, and you can add it to the manifest with the .hgtag command and so forth. The format of .hgtags is simply that every line starts with a change set ID, the full 40-digit change set ID, not the 12-digit short form, followed by a space, and then the tag name. So we see in this example here five different tags. The first, the tag demo release. The second, tag v0.1. The third with the name v0.2 space alpha. And then the last two also have in the name demo release. Now, I did say that tags in a repo are meant to be unique. You can't have the same tag name applied to multiple change sets. So what happens when you have a conflict is that the last takes precedence. So here the tag demo release is applied to the change set 7D8CC6072. It's that last one. That overrides the two tags of the same name above it. Now, the reason you would have the tag name written on multiple lines like this is that as the .hgtags file is revised from change set to change set, you're not supposed to edit or remove any existing lines. You only edit the file by appending new lines. Otherwise, Mercurial can get confused about what tags are supposed to apply to what change sets. And this really is the most confusing aspect about tags. You would think in a Mercurial command, when you specify some change set by a tag name, a tag which is applied to that change set, that Mercurial would look up the tag name in the current version of .hgtags. That is whatever version is currently in your working directory. But that's not how it works. The current set of tags in effect in your repository is not determined by whichever change set you've updated to in your working directory. Rather, it is determined by the state of the .hgtags file in the current head in the repository. And most confusingly, in the case where your repository has multiple heads at the moment, then the current set of tags is an amalgam of the content of .hgtags in all of those heads. And this amalgamation of the .hgtags files in the heads is similar to how a merge works, but not exactly the same. We won't go over the details here. Just remember that the odd thing about tags is that the current set of tags in effect is determined by not the content of .hgtags in your working directory, but rather by the heads in the repo. So, in fact, this has the odd consequence that if you manually edit .hgtags, if you append new lines, those tags won't be visible. They won't be known to the repo until you actually make a commit with those changes to .hgtags. Now, while you generally can get away with manually creating and editing the .hgtags files, usual practice is to create and edit the file indirectly by using the .hgtag command, and the unintuitive thing about the .hgtag command is that it not only appends a new line to .hgtags, but it then commits the file, because if it didn't, that new tag wouldn't be in effect. It would only be a line in the file. It wouldn't be a tag name you could actually use in your commands. Some people find this very objectionable about the tag system because it means anytime you make a new tag or modify an existing tag, a new change set is committed, and some people don't like how that clutters in repositories. Anyway, in demonstrating the tag command, we'll also use the tags command, note the difference, which doesn't actually create any tags or modify any existing tags. It simply just lists the set of tags currently in effect in your repository. So if you're wondering what tag refers to what revision currently, the tags command will tell you. You may have noticed in change sets we've seen previously that some of them report a line that says, tip is a special tag which is always automatically set to refer to the tip change set. That is the head in the repo with the highest revision number. That's always the tip. So here, when I try to use the hgt tag command to apply the tag tip to the current parent of the working directory, we get the Sarah Masters saying abort, the name tip is reserved. So we can't use tip as a tag name, nor in fact as a bookmark name. So we can use the hgt tag to apply the tag release space v3.4 to revision 359 and note that if I didn't specify a revision number it would default to the current parent of the working directory. Then immediately after the tag command if we look at the log, you'll notice that it actually has created a new change set 360. So the tag command not only appended to .httags, it actually made a new commit. And now you can see below in change set 359 release space v3.4. By the way, in the log command we specified the option hyphen l space 2 meaning show just the last two revisions. If I didn't use that option and I just wrote hglog it would print out all 361 change sets. And then at the bottom here we invoke hgt tags to report what the current tags are. There's the tip which will always be there but also now it reports that the tag release space v3.4 applies to revision 359. Now when using the hgt tag command to modify an existing tag that is to set the tag to refer to some other change set rather than the one it currently refers to you'll get an error message saying that the tag of that name already exists and if you really want to modify the tag then you have to invoke tag with the f option meaning force. The reason for this is really just to prevent you from accidentally modifying some existing tag. It's effectively asking for confirmation that you know you're actually modifying some existing tag not creating a new one.