An in-depth analysis of Mercurial and Git branches

I’ve discussed the advantages of Git over Mercurial many times (e.g. here, and here), and I even created a challenge for Mercurial supporters, but in this blog post I’ll try to refrain from doing judgments and concentrate on the actual facts (the key-word being try).

Continuing this full disclosure; I’ve never actually used Mercurial, at least on a day-to-day basis, where I actually had to get something done. But I’ve used it plenty of times testing many different things, precisely to find out how to do things that I can do easily in Git. In addition, I’ve looked deep into the code to figure out how to overcome some of what I considered limitations of the design. And finally, I wrote Git’s official GitMercurial bridge; git-remote-hg (more here).

So, because I’ve spent months figuring out how to achieve certain things in Mercurial, and after talking with the best and the brightest (Git, gitifyhg, hg-git, and Mercurial developers), and exploring the code myself, I can say with a good degree of confidence that if I claim something cannot be done in Mercurial, that’s probably the case. In fact, I invited people from the #mercurial IRC channel in Freenode to review this article, and I invite everyone to comment down below if you think there’s any mistake (comments are welcome).

Git vs. Mercurial branches

Now, I’ve explained before why I think the only real difference between Git and Mercurial is how they handle branches. Basically; Git branches are all-purpose, all-terrain, and Mercurial have different tools for different purposes, and can almost do as much as Git branches, but not quite.

I thought the only real limitation was that Mercurial branches (or rather bookmarks), didn’t nave a per-repository namespace. For example: in Git the branch “development” can be in different repositories, and point to different commits, and to visualize them, you can refer to “max/development” (Max’s development branch), “sarah/development” (Sarah’s), “origin/development” (The central repository version), “development” (your own version). In Mercurial you only have “development”, and that’s it. I consider that a limitation of Mercurial, but feel free to consider it a “difference”. But it turns out there’s more.

In Git, it’s easy to add, remove, rename, and move branches. In Mercurial, bookmarks are supposed to work like Git branches, however, they don’t change the basics of how Mercurial works, and in Mercurial it doesn’t matter if you have a bookmark or not pointing to a commit, it’s still there, and completely visible; in Mercurial, each branch can have multiple “heads”, it doesn’t matter if there’s a bookmark pointing to it or not. So in order to remove a bookmark (and its commits), you need to use “hg strip” command, and to use that command, you need to enable the MqExtension, however, that’s for local repositories, for remote ones you need to cross your fingers, and hope your server has a way to do that — Bitbucket does through its web UI, but it’s possible that there is just no way.

Mercurial advocates often repeat the mantra “history is sacred”, and Mercurial’s documentation attempts to explain why changing history is hard, that shows why it’s hard to remove bookmarks (and it’s commits); it’s just Mercurial’s design.

On the other hand, if you want to remove a branch in git; you can just do “git push :feature-a“. Whether “history is sacred” or not is left for each project to decide.

Solving divergence

In any version control system, divergence is bound to happen, and in distributed ones, even more. Mercurial and Git solve this problem in very different ways, lets see how by looking at a very simple divergent repository:

Diverged

As you can see we have a “Fix” in our local branch, but somebody already did an “Update” to this branch in the remote repository. Both Mercurial and Git would barf when you try to push this “Fix” commit, but lets see how to solve it in each.

In Git this problem is called a “non fast-forward” push, which means that “Fix” is not an ancestor of the tip of the branch (“Update”), so the branch cannot be fast-forwarded to “Fix”. There are three options: 1) force the push (git push --force), which basically means override “origin/master” to point to “master”, which effectively dumps “Update” 2) merge “Update” and “Fix” and then push 3) rebase “Fix” on top of “Update” and then push. Obviously dropping commits is not a good idea, so either a merge or a rebase are recommended, and both would create a new commit that can be fast-forwarded from “Update”.

In Mercurial, the problem is called “multiple heads”. In Git “origin/master” and “master” are two different branches, but in Mercurial, they are two heads of the same branch. To solve the problem, you can start by running “hg heads“, which will show you all the heads of all the branches, in this case “Fix” and “Update” would be the heads of the “default” branch (aka. “master”). Then you have also three options: 1) force the push (hg push --force), although in appearance it looks the same as the Git command, it does something completely different; it pushes the new head to the remote 2) merge and push 3) rebase and push (you need the rebase extension). Once again, the first option is not recommended, because it shifts the burden from one developer to multiple ones. In theory, the developer that is pushing the new commit would know how to resolve the conflicts in case they arise, so (s)he is the one that should resolve them, and not take the lazy way out and shift the burden to other developers.

Either way solves the problem, but Git uses remote namespaces, which I already shown are useful regardless, and the other requires the concept of multiple heads. That is one reason why the concept of “anonymous heads”, that is used as an example of a feature Mercurial has over Git, is not really needed.

Mercurial bookmarks and the forced push problem

The biggest issue (IMO) I found with Mercurial bookmarks is how to create them in the first place. The issue is subtle, but it affects Git-like workflows, and specially Git<->Mercurial bridges, either way it’s useful to understand Mercurial’s design and behavior.

Suppose you have a very simple repository:

Simple repository

In Git, “feature-a” is a branch, and you can just push it without problems. In Mercurial, if “feature-a” is a bookmark, you can’t just push it, because if you do, the “default” branch would have two heads. To push this new bookmark, you need to do “hg push --force“. However, this only happens if the commit “Update” is made, also, you can push “feature-a” if it points to “Init”, and after pushing the bookmark, you can update it to include the “Feature A” commit. The end result is the same, but Mercurial barfs if you try to push the bookmarks and the commits at the same time, and there’s an update on the branch.

There’s no real reason why this happens, it’s probably baggage from the fact that Mercurial bookmarks are not an integral part of the design, and in fact began as an extension that was merged to the core in v1.8.

To workaround this problem in git-remote-hg, I wrote my own simplified version of the push() method that ignores checks for new heads, because in Git there cannot be more than one head per branch. The code still checks that the remote commit of this branch is an ancestor of the new one, if not, you would need to do ‘git push –force’, just like in Git. Essentially, you get exactly the same behavior of Git branches, with Mercurial bookmarks.

