I've always used git before, but I want to contribute to python so now I have to learn mercurial and I find it very frustrating.

So, I've made a couple of small patches and I wanted to track them as commits in my local mercurial repository. Apparently there are 4 ways to handle branching in mercurial.
1 and 4 looked completely ridiculous to me, named branches seem to be heavyweight and I feel that I'm not supposed to use them for quick 1-commit fixes, so I used bookmarks.

Now, my patch gets rejected and I want to remove one of my bookmark-branches from my repository.
OK, in git I would just force-delete my branch and forget about it, so I delete my bookmark and now I have following problems:

TortoiseHG and hg log still show that commit and default branch has 2 heads. And if I understand correctly, you can't delete commits in hg without additional plugins.

Mercurial has not only hashes, but also revision numbers. As I've added a couple of my own commits, all commits pulled after that have different revision numbers from the main central
repo.

I do hg update after pulling to move my master bookmark to the latest commit automatically, but I couldn't find a way to do that in TortoiseHG.

What am I doing wrong? Is this normal and expected and should I just ignore these issues?
Or how am i supposed to work with my branches?

4 Answers
4

Personally, for your scenario, I wouldn't bother even creating a branch, unless I was working on multiple changes, each of which would need to be accepted by the core developers.

Just clone their repository and work in it, then make a pull request.

If I were to use a branch then I'd rather use named branches. They were designed for this exact purpose, where bookmarks weren't. I don't see why you'd consider it heavy-weight.

Mercurial have a whole page on their wiki describing different ways of "Pruning Dead Branches". The "Using clone" option should satisfy your requirements.

To answer your more specific issues ...

TortoiseHG and hg log still show that commit and default branch has 2 heads. And if I understand correctly, you can't delete commits in hg without additional plugins.

This is a mistake I made with Mercurial when I was new to it. Do not be afraid of those additional plugins. Some of them are very powerful tools and often they later get pulled into the core product. That just how Mercurial works. If you need one to perform a specific task, get it and use it.

Revising history is considered a bad thing in the Mercurial world, so the vanilla product doesn't always have everything that a Git user thinks it should have, but there are plenty of plugins for those who want to use the application but have different priorities.

Mercurial has not only hashes, but also revision numbers. As I've added a couple of my own commits, all commits pulled after that have different revision numbers from the main central repo.

Do not worry about revision numbers. They are a matter of convenience, no more. The hash codes are the important identifiers that will pass from repo to repo. Revision numbers are inconsistent across repositiories. Check out Hg Init for a good explanation.

Revision numbers are just a handy and more memorable shortcut when working with a single repo.

I do hg update after pulling to move my master bookmark to the latest commit automatically, but I couldn't find a way to do that in TortoiseHG.

When using TortoiseHG, use the Workbench rather than the other tools. Everything (almost) is in there. Update is in the revision context menus. It's not always intuitive, but there is a good guide at the link above and as you get used to it, you end up clicking away with confident abandon.

Apparently there are 4 ways to handle branching in mercurial. 1 and 4 looked completely ridiculous to me, named branches seem to be heavyweight

In Mercurial, you don't create branches. Every commit is effectively a branch, any commit can have multiple parents and multiple children. So those are the four different ways to organize the same entities.

You can give them different names, you don't have to, but it's a good idea. There is nothing heavyweight about named branches - it's just some extra metadata. I personally prefer named branches to anything else in any situation.

TortoiseHG and hg log still show that commit and default branch has 2 heads.

Which is exactly the reason to use named branches instead of dumping everything into default.

And if I understand correctly, you can't delete commits in hg without additional plugins.

You can't actually delete anything in Mercurial at all and you shouldn't. You can use hg strip but it isn't logged - you basicaly just cut off a part of your local repo. You can't push that, and if you pull from a repo that has the branch you stripped locally, it comes back.

Mercurial has not only hashes, but also revision numbers. As I've added a couple of my own commits, all commits pulled after that have different revision numbers from the main central repo.

Numbers don't mean anything. You can disregard them if they confuse you.

I do hg update after pulling to move my master bookmark to the latest commit automatically, but I couldn't find a way to do that in TortoiseHG.

I haven't used TortoiseHG but hg pull -u will do both pull and update.

I've always used git before, but I want to contribute to python so now I have to learn mercurial and I find it very frustrating.

That's ok, many Mercurial users feel the same about Git (including me).

Even when Mercurial and Git are similar, they have different designs, maybe being the most important design difference is that in Mercurial modifying the history is not as flexible as in git (because it is kind of discouraged).

Short answer: it doesn't matter if you have a small amount of changes, you can still use a branch. If you are thinking about deleting that branch then use a bookmark so you can delete it later and strip the changes afterwards.

First, trying to shed a little light on some of the things you mention:

1 and 4 are considered branching is because every time you commit you are effectively creating an unnamed branch (if there is another commit by the same time at your source/blessed repo), which is technically a branch. In method 4 you are creating a new "head" while in method 1 you are not. Heads are supposed to be merged. I agree that method 1 is kind of silly, but some seem to like it... for small projects, I'd guess.

Regarding method 2, it is not that branches are heavy, it is that they are permanent. You cannot remove a branch unless you use something like the strip extension. Again, Mercurial's design philosophy doesn't go towards modifying the history (but it has gotten better at that).

Regarding revision numbers, they are just a local and more humanly readable reference for you to use all commands that have to do with revisions. If you like using hashes, you can still do. Revision numbers are just a shortcut and are disregarded by Mercurial for any internal operations between different repositories.

Now, to answer your other questions:

You can check what heads you have with hg heads, if you see 2+ heads in a single named branch, it is preferable that they are merged. That is probably where your bookmark is.

To get rid of a revision you've just made, you could do hg rollback, but I'm guessing this isn't the case.

Mercurial already comes bundled with several extensions, but they are not activated by default. Just go into any folder and right click anywhere to get the TortoiseHG context menu, go into Global Settings and then Extensions: activate the MQ extension and the Rebase extension. This does not damage compatibility between repositories whatsoever.

Now that you are here, you could either:

Strip where your bookmark began (this probably fixes your problem)

For easier visualization, maybe you could rebase your changes at the front and then strip them afterwards. I just mentioned rebase because it might be something useful for you some other time.

Also, in git you can have "private local branches" because you have to push them explicitly and you can delete them afterwards. In Mercurial you push all what you have, however, if you want to avoid this you can use the Phases feature and mark a set of revisions as secret. Secret revisions won't get pushed.

Finally, you are not doing anything wrong, just keep in mind that they are just different tools built with slightly different mindsets, which pretty much boil down to: modifying history (git) or not modifying history (hg). In Mercurial it is harder to shoot yourself in the foot modifying the history (specially with Phases) and that is why some like it better than git.

I find with mercurial it easiest not to worry about branches. I just find where in history I want to edit from and create commits as required (a.k.a. anonymous branches). Sometimes bookmarks might be useful if I'm having to jump between heads in different contexts but most often I don't bother with them. Named branches are OK for long-lived branches (bug-fix branches, project-branches) but for 1- or 2-commit fixes, they are not the right tool for the job.

The trick with anonymous branches is to set their phase to "secret" if you don't want to push them i.e. if you want to keep them local. If you do want to push them, but you don't want any more commits based on them, you just commit a "--close-branch" on top of them which means they no longer appear in the 'heads' list and mercurial will stop complaining about multiple heads on that branch.