📜 ⬆️ ⬇️

Comparing Subversion and Mercurial (HG)

My first acquaintance with the version control system was still at school. It was Subversion. At that time, I was very impressed with his strength and capabilities. But time passed. There were not very pleasant moments with the renaming of files, directories, etc. (yes, long live svn 1.5, 1.6 and its perpetual .svn folders). And everything would have continued in the same spirit if one day the company had not thought about changing the version control system. Everything happened unexpectedly quickly and Mercurial appeared before me. I had to read about its features, ask around for tips from experienced ones, and now I myself have helped my colleagues to understand the behavior and work of the new tool. The longer I became acquainted with Hg, the more I liked it, more precisely, I liked its decentralized approach to version control, Subversion inevitably faded into the background.
However, at the new place of work, I again had to recall Subversion, which, to be honest, did not make me happy. Fortunately, this was not the company's unconditional policy and it was quite realistic to offer an alternative, especially considering that some employees preferred Git and work with it successfully. It means that it’s easy to show clearly what are the advantages of working with decentralized version control systems: Git or Mercurial, but, due to my personal experience, I decided to tell about Hg. Actually, this article is a summary of the round table that I conducted in order to compare and change the version control system.


There are many opinions about which version control system is better. Of course, every opinion has its own arguments for and against. However, to take at least the simplest scenario: 2 or more people work on the project, and the project involves further support and development, say, as a library, then storing it in svn will cause you much more trouble than storing in Mercurial.
Let us turn to the specific features that distinguish Mercurial from the rest.

1. Unlike svn commit, with the hg push command you will always find out if someone managed to change something in the project and recorded these changes on the server.
')
svn commit - a command to send local changes to a remote server. Occurs atomic. In this case, it fails only if the version on which the modified files are based is no longer the last one on the remote server. That is, if there are two a.txt and b.txt files in the directory and you changed only b.txt, and Petya only a.txt file, the commit command will complete for you successfully and if you do not execute the svn update command (update all files in directories to the latest version), you will not know about it. Also, svn supports commit (and checkout) from any project folder. Because of this, if you commit in one folder, you will not find out about changes in another.

hg push is a command to send change sets that were made earlier with the hg commit command. The last command captures the current state of the repository, but does it completely locally. Only when making the hg push command - changes are sent to the remote server. Since this is a command for sending changes, it extends entirely to the entire repository. Thus, with this command, the entire state of the repository will be fully recorded. And if someone managed to push before you, then this situation is treated as a multi-sided one and by default hg push ends with an error that says your action will make a new head (head) in the remote storage.
For completeness, we give the definition of the head (head). This is a revision that is not itself the parent of any other revision in this brunch. A multihead is a situation where there is more than one head in one brunch.
Let's return to our situation when someone is ahead of us. After returning the error, we need to make the hg pull command, which will delay all the missing revisions to our local storage. Again, it is worth noting that this action will not affect our files in any way. None of them will be changed. This command simply adds to the history list of changes that we did not have. Thus, if we look at the visualization of the current situation in the repository, we will see that we have a multihead. Multihead in the local storage is not scary. After all, we did it ourselves. It is much more dangerous if we create the same situation at a remote repository and someone has time to incline him to himself. This person will not be able to understand which version is the most relevant and how to work with them. He will begin to run, shout and swear that all this is too difficult and incomprehensible. Therefore, in no case can we do a push in the current state (Mercurial will only allow us to do this using the hg push --force command, which is better never to do). So we have to merge two heads and get one that Mercurial can safely upload to the remote server.

And now why this could be important. If for some reason another developer changed some common component (logic, interface, or something else), but you didn’t know about it, then in the case of svn, the remote repository may turn out to be incorrect or even non-compiled code. In this case, the first such cant can be detected quite quickly (we still do svn update from time to time and start the compilation, isn’t it?), But the detection of another cant can be delayed until the tests. The logic of the work of Mercurial allows you to immediately find out about the change and do all the checks immediately with merge. Of course, if you didn’t ask what was changed in parallel with your work, then you risk getting into the same situation as with svn, but with one difference - in the first case you didn’t even know about this, and in the second you scored .
It can be argued that if a person does not make the svn update command before the svn commit command and does not check the code, then he himself is guilty and there is no plus here, but this is an erroneous opinion. A bunch of update / commit commands in svn is not atomic, and hg push is an atomic operation, which greatly simplifies life.

2. With the pull commands, merge you do not lose your state, which you have not yet managed to transfer to a remote server, unlike svn update.

This has already been mentioned - with pull you simply get a set of previously unknown changes to the history without changing the files. And since merge in Mercurial is done locally and with local revisions, these revisions are not lost anywhere. And if you want, you can always delete the result of merge and make it anew, or completely roll back to the version of the repository that was before all pull / merge. In svn, this is unrealistic. After executing svn update from your working copy, you get a hodgepodge of unchanged, new, automatically deleted files, files with conflicts, and the usual files you modified. At the same time, it is impossible to return to the repository the state that you had before svn update. No

3. Another small bun - roll back to any version of the repository in Mercurial in seconds. The only limitation is that your local copy must be clean (without uncommitted changes). This can be done using hg update and specifying the desired revision. It does not require a connection to a remote server, because you have all the history locally. In svn, this can be done only with a remote server and only by pumping out the repository again in the required revision.

4. It often happens that you need to urgently do something with the application. For example, they come running to you and urgently want to get a build (since I am engaged in mobile development, it happens, although there is a build server). And your project is completely collapsed, as you are sawing some super feature. In svn, you would either have to re-download all the sorti from the last revision, or try to roll back the code to a more or less working state, or say that you cannot do it now. All options are so-so and usually take a lot of time. In any decentralized version control system, you can make a local commit, then roll back to any working version of the code and build the project. At the same time, after this, you will return exactly to the state of the repository in which you were before you were disturbed!

5. Another frequent occurrence is the development of a library project. And if you were unexpectedly asked to build a project that was written for a long time and used the library that was connected to svn external, then you may have big problems. He may simply not gather, as he used the old library, which they managed to rewrite, reborn, and so on. The only way out would be to look for the audit with which this project worked, and copy-paste the library. We do not consider the variant with a small doping of the project to support the new version of the library, since the probability of such a possibility decreases exponentially with time. In Mercurial, there is a concept of a sub repository that refers not only to the repository itself, but also to its specific version. Thus, you always know with what version of the library the project is running and you can not be afraid of its changes.

6. I have already mentioned the branch in hg. It is worth recalling how branches are implemented in svn. These are just folders with a full copy of the repository. Starting with version 1.5, the history of such files has appeared, but still they are just folders and files. To work with them you need to adhere to special rules for naming and content. In mercurial, the same branch is the named state of the repository and its changes. And when working with branches, everything is exactly the same as when working in one branch. It is much easier.

7. Similar to clause 6, we can talk about tags.

8. Finally, I want to say about the history of commits. If it is purely straightforward in svn and it’s impossible to say that you were actually based on revision 2, not 10, and didn’t know what was going on from 3 to 10, although your commit should be number 11 ... In Mercurial you will see clearly that you worked with the repository of version 2 and made a commit 3 'and only after that you made your changes 3' with revision 10. Such data is important if you want to trace some important events.

Summing up the article, I want to note that for all the time I work with Mercurial, I cannot name its minuses. Some sin on his speed, some on commit / push commands to commit changes to the server. For me, this is not a problem, since I did not notice any special delays in speed (they were, of course, with huge repository sizes, but these are little things in life), and the second is a matter of habit.

In general, some of the listed benefits of Mercurial can be transferred to other decentralized version control systems. And with this article I would just like to gather all the main advantages of using such systems, relying on Mercurial, as an example with which I myself had experience. I hope this article will be useful if you have to experience the torment of choice.

ps As a result, we decided to switch to Git =)

Source: https://habr.com/ru/post/177451/


All Articles