Fixing Git

All right, I’m done trying to avoid judgement, but to try to be fair, I’ll start by mentioning the one (and only one) feature that Git lacks in comparison to Mercurial; find the branch-point of a branch, that is; the point where a branch was created (or rebased onto). It is trivial to figure that out visually, and there are scripts that do a pretty good job of finding that out from the topology of the repository, but there are always corner-cases where this doesn’t work. For more details on the problem and proposed solutions check the stackoverflow question.

Personally I’ve never needed this, but if you absolutely need this, it’s easy to patch Git, I wrote a few patches that implement this:

https://github.com/felipec/git/commits/fc/base

This implements the @{tail} notation, which is similar to the official @{upstream} notation, so you can do something like “development@{tail}”, which will point to the first commit the “development” branch was created on.

If this was really needed, the patches could be merged to upstream Git, but really, it’s not.

Fixing Mercurial

On the other hand fixing Mercurial wouldn’t be that easy:

  1. Support remote ‘hg strip’. Just like Git can easily delete remote commits, Mercurial should be able to.
  2. Support remote namespaces for bookmarks. Begin able to see where “sarah/development” points to, is an invaluable feature.
  3. Improve bookmark creation. So the user doesn’t need to force the push depending on the circumstances

Thanks to git-remote-hg, you can resolve 2) and 3) by using Git to work with Mercurial repositories, unfortunately, there’s nothing anybody can do for 1), it’s something that has to be fixed in Mercurial’s core.

Conclusion

I often hear people say that what you can achieve with Git, you can achieve with Mercurial, and vice versa, and at the end of the day it’s a matter of preference, but that’s not true. Hopefully after reading this blog post, you are able to distinguish what can and cannot be done in each tool.

And again, as usual, all comments are welcome, so if you see a mistake in the article, by all means point it out.

Cheers.

Advertisements

What it takes to improve Git or: How I fixed zsh completion

I’ve used Git since pretty much day one, and I use it all the time, so it’s important to me that it’s easy to type Git commands quickly and efficiently. I use zsh, which I believe is way superior to bash, unfortunately I found many issues with its Git completion.

In this blog post I will try to guide you through the ordeal from how I identified a problem, and how I ended up fixing it years after, for everyone’s benefit.

The issue

I work on the Linux (kernel) source tree from time to time, and I noticed that sometimes completion took a long, looong time. Specifically, I found that typing ‘git show v’ took several seconds to complete.

I decided to bring that issue up to the zsh developers, and it caused a lot of fuzz. I won’t go to every detail of the discussion, but long story short; they were not going to fix the issue because of their uncompromising principles; correctness over functionality, even if very few people use that correctness, and the functionality is almost completely broken to the point the completion is not usable in certain cases. I argued that completion is meant to make typing commands more efficient, and if completing a command takes longer than what it would have taken me to type it manually, the completion is failing its purpose. I thought any sane person would see the problem with that, but apparently I was wrong (or was I?).

Fortunately zsh has bash completion emulation, so it’s possible to use Git’s official bash completion in zsh. You loose some of the features of zsh completion, but it works very efficiently (‘git show v’ was instantaneous).

Unfortunately, zsh’s bash emulation, and zsh’ bash completion emulation (two different things), are not perfect, so some workarounds were needed in Git’s bash completion script, and those workarounds were not working properly by the time I started to use such completion, so that’s when my involvement begin.

Fixing the bridge

Each time I found a bug, I tried to fix it in Git (patch), and made sure that zsh folks fixed in their side too (commit), so eventually no workarounds would be needed, and everything would work correctly.

The completion worked for the most part, but with workarounds, and not exactly as good as bash’s. So I decided to fix zsh’s bash completion emulation once and for all. After my patches were applied by zsh developers, Git’s official completion worked much closer to how it did in bash, but there were still minor issues.

Moreover, Git’s bash completion was constantly changing, and it was only a matter of time before one change broke zsh’s completion, so I decided to get involved, understand the code and simplify it to minimize the possibility (e.g. d79f81a, 583e4d5). I saw a lot of areas of improvement, but in order to make sure nothing got broken in the process of simplification, I thought it would make sense to have some tests (5c293a6). Git’s testing framework is one of the most powerful and simple there is, so it was a pleasure to write those tests. Eventually the completion tests were good enough that I became confident in changing a lot of the completion code.

At the same time I realized most of zsh’s bash completion emulation code was not needed at all, so I wrote a very small version of it that only worked with Git’s completion. The result was very simple, and it worked perfectly, yet it could be even simpler, if only I could simplify Git’s completion even more.

The culmination of that work was the creation of __git_complete (6b179ad), a helper that has nothing to do with zsh, but it solved a long standing problem with Git completion and aliases. It’s not worth going into details about what was the problem, and why it received so much push-back from Git developers (mostly because of naming issues), what is important is that I implemented it with a wrapper function, a wrapper function that was *exactly* what my zsh simple completion wrapper needed.

Now that everything was in place, the final wrapper script ended up very small and simple (c940786), it didn’t have any of the bugs zsh’s bash completion emulation had, and was under full control of the Git project, so it could be improved later on.

Finally. I had Git completion in zsh that worked *perfectly*; it worked exactly the same as it did on bash. But that was not enough.

Now that Git completion worked just like in bash, it was time to implement some extras. zsh completion is extremely powerful, and does things bash cannot even dream of doing, and with my custom wrapper, it was possible to have the best of both worlds, and that’s exactly what I decided to do (4911589).

git-zsh-shot

Finally

So there it is, after years of work, several hundreds of mails, tons of patches through different iterations… Git now has nice zsh completion that not only works as efficiently as in bash without any difference, but in fact it even has more features.

If you want to give it a try, just follow the instructions: contrib/completion/git-completion.zsh

ūüėČ

Felipe Contreras (54):
      git-completion: fix regression in zsh support
      git-completion: workaround zsh COMPREPLY bug
      completion: work around zsh option propagation bug
      completion: use ls -1 instead of rolling a loop to do that ourselves
      completion: simplify __gitcomp and __gitcomp_nl implementations
      tests: add initial bash completion tests
      completion: simplify __gitcomp_1
      completion: simplify by using $prev
      completion: add missing general options
      completion: simplify __git_complete_revlist_file
      completion: add new __git_complete helper
      completion: rename internal helpers _git and _gitk
      completion: add support for backwards compatibility
      completion: remove executable mode
      completion: split __git_ps1 into a separate script
      completion: fix shell expansion of items
      completion: add format-patch options to send-email
      completion: add comment for test_completion()
      completion: standardize final space marker in tests
      completion: simplify tests using test_completion_long()
      completion: consolidate test_completion*() tests
      completion: refactor __gitcomp related tests
      completion: simplify __gitcomp() test helper
      completion: add new zsh completion
      completion: start moving to the new zsh completion
      completion: fix warning for zsh
      completion: add more cherry-pick options
      completion: trivial test improvement
      completion: get rid of empty COMPREPLY assignments
      completion: add new __gitcompadd helper
      completion: add __gitcomp_nl tests
      completion: get rid of compgen
      completion: inline __gitcomp_1 to its sole callsite
      completion: small optimization
      prompt: fix untracked files for zsh
      completion: add file completion tests
      completion: document tilde expansion failure in tests
      completion; remove unuseful comments
      completion: use __gitcompadd for __gitcomp_file
      completion: refactor diff_index wrappers
      completion: refactor __git_complete_index_file()
      completion: add hack to enable file mode in bash < 4
      completion: add space after completed filename
      completion: remove __git_index_file_list_filter()
      completion: add missing format-patch options
      complete: zsh: trivial simplification
      complete: zsh: use zsh completion for the main cmd
      completion: zsh: don't override suffix on _detault
      completion: cleanup zsh wrapper
      completion: synchronize zsh wrapper
      completion: regression fix for zsh
      prompt: fix for simple rebase
      completion: zsh: improve bash script loading
      completion: avoid ls-remote in certain scenarios

The problem with GNOME 3

Since I started using Linux I used GNOME, v1.2 in those times. It has always done what I needed, maybe not perfectly, and not fully, but for the most part. GNOME 3 changed all that.

I complained about GNOME 3 since day one, and I discussed with GNOME 3 developers many problems with their rationale about why what they were doing made sense, and I foresaw many of the problems they are now facing.

I even started the GNOME user survey, in an effort to make GNOME developers see the light.

I blogged once before about GNOME 3, but only superficially, and even then GNOME developers didn’t take it well. Some GNOME developers might be tired of my arguments in Google+ and other media, but it’s time to dive into the issues with GNOME 3 in this blog.

Two years after the first release of GNOME 3, once GNOME developers have had the time to polish the rough edges, it’s time to make the call; GNOME 3 sucks. Here’s why.

The purpose of GNOME

Before we start, we need to clarify the purpose of GNOME, or rather; the purpose of any software project in general, which is to be useful to the users. Your software might the most efficient at doing certain task, it might have the simpler code, and the best development practices, but it’s all for naught if it’s not useful to anybody.

Software has to be useful for other people, otherwise nobody will use your software, and nobody will contribute to your software. Quite likely there will always be other software that does something similar to yours, so you need to convince users that your software is better than the alternatives, usually by providing a good user experience.

Once the user has spent time analyzing the alternatives and has chosen your software, the user expects your software to keep working, and in the same way. If the software keeps changing the way it behaves from one version to the next, it’s not achieving it’s main goal; to be useful to the users. If you do this, your users will move on to another project that might not have as many features, but at least they can rely on it and they don’t have to spend any more of their valuable time learning what broke now in the new release.

More important than providing a good user experience, is to not break existing user expectations.

You would think this is as obvious as a leopard’s spots, yet many software projects, including GNOME, don’t seem to understand this fact.

No project is more important than the users of the project. — Linus Torvalds

What users want

The problems I’ll talk about are not my invention, but conformed by GNOME user surveys, which show the most important issues according to the users:

  1. Lack of configuration options
  2. Developers don’t listen to users
  3. Bring back traditional interface

I knew these were important issues myself before the survey, but a survey was needed in order to know for sure. Of course, even after the survey, GNOME developers reject these issues are important to their users.

Developer attitude

In my opinion the main problem with GNOME is not just the code, code can be fixed, but the attitude from the developers (which is reflected in the code), and as users made it clear in the survey.

Many open source projects would kill to have the user-base GNOME had, and welcome their input with open arms, but GNOME neglected their users, they thought they were irrelevant, and they tried to dismiss their complaints with typical defenses, which of course don’t make sense.

no-feedback

People hate new things

By far the most widely used defense for the changes in GNOME 3 is that some people are backwards, and always hate new things, so it’s no surprise that they hate GNOME 3.

Any rational person would see the problem with this claim, but unfortunately I must spell it, because I had to explain it at great length to GNOME developers, and based on the responses, one would think they are incapable of seeing hasty generalization fallacies.

Say 50% of users hate GNOME 3, how many of them have legitimate reasons, and how many hate it just because they always hate new things? It’s impossible to know. So to dismiss every complaint saying “people hate new things” is totally stupid; you cannot know beforehand if they belong to this group or not, you first need to hear their complaints, and then decide if the complaints are invalid or not.

Saying “Jon doesn’t have legitimate complaints” makes sense (after analyzing his complaints), saying “people hate new things” does not, and GNOME developers do the later when people complain about GNOME 3.

Users don’t know what they want

Really? People don’t know if they want a punch in the face or not? Some people might not know what they want, but they definitely know what they don’t want.

Moreover, that’s a very rudimentary notion of user choice. Malcolm Gladwell explains rather well how it’s true that people don’t know what they want, or rather; they can’t tell you what they want, but when they get a taste of it, they most definitely can tell you: this is what I want.

If it wasn’t clear by now; GNOME 3 is not what a lot of people wanted.

gnome-hate

People complained about GNOME 2 too

Did this actually happen? If you google GNOME 2 for results between 2002 and 2004¬†you would find barely (if any) results that show negative comments, so if it did happen, the backlash probably wasn’t that bad, and it probably died rather quickly. Check the thread in Slashdot, and try to find one comment suggesting to go back to GNOME 1; I couldn’t find any.

Did anybody create forks after GNOME 2 was released the same way people forked after GNOME 3? No.

Yes, people complained about GNOME 2, but not nearly as much as they do about GNOME 3. There’s even an entire wikipedia article dedicated to the controversy over GNOME 3.

 

Sorry GNOME developers, none of your excuses for not listening to your users make sense. You should always listen to your users. Without them your project is nothing.

Configuration

The biggest complaint users had was the lack of configuration options, which could have been solved very easily, if the developers had more than two neurons in their brain, but instead, there’s only sub-par alternatives.

Advanced mode

GNOME 3 got rid of a bunch of useful configurations users relied on, and to defend themselves they said you could use gsettings manually, or install (or write) an extension, and so on, but I argued that there should be an “advanced mode” that the user can optionally turn on in order to further configure the system the way they wanted.

GNOME developers argued that this was a bad idea, because more code would need to be maintained which is absolutely not true for gsettings; the configurations are already there in the code, the only thing missing is the UI. Then they argued that it would mess up the configuration UI, which they wanted to keep clean, but adding a single check box can’t possibly mess with anything. In the end, I never received a single satisfactory answer of why an advanced mode didn’t make sense.

Tweak tool

The tweak tool is the closest thing to a sane configuration interface, however, it should be cleaned up, distributed by default, and integrated in the GNOME control center by adding an “Advanced mode” checkbox that when switched on enables these settings which should be distributed among the different “capplets”.

Even then, the amount of configurations available is not enough.

Shell extensions

Finally, there’s shell extensions which sound like a great idea at first, but if you think about it for thirty seconds, you realize the problem; there’s no APIs for extensions. This means extensions bring many problems.

First, there’s no guarantee that an extension will work the next version of GNOME, because it’s modifying the JavaScript code directly, and there’s no guarantee that the code will remain the same. There’s no extension API like with Chrome, or Firefox. The result is not unexpected; extensions break very easily from one version of GNOME to the next.

The second issue is that extensions can easily break GNOME, because they can modify absolutely anything in the shell.

gsettings

Another option is to manually change the configurations through the command line. This is obviously not user-friendly, and not ideal either.

 

GNOME developers made the mistake of not allowing configurability directly into GNOME, and as a result they have made the much needed configurations second class citizens, than no matter what you do, they don’t work as expected. The problem is very easy to solve; the configurations should be integrated into GNOME, and activated by a single switch, so their normal configurations are not disturbed. But talking sense to these guys is next to impossible.

Classic mode

Finally, after so much backlash from the users for years, GNOME developers had to implement the classic mode, so users could be able to run their beloved GNOME 2 interface with GNOME 3 technology.

Unfortunately, GNOME classic is more of a hack than anything else; it’s full of bugs and inconsistencies. Sure, this mode is still in its infancy, and will probably improve in the next releases, but it’s safe to bet that it would never be as polished and usable as GNOME 2 was.

Sorry GNOME devs; too little, too late.

Suckage

I am not going to list every single reason why GNOME 3 sucks, I would never finish this post, and there’s plenty of people that have already added their share (I’ll list some of them).

Personally for me the most obvious way to see that GNOME 3 defaults are brain-dead is the way alt+tab works. The whole purpose of work-spaces is to separate work, instead of having all your browser windows, terminals, editors, email client, and so on, on the same work-space, you split them among different ones. Even their own design references for GNOME shell say so. So, to make alt-tab cycle through the windows in all works-paces instead of only the current one is idiotic; it undermines the whole purpose of work-spaces.

Instead of accepting this obvious fact (which many users complained about), they disregard any feedback, and say “oh, you can use an extension for that”. Never mind the fact that a huge percentage of their users need to install the extension just to have a sane behavior, and that the extension can break at any moment.

gnome-3-is

Another quite obviously stupid behavior is to switch to an already running “application” instead of opening a new one. For example; if I press the Windows key, and type chromium, I expect a new browser window to open, but no, instead I’m unexpectedly dragged to another work-space where there’s already a browser window. This makes sense on single-window applications, but not on other ones.

Linus Torvalds and others complained about this, and I proposed a solution; add a menu item when right clicking on the application that says “Always open new window”; problem solved. Now each time the user tries to open this application, it’s done in a new window. But no, users don’t know what they want; GNOME developers know better what’s best for us.

The list of stupidities in GNOME 3 is never ending:

gnome-3

The Linux way

What GNOME should have done is simple; don’t ever, ever break user experience. This is how the Linux project has managed to become the most successful software project in history. There are no forks of the Linux kernel, simply because there’s no need; user experience is never broken; what works in v2.0, works in v3.0, and will work in v4.0. New features are added carefully, making sure nothing breaks, and users always have a way to make the system work the way they expect it to work.

GNOME shell should have been developed alongside GNOME 2 and users should have given the option to turn this mode on and off. Slowly, GNOME shell would get more features from GNOME 2, until it was a full replacement, and at the same time GNOME 2 would evolve to integrate GNOME 3 technologies (like GTK+ 3.0). Eventually GNOME shell becomes the default, but always with the option to use the classic interface. After some cycles, the GNOME shell interface is bound to be a full replacement for the classic one.

Unfortunately, they chose not to do this.

Going this way requires more effort, of course, but it’s the only way to move forward without loosing developers and users along the way. GNOME developers argued that they didn’t have the resources to do such careful move, but that is clearly false, as the developers working on MATE, Cinnamon and GNOME classic show; there’s developers interested in making things work for the traditional mode.

They chose not to listen to the warnings, and they became impatient and went forward with a move that had the potential of angering a lot of users. Well, this potential was fully realized, and now they are paying the consequences.

They were wrong

They argued this was like GNOME 2; the people complaining about it will eventually learn the new ways, and most will be happy. They were wrong.

Even to this day people keep complaining about GNOME 3, how the interface doesn’t make sense, how the developers don’t listen, and how the design is brain-dead.

There’s no other way to put it; GNOME 3 was a mistake.

Bridge support in git for mercurial and bazaar

I’ve been involved in the git project for some time now, and through the years I’ve had to work with other DSCMs, like mercurial and monotone. Not really as a user, but investigating the inner workings of them, mostly for conversion purposes, and I’ve written tools that nobody used, like mtn2git, or pidgin-git-import, but eventually I decided; why not write something that everybody can use?

So, I present to you git-remote-hg, and git-remote-bzr. What do they do?

git clone "hg::http://selenic.com/repo/hello"
git clone "bzr::lp:gnuhello"

That’s right, you can clone both mercurial and bazaar repositories now with little to no effort.

The original repository will be tracked like any git repository:

% git remote show origin
* remote origin
  Fetch URL: hg::http://selenic.com/repo/hello
  Push  URL: hg::http://selenic.com/repo/hello
  HEAD branch: master
  Remote branches:hg and mercurial. 
    branches/default tracked
    master           tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (create)

You can pull, and in fact push as well. Actually, you wouldn’t even notice that this remote is not a git repository. You can create and push new branches… everything.

You might be thinking that this code being so new might have many issues, and you might screw up a mercurial repository. While that is true to some extent, there’s already a project that tries to act as a bridge between mercurial and git: hg-git. This project has a long history, and a lot of people use it successfully. So, I took their test framework, cleaned it up, and used to test my git-remote-hg code. Eventually all the tests passed, and I cloned big mercurial repositories without any issue, and the result were exact replicas, and I know that because the SHA-1’s were the same ūüôā

So you can even keep working on top of clones you have created with hg-git, and switch back and forth between git-remote-hg and hg-git as you wish. The advantage over hg-git, is that you don’t need to use the mercurial interface at all, you can use git ūüôā

To enable the hg-git compatibility mode you would need this:

% git config --global remote-hg.hg-git-compat true

What about the others?

Surely I must not be the first one try something this cool, right? I don’t want to dwell into all the details why none of the other tools suited my needs, but let’s give a quick look:

hg-git

It’s for mercurial, not git. So you need to use it through the mercurial UI.

fast-export

This is a very nice tool, but only allows you to export stuff (fetch an hg repo), and you have to manually run the ‘git fast-import’ command, setup the marks, and so on. Also, it’s not very well maintained.

Another git-remote-hg

It needs hg-git.

Yet another git-remote-hg

You need quite a lot of patches on top of git, so your vanilla version of git is not going to cut it.¬†In addition to that it doesn’t support as many features; no tags, no bookmarks. Plus it fails all my extensive tests for git-remote-hg.

git-hg

It needs separate tools, such as ‘hg convert’, and fast-export, and it doesn’t use remote helper infrastructure, so it’s not transparent: you have to run git-hg clone, git-hg fetch, and so on.

Another git-hg

It needs hg-git, and doesn’t use git’s remote helper infrastructure either: you have to do git hg-clone, git hg-pull, etc.

There might be others, but you get the point.

The situation in bazaar is not much better, but I’m not going to bother listing the tools.

More coolness

In fact, you can push and pull from and to mercurial and bazaar ūüôā

% git remote -v
bzr	bzr::lp:~felipec/+junk/test (fetch)
bzr	bzr::lp:~felipec/+junk/test (push)
gh	gh:felipec/test.git (fetch)
gh	gh:felipec/test.git (push)
hg	hg::bb+ssh://felipec/test (fetch)
hg	hg::bb+ssh://felipec/test (push)

Isn’t that cool?

So, are there any drawbacks? Surely some information must be lost.

Nope, not really. At least not when using the hg-git compat mode, because all the extra information is saved in the commit messages.

Update: I forgot to mention the only bidirectionality problem: octopus merges. In git a merge can have any number of parent commits, but in mercurial only two are allowed. So you might have problem converting from a git repository to a mercurial one. It’s the only feature that hg-git has, that git-remote-hg doesn’t. As for bazaar, it also allows multiple parents, so it should work fine, but this hasn’t been thoroughly tested.

The only consideration is that in the case of mercurial branches are quite different from git branches, so you need to be really careful to get the behavior you want, which is why it’s best to just ignore mercurial branches, and use bookmarks instead. When you create git branches and push them to mercurial, bookmarks will be created on whatever branch is current.

Trying it out

Just copy them files (git-remote-hg,¬†git-remote-bzr) to any location available in your $PATH (.e.g ~/bin), and start cloning ūüôā

Soon they might be merged into upstream git, so they would be distributed as other contrib scripts (e.g. /usr/share/git), and eventually possibly enabled by default. They were distributed as other contrib scripts, and they were going to be enabled by default, until the maintainer decided not to, for no reason at all.

Enjoy!

msn-pecan 0.1.4 released

Hi,

Long time no see! I’ve been busy with many other things and haven’t had time to work on msn-pecan, but I’m back.

This a minor bugfix release, mostly to fix issues while reconnecting. These will be useful for HTTP non-persistent connections which is a work in progress. There’s plenty many other patches pending in the queue, some you can try on the master branch.

Felipe Contreras (6):
      node: avoid writes when connection is closed
      ssl-conn: cleanup properly on errors
      io: properly cancel connect operations
      build: fix platform detection
      win32: update instructions for Arch Linux
      win32: version bump

Download from the (usual place).

Top 10 suggestions from the 2011 GNOME user survey

I’ve taken the time to read one by one the suggestions from the 2011 GNOME user survey, I’ve only managed to read 20% of them so far, but I don’t think they will shift that much (I might update this post if they do).

The next version of the survey will have these and other suggestions already listed, so it would be easier for users’ voice to be heard, and¬†summarize¬†the results.

Note: I already posted most of these on my previous post, but apparently people didn’t like my critical tone, so these are the suggestions only, not my opinion.

1. Better customization

This is by far the most requested, people don’t want to manually fiddle with gconf/dconf, extensions, or gnome-tweak, they want a whole lot more options integrated. One suggestion was to have an advanced mode.

Not only do people want more options, but they think some of the current ones are useless, and that defaults are all wrong. They also want more options for power management, like deciding what happens when you close the lid. Also more options to change the appearance: font, icons, keyboard bindings, screensaver, etc. Also, disable the accessibility stuff.

2. GNOME 2

People love their GNOME 2. A lot of them suggested to have two interfaces: the traditional one, and the shell, others requested to improve the fallback mode, but most of them demanded to get rid of GNOME shell completely. A lot of people also asked specifically to bring back the GNOME 2 panel, and taskbar.

3. Improve performance and footprint

A lot people think GNOME is too bloated and asked for better performance, less CPU usage, less memory usage, smoother animations, faster¬†start-up¬†times, etc. Specially the ones that have used GNOME shell, which apparently is a resource hog, or at least that’s what users say.

4. Nautilus

People are definitely not happy with nautilus. They complain it’s too slow, takes too much time to start, and lacks a lot functionality. Many suggested to get rid of it and use some of the already existing alternatives.

5. Notifications

The new notifications are annoying; one shouldn’t need to move the mouse cursor the corner to see them; that makes it easy to miss them, which defeats the purpose of a notification.

6. Shutdown / Restart / Suspend

This is a no-brainer; just add this option. Yes, you can see them by pressing “alt” but people don’t want that, there’s no excuse to remove basic functionality, and users are complaining hard for this particular feature.

7. Improve theming

Users want better themes and icons, they don’t like the default theme, also want a dark theme, and think the amount of customization a theme can achieve is not enough.

8. Better multi-monitor support

Another very requested feature was to improve multi-monitor support, which apparently works very badly in GNOME shell.

9. Improve Evolution

A considerable amount of people suggested to get rid of Evolution completely, because it has so many problems, and because there are better alternatives (i.e. Thunderbird). Some people only want to use the calendar part of it, because it’s integrated to other parts of GNOME’s UI, so they suggested to split this component. The rest suggested many ways to improve it, like stop the constant crashing.

10. Listen to users

Lastly, a lot of people think that GNOME developers are ignoring users, and their suggestions. Also, they don’t like the developers’ attitude that users are idiots, and developers/designers know best.

The problem

As #10 shows, the problem is that GNOME developers don’t listen to the users, or at least that’s the perception from a lot of users, and since the community rejected the idea of running and/or blessing this survey, it would be safe to¬†assume¬†that they would ignore the results. The story of this survey is rather interesting, and explains a lot, but you can read about it through¬†Bruce Byfield’s mouth instead of mine in his article ‘The Survey That GNOME Would Rather Ignore‘.

Even before the survey was run, GNOME developers said the results would be worthless, however, the only valid criticism was the possibility of non-response bias, which fortunately didn’t happen, and I explained why in my analysis of the survey results. I still haven’t received any comments from GNOME developers after I publicized the analysis of the results, so if there’s any valid criticism remaining, I still haven’t heard of it.

I wish they would look at these results critically, not outright reject them, and if there’s any problem with the survey, tackle the problems for the 2012 survey, and even more: run the survey themselves. Wouldn’t that be great?

 Other suggestions

  • Reduce dependencies (specially¬†PulseAudio)
  • Improved reliability / stability
  • Minimize / Mazimize
  • Tiling
  • alt+tab
  • Faster shell search
  • Collaborate more with other communities
  • Fix ATI fglrx issues
  • Integrate Zeitgeist
  • Render KDE apps seamlessly
  • Reduce dead space
  • Compiz compatibility

The meaning of success

I once had a quite extensive discussion with a colleague about several topics related to the software industry, and slowly but methodically we reached a fundamental disagreement on what “success” means. Needless to say, without agreeing on what “success” means it’s really hard to reach a conclusion on anything else. I now believe that many problems in society — not only in the software industry — can be derived from our mismatches in our understanding of the word “success”. It is like trying to decide if abortion is moral without agreeing on what “moral” means — and we actually don’t have such an agreement — and in fact, some definitions of morality might rely on the definition of “success”.

For example: which is more successful? Android? iPhone? or Maemo? If you think a successful software platform is the one that sells more (as many gadgets geeks probably do), you would answer Android, if on the other hand you think success is defined by what is more profitable (as many business people would do), you would answer iPhone. But I contend that success is not relative only relative to a certain context; there’s also an objective success that gives a clear answer to this question, and I hope to reach it at the end of this post.

This not a¬†meta-philosophical¬†exercise, I believe “success” in the objective sense can be clearly defined and understood, but in order to do that, I would need to show some examples and counter-examples in different disciplines. If you don’t believe in the theory of evolution of species by natural selection, you should probably stop reading.

Definition

The Merriam-Webster dictionary defines success as (among other definitions):

  • a¬†:¬†to turn out well
  • b¬†:¬†to attain a desired object or end¬†<students who¬†succeed¬†in college>

From this we can say there’s two types of success; one is¬†within¬†a specific context (e.g. college), and the other one is in general. In this blog post I will talk about generic success, with no specific goal, or rather with the generic ultimate goal. Since it’s highly debatable (and difficult)¬†how to define this “ultimate goal”, I will concentrate on the opposite; to try to define the ultimate failure in a way that no rational person would deny it.

Humans vs. Bacteria

My first example is: what organisms are more successful? Humans, or bacteria? There are many angles in which we could compare these two organisms, but few would reach a definite answer. The¬†knee-jerk¬†reaction of most people would be to say: “well, clearly humans are more evolved than bacteria, therefore we win”. I’m not an expert in the theory of evolution, but I believe the word “evolved” is misused here. Both bacteria and humans are the results of billions of years of evolution, in fact, one could say that some species of bacteria are more evolved because Homo Sapiens is a relatively new species and only appeared a few hundred thousands years ago, while many species of bacteria have been evolving for millions of years. “Kids these days with their fancy animal bodies… I have been killing animals since before you got out of the water… Punk” — A species of bacteria might say¬†to younger generations¬†if such a thing would be possible. At best humans are as evolved as bacteria. “Primitive” is probably the right word; bacteria is more primitive because it closely resembles its ancestors. But being primitive isn’t necessarily bad.

In order to reach a more definitive answer I will switch the comparison to dinosaurs vs. bacteria, and come back to the original question later. Dinosaurs are less primitive than bacteria, yet dinosaurs died, and bacteria survived. How something dead can be considered successful? Strictly speaking not all¬†dinosaurs¬†are dead, some evolved into birds, but that’s besides the point; let’s suppose for the sake of argument that they are all dead (which is in fact how many people consider them). A devil’s advocate might suggest that this¬†comparison¬†is unfair, because in different circumstances¬†dinosaurs¬†might have not died, and in fact they might be thriving today. Maybe luck is an important part of success, maybe not, but it’s pointless to discuss about what might have been; what is clear is that they are dead now, and that’s a clear failure. Excuses don’t turn a failure into a success.

Let me be clear about my contention; anything that ceases to exist is a failure, how could it not? In order to have even the smallest hope of winning the race, whatever the race may be, even if it doesn’t have a clear goal, or has many winners; you have to be on the race. It could not be clearer: what disappears can’t succeed.

Now, being more evolved, or less primitive, is not as a trump card as it might appear; nature is a ruthless arena, and there are no favorites. The vast majority of species that have ever lived are gone now, and it doesn’t matter how “unfair” it might seem, to nature only the living sons matter, everyone else was a failure.

If we accept that dinosaurs failed, then one can try to use the same metric for humans, but there’s a problem (for our¬†exercise); humans are still alive. How do you compare two species that are not extinct? Strictly speaking all species alive today are still in the race. So¬†how easy is it for humans to go extinct? This is a difficult question to answer, but lets suppose an extreme event turns the average temperature of the Earth 100¬įC colder; that would quite likely kill all humans (and probably a lot of plants and animals), but most certainly a lot of bacterial species would survive. It has been estimated that there’s¬†5√ó1030¬†bacteria on Earth, countless species, and possibly¬†surpassing¬†the biomass of all plants and animals. In fact, human beings could not survive without bacteria, since it’s essential to the human microbiome, and if you sum the bacteria genes in a human body, it¬†probably outranks the human genes by a factor of 100-to-1. So, humans, like¬†dinosaurs, could disappear rather easily, but bacteria would still be around for a long long time. From this point of view, bacteria are clearly more successful than humans.

Is there any scenario in which humans would survive, and bacteria would not? (therefore making humans more successful) I can think of some, but they would be far into the future, and most definitely we are not yet there. We are realizing the importance of our microbiome only now, and in the process of running the Human Microbiome Project, so we don’t even know what role our bacteria plays, therefore we don’t know how we could replace them with something else (like nanorobots). If bacteria disappeared today, so would we. It would follow then that bacteria are more successful, and there’s no getting around that.

Fundamentals and Morality

Could we define something more fundamental about success? I believe so: a worse failure than dying, is not being able to live in the first place, like a fetus that is automatically aborted because of a bad mutation, or even worse; an impossibility. Suppose “2 + 2 = 5”; this of course is impossible, so it follows that it’s a total failure. The opposite would be “2 + 2 = 4”; this is as true as anything can be, therefore it’s a total success.

There’s a realm of mathematics that is closer to what we consider morality: game theory. But don’t be fooled by its name; game theory is as serious as any other realm of mathematics, and the findings as conclusive as probability. An example of game theory is the prisoner’s¬†dilemma — here’s a classic version of it:

Two men are arrested, but the police do not possess enough information for a conviction. Following the separation of the two men, the police offer both a similar deal‚ÄĒif one testifies against his partner (defects/betrays), and the other remains silent (cooperates/assists), the betrayer goes free and the one that remains silent receives the full one-year sentence. If both remain silent, both are sentenced to only one month in jail for a minor charge. If each ‘rats out’ the other, each receives a three-month sentence. Each prisoner must choose either to betray or remain silent; the decision of each is kept quiet. What should they do? If it is supposed here that each player is only concerned with lessening his time in jail, the game becomes a non-zero sum game¬†where the two players may either assist or betray the other. In the game, the sole worry of the prisoners seems to be increasing his own reward. The interesting symmetry of this problem is that the logical decision leads each to betray the other, even though their individual ‚Äėprize‚Äô would be greater if they cooperated.

There are different versions of this scenario; with different rules and more complex agents game theory arrives to different conclusions as to what rational agents should do to maximize their outcomes, but these strategies are quite factual and universal; we are not talking about human beings; they are independent of culture, or historicism; the rules are as true here as they are in the other side of the universe. So if game theory determines that a certain strategy fails in certain¬†situation, that’s it; it’s as hard of a failure as “2 + 2 = 5”.

With this notion we might be able to dive into more realistic and controversial examples — like slavery. Nowadays we consider slavery immoral, but that wasn’t the case in the past. One might say that slavery was a failure (because it doesn’t exist (at least as a desirable concept)), but that is only the case in human society, perhaps there’s another civilization in an alien planet that still has slavery, and they are still debating, so one might be tempted to say that slavery’s failure is still contended (perhaps even more so if you live in Texas). But we got rid of slavery because of a reason; it’s not good for everybody. It might be good for the slave owners, and good for some slaves, but not good for everybody. It is hard to imagine how another civilization could arrive to a different conclusion. Therefore it is quite safe to say that in all¬†likelihood¬†slavery is a failure, because of its tendency to disappear. Perhaps at some point game theory would advance to the point where we can be sure about this, and the only reason it took so long to get rid of slavery is that we are not rational beings, and it takes time for our societies to reach this level of rationality.

Objective morality and the moral landscape

Similarly to the objective success I’m proposing, Sam Harris proposes a new version of objective morality in his book The Moral Landscape. I must admit I haven’t read the book, but I have watched his online lectures about the topic. Sam Harris asserts that the notion that science shouldn’t deal with morality is a myth, and that advances in neuroscience (his field of expertise) can, and should, enlighten us as to what should be considered moral. Thus, morality is not relative, but objective. The different “peaks” in the landscape of morality are points in which society aims to be, in order to be a good one, and historically the methods to find these “peaks” has been rather¬†rudimentary, but a new field of moral science could be the ultimate tool.

Regardless of the method we use to find these “peaks”, the important notion (for this post), is that there’s an abyss; the lowest moral point. The worst possible¬†misery¬†for all beings is surely bad:

The worst-possible-misery-for-everyone is ‘bad.’ If the word ‘bad’ is going to be mean¬†anything¬†surely it applies to the worst-possible-misery-for-everyone. Now if you think the worst-possible-misery-for-everyone isn’t bad, or might have a silver lining, or there might be something worse… I don’t know what you’re talking about. What is more, I’m reasonably sure you don’t know what you’re talking about either.

I want to hijack this concept of the worst-possible-misery-for-everyone that is the basis of (scientific) objective morality, and use it as a comparison to my contention that ceasing-to-exist is the basis for objective success.

Today our society is confronted with moral dilemmas such as gay marriage and legal abortion, many of these are hijacked by religious bigotry and irrationality, and it’s hard to move forward because many still define morality through religious dogmas, and even people who don’t, and are extremely rational, still cling to the idea that morality comes from “God” (whatever that might mean). Even many scientists claim that morality cannot be found through science, and others that morality is relative. But yet others disagree and have tried to define morality in universal terms, like Sam Harris. The jury is still out on this topic, so I cannot say that morality should¬†definitely¬†be defined in terms of what is successful to our worldwide society, merely that it is a possibility — A rather strong one, in my opinion.

Life

It’s a little more tricky to define what constitutes a successful life, because all life ends. The solution must be one on the terms of¬†transcendence: offspring, books, memes, etc. However people living a more¬†hedonistic¬†life might disagree; but lets be clear, a life can be unsuccessful in the grand scheme of things, but still be good, and the other way around. It might be tempting to define success in different terms: “if my goal is to enjoy life, and I do; I’m succeeding”, and while that is true, that’s being successful in relative terms, not general terms.

Some people might have trouble with this notion, so I would give an example:¬†Grigori Perelman vs. Britney Spears. Most people probably don’t know Grigori, but he solved one of the most difficult problems in mathematics, and was awarded one million USD for it. Clearly this would have helped him to become famous, but he rejected interviews and rejected the money. Does this means he rejected success? Well, lets try to view this from the vantage point of 500 years into the future; both Britney Spears and¬†Grigori Perelman would be dead by that time, so the only things that remain would be their¬†transcendence. Most likely nobody would remember¬†Britney Spears, nor listen to any of her music, while it’s quite likely that people would still be using¬†Grigori Perelman’s mathematics, as he would be one of the giants upon which future scientists would stand. In this¬†sense¬†Grigori is more successful, and any other sense of success would be relative to something else, not objective.

Test

Hopefully my definition of success should be clear by now in order to apply it to the initial example.

iPhone

iPhone is clearly successful in being profitable, but many products have been profitable in the past and have gone with the wind. The real question is: What are the chances that the iPhone will not¬†disappear? It is hard to defend the position that the iPhone will remain for a long period of time because it’s a single product, from a single company, and specially considering that many technology experts can’t find an explanation for its success other than the Apple Cult. While it was clearly superior from an aesthetic point of view while it was introduced, there’s many competitors that are on par today. Maybe it would not¬†disappear¬†in 10 years, but maybe it would. It’s totally unclear.

Android

Compared to the iPhone, Android has the advantage that many companies work on it, directly and indirectly, and it doesn’t live on a single product. So if a single company goes down, that would not kill Android, even if that company is Google. So, as a platform, it’s much more resilient than iOS. Because of this reason alone, Android is clearly more successful than the iPhone — according to the aforementioned definition.

Maemo

Maemo is dead (mostly), so that would automatically mean that it’s a failure. However, Maemo is not a single organism; it consists of many subsystems that are part of the typical Linux ecosystem: Linux kernel, X.org, Qt, WebKit, GStreamer, Telepathy, etc. These subsystems remain very much alive, in fact, they existed before Maemo, and will continue to exist, and grow. Some of these subsystems are used in other platforms, such as WebOS (also dead (mostly)), Tizen, MeeGo (also dead (kinda)), and Mer.

A common saying is that open source projects never die. Although this is not strictly true, the important thing is that they are extremely difficult to kill (just ask Microsoft). Perhaps the best¬†analogy¬†in the animal kingdom would be to compare Maemo to a sponge. You can divide a sponge into as many parts as you want, put it into a blender, even make sure the pieces pass through a filter with very minute holes. It doesn’t matter; the sponge would reorganize itself again. It’s hard to imagine a more resilient animal.

If this is the case, one would expect Maemo (or its pieces) to continue as Tizen, or Mer (on Jolla phones), or perhaps other platform yet to be born, even though today it seems dead. If this happens, then Maemo would be even more successful than Android. Time will tell.

Predictions

Like any a scientific theory, the really interesting bit of this idea would be it’s predictive power, so I will make a list of things in their order of success, and if I’m correct the less successful ones would tend to¬†disappear¬†first (or their legacy):

  • Mer > Android > iOS > WP
  • Linux > Windows
  • Bill Gates > Steve Jobs > Carlos Slim (Richest man in the world)
  • Gay marriage > Inequality
  • Rationality > Religious dogma
  • Collaboration > Institutions

To me, this definition of “success” is as true as “2 + 2 = 4” (in fact, it’s kind of based on such fundamental truths), unfortunately, it seems most people don’t share this point of view, as we still have debates over topics which are in my opinion a waste of time. What do you think? Are there examples where this definition of success doesn’t fit?