Mercurial … what happened to you?

Mercurial used to be the VCS that I looked to for several reasons. You can easily clone locally or to a server with the only prerequisite being a remote hg binary and SSH. Also, Mercurial wouldn’t get upset with you if you pushed to a remote (“local”) repo, because that had a worktree checked out, like Git does. Instead Mercurial keeps push as the opposite of what fetch is in the Git world.

If you think hard enough you’ll notice that Git is lacking anything like this. It has pull and fetch, but nothing that is the counterpart to fetch on the outgoing end …

And the arguments for why this is the case are spurious at best. But hey, Git has won.

But now I realized it actually has won, because Mercurial made a fatal, flawed decision some years ago with the Python 3 migration. Instead of introducing a new repository format version and then — perhaps as extension — offering a migration path between the repo format versions, they decided that the pre-Windows-NT 1 encoding would be the correct path forward. At least twenty years after NT 4.0 got released.

Picture this: because existing repos would need the Windows encoding for path names (the infamous A APIs, like CreateFileA) or break, they decided to cement this mis-design for future versions. This will make it very hard to fix it going forward.

Also all arguments about why Mercurial cannot possibly care about path encodings are ridiculous at best.

Again, the repo format version would have been the savior and this would certainly have been the lever to pull.

Mercurial supports arbitrary raw bytes for path names. Well, does it? Nope it does not! Neither does Linux or other Unixes. Heck even if we ignore the practicality of using weird path names from a shell on Unix, there are limitations to “arbitrary” based on the file system. Admittedly fewer as far as the allowed set of characters is concerned, but conversely a lot more when the length of a path segment or the overall path length is concerned. Or in other words, the argument is hogwash. And it doesn’t at all invalidate the fact that a “portable repo” — one that is usable from different systems — needs to take into account the common denominator regarding limitations.

Mercurial started out brilliantly. For example you will notice that in its internal store it would keep the uppercase/lowercase of file names encoded. Which sort of suggests that it cares to some extent about paths beyond them as arbitrary raw bytes.

I like to point to this internal encoding all the time when people first encounter the weirdness that is Git: branch names are files/directories and they have the exact same limitations.

And before people come claiming Windows doesn’t do case-sensitive: that’s hogwash as well. NT has always handled case-sensitivity fine, especially with NTFS, but the Win32 personality has disabled case-sensitivity for the API layer 2. But even Linux has had support for FAT and other file systems which are inherently case-insensitive (unlike NTFS). So there’s literally no reason other than ignorance — when coming from the Unix side of things — to claim case-insensitivity is some sort of outlandish and undesirable file system behavior.

What is outlandish and undesirable is how Git handles branches. But then they have long advertised with git --everything-is-local … hell yeah, even branches. That’s why Mercurial calls local tags bookmarks. Try getting a proper, faithful, mirror of a Git repo in either direction and I’ll welcome you on the other side of a sea of pain …

So in a sense Mercurial used to be the VCS what didn’t treat Windows like an afterthought. Or so it appeared at first. While with Git you had to go through hoops for many years, including building it from scratch and ideally not forgetting to clean those two-odd GiB of object files afterward, Mercurial was thought as a more portable system.

With the aforementioned decision, I think they have demonstrated that they don’t care about people on Windows. And mind you: I only develop some private projects on Windows and otherwise only have to use it at work. But pretending you can ignore Windows for this sort of tool?! Sorry, folks, news flash: that’s an ignorant and stupid thing to do.

The door probably isn’t shut for good. In theory it’d be possible to reopen it by leveraging the repo format version. But I am not sure if it’s worth it. I loved TortoiseHg and “blame” it to an extent for “the victory of Git”. TortoiseHg was such a brilliant interface that something like GitHub was never originally needed. For Git there was always this lack of the ability to clone to a remote repo 3 that hadn’t been initialized already on the remote end. This required the need for GitHub and similar code forges. The rest is history, as they say. The Mercurial ecosystem didn’t have that need. TortoiseHg was good enough. Cloning to a remote including creation of the remote repo was never a problem in the first place.

I still think Git has many many shortcomings and people ignore them or work around them with cures that are worse than the sickness they purport to address 4. Although, admittedly, I haven’t seen anything that does “submodules” or something like it Right™. But Git LFS? Yeah, the L stands for binary, as is common knowledge. And while deltas can be an issue for large files, I question that files are coerced into LFS — for which there exists no exit path other than completely rewriting repo history all over — on account of being binary and of laughable sizes like a handful of MiB. Sure, hundreds of MiB we might want to think about alternatives, but then the question becomes: do we need all operations on these files in the first place? If not, why waste the effort?

Anyway, I am very disappointed by Mercurial right now 5 and need to see whether that changes my stance regarding it. Certainly a bare local Git repo suddenly sounds a lot sexier when compared to the issues Mercurial will not even address.

// Oliver

PS: Git doesn’t officially track path names. Except it does … somewhat. And in a similar fashion. So how do they sidestep the issue? Easy: MSYS2 is the translation layer based on Cygwin which presents a unixoid API to the Git side and uses the “wide” APIs (i.e. the UTF-16-enabled APIs) on the Windows side. That’s why it works effortlessly there, because UTF-8 and UTF-16 are losslessly interchangeable for the most part …

  1. … and no it’s not always identical to ANSI, it’s a variant thereof[↩]
  2. meaning there’s case-folding going on when accessing paths[↩]
  3. to this very day and for no good reason![↩]
  4. Git LFS … submodules …[↩]
  5. Probably TortoiseHg sticking for long to Python 2.x exacerbated the issue and hid the problem for which now there isn’t even any workaround any longer like the original fix-utf8 extension.[↩]
This entry was posted in EN, Opinion, Rant, Software, VCS and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *