I'm teaching HG to my students, as it is a good playskool DVCS (not powerful as GIT but simple to start working with trivial concepts). I use HG because it seems very difficult to destroy previous entries (with the exception of hg rollback
), so you have always a chance to get back on train without destroying important data. But i was recently wondering:
rebase
option which can be very dangerous)Both are DVCSs, meaning that you’re supposed to clone the repo and push your changes somewhere when you want a backup copy. If you do this diligently, then it becomes irrelevant which destructive tools are available to you, since backups are cheap and easy to maintain.
Now, be warned that I’m a 100% biased Git bigot.
Out of the box, Mercurial only ships with one destructive command, rollback. Everything else is relegated to extensions which must be manually enabled — strip, rebase, etc. These extensions are most certainly destructive in that they rewrite history in-place, or they destroy it. To avoid using these, most Mercurial users prefer to use the Mercurial Queues extension, which lets you maintain changesets as flexible patches before setting them in stone as commits. This essentially amounts to an entire VCS which sits on top of Mercurial. It gets the job done, but it must be consciously applied before the commits are written.
By contrast, Git ships with several commands that may be considered “destructive”, but with one crucial difference — nothing inside Git’s database is ever rewritten. Whenever you use the rebase, filter-branch, or reset commands, new objects are created in the database, and then the branch pointer is updated to point to these. Every time a branch pointer is updated, an entry is appended to its reflog, a history log which sits on top of Git and protects your branch pointers from unwanted updates; it’s always possible to revert a “destructive” command. It can be difficult, in fact, to permanently remove an object from Git’s database — it involves dropping the reflog entry and then pruning the unref’d objects.
In short:
For your use case of teaching, these differences are generally irrelevant anyway — you’ll be teaching the basic commands, and if someone wants to explore, the only way they’ll learn is by chainsawing their arm off. It is said that Mercurial is easier for beginners to learn, but I feel that that’s mostly because it doesn’t expose the index and so is more like Subversion. Complete neophytes to version control might not benefit from this similarity.
I don't think 'playskool' is a good term to describe Mercurial. It's a major, full featured DVCS used by Python, OpenOffice, Netbeans, and many more projects. 'Playskool' implies that it's not ready for production-level use, or that it's a watered down version of something else. Both untrue. Try not to confuse usability with simplicity or insignificance.
Several members have mentioned that by default Hg doesn't come with extensions installed, but because extensions are so easy to install, it might be worth knowing which ones can cause some "damage". Of course, even if damage is caused, the distributed nature of Hg would allow you to strip offending changesets and re-pull from a centralized server (kind of like cutting off and re-growing a limb when you think about it).
I would also differentiate between Damage (repository corruption or data loss) and Danger (HG pitfall or unwise action - no data loss).
Damage: Using rebase could cause severe merge conflicts if you're trying to rebase from revA to revB and they are significantly different. In these cases, Mercurial will generate .diff files that let you handle the failed merges yourself. If this occurs, merging can be complex and data could be lost.
Danger: rebase changes the hash ID of each changeset it moves, which means it should not be used once a changeset has been pushed. Also, rebase will apply changesets to the default branch unless you specify otherwise with --keep-branches
Damage: Although mq is probably a better extension, histedit can still be used to rearrange, modify, or otherwise edit existing changesets. Using edit
allows any user modification of the revision, including reverting all changes. Using drop
allows changesets to be removed completely. Both of these operations can result in data loss.
Danger: similar to rebase, histedit can modify the hash ID of a changeset.
Damage: Mq is a very powerful and multi-faceted feature, so damage that can be caused by it is varied. mq strip
is an easy example of potential data loss.
Danger: again, causes ID changes.
As you mentioned, this operation can cause some damage. The help text says it best:
This command should be used with care. There is only one level of rollback, and there is no way to undo a rollback. It will also restore the dirstate at the time of the last transaction, losing any dirstate changes since that time.
Making a safety clone before using any of these options should allow you to overcome even catastrophic damage. Rely on the fact that Hg is a DVCS to ensure you always have a copy of the repository before trying anything crazy!
Since the repo is local, you can easily destroy the repo by doing things to the files directly. So destroying entries is, per se, not difficult.
However, using commands, it pretty much boils down to which extensions you enable in Mercurial. For instance strip
is quite "dangerous", and it is enabled whenever you choose to use the mq
extension.
From a technical pont of view, both Git and hg by default don't change data which has been written in the past. hg always only appends data to files, and Git has its internal data representation which is persisted in files which don't change after being written.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With