I read about bookmarks in mercurial, every source states that it's like git branching, that the bookmark gets updated uppon every commit, but I really don't understand what's its purpose. Any guidance would be greatly appreciated. Thanks.
From the Mercurial wiki:
Bookmarks are references to commits that are automatically updated
when new commits are made. If you do hg bookmark feature the feature
bookmark refers to the current changeset. As you work and commit
changes the bookmark will move forward with every commit you do. The
bookmark will always point to the latest revision in your line of
work. Since bookmarks are automatically updated when committing to the
changeset they are pointing to, they are especially useful to keep
track of different heads. They can therefore be used for trying out
new features or pulling changes that have yet to be reviewed.
I also suggest reading this article for an overview of the various ways to branch in Mercurial.
I suggest not taking bookmarks and trying to find a use for them, but rather finding a process you find natural to use in your team and then finding how Mercurial best handles branches in the context of that process, be it with bookmarks or cloning or what have you.
Adding just a few minor details, to the excellent points of Mihai Danila:
Bookmarks are, in a few words, a lot like: "movable tags without a permanent movement log".
There are various features built on top of the 'movable tag' property, like merging of bookmarks from other clones, automatic movement of the bookmark as you commit on top of it, etc. But the basic idea is pretty much just that. A symbolic name that you can attach to a changeset, much like a 'tag', but one that can move arbitrarily forward or backward in history as required.
You can definitely built a branching scheme on top of bookmarks. In fact, Mercurial itself has adopted the names 'crew' and 'crew-stable' for two bookmarks that the development team uses to coordinate Mercurial's own development. But you don't have to.
I agree 100% with what Mihai wrote: "Don't take bookmarks and try to find a use for them, but rather find a process you find natural to use in your team and then find out how Mercurial best handles branches in the context of that process, be it with bookmarks or cloning or what have you".
Related
I really like the Hg Flow for Mercurial repositories. we are currently using Bitbucket, and in each product multiple developers are working. basically they can work as below:
a team might work on a single feature.
another team might work on a release/hot fix.
So do i keep the "develop" branch in BitBucket or local repositories. and how about feature branches, should i push them to the central repository and remove when required. i assume we should do so right?
Thanks
I personally neither use git flow or hg flow as tools, but I do use some of the methods for my own projects (manually).
Before going into detail, you always need to provide branches in the main/bitbucket repository when multiple people need to merge or branch from them.
This definately includes "develop" and probably also features/fixes multiple people need to work on (unless you have another repository or method to exchange branches/commits between them)
The difference between using git and mercurial/hg is relevant here, since the branching models are quite different.
See A Guide to Branching in Mercurial for details. Using hg bookmarks would be quite similar to what git does with branches, but there is no full support for the bookmark branching model on BitBucket (see this ticket).
hg flow (the tool) uses named branches. In contrast to git branches, these are not at all light-weight, but permanent and global (they can at least be closed now).
This means whenever any commit created on any (named) branch other than "default" is pushed to bitbucket (even after merging) this will create the branch in the bitbucket repository.
So you don't have any other choice than keeping all branches in the main repository.
However, You can decide when to push and when to close these.
I would advise using hg push -r to push only the branches/heads you want to push and only pushing these when they are either needed by somebody else or finished and merged.
Branches should be closed as soon they are not needed anymore. (This is probably done by hg flow automatically)
You should close branches locally whenever possible. This way they might not even appear in the bitbucket interface. Some might reach the bitbucket repository only in closed state (which hides them from the interface).
Obviously you should often push any branches multiple people need to merge from.
In my understanding of the workflow the "develop" branch is always exactly one branch per project that should be pushed frequently (after local testing).
In case you are either not using hg-flow or named branches things are a bit different.
Both, using forks/clones or bookmarks as a branching method doesn't generate permanent or necessarily global branches.
Like mentioned above, you can't use bookmarks (reliably) when you also want to use bitbucket pull requests. You have to push bookmarks separately. A normal push will only update (a head of) the branch so you might miss commits from other team members when marging later. Hg will tell you when a new head is created. In that case you might want to merge the branch with the remote bookmark into your branch before pushing.
When using forks as branches it works a bit like with bookmarks, but bitbucket has full support for that. You need to have a new fork on bitbucket for every branch.
You naturally only want to create extra forks if you need different people to work on it and you don't have other means of commit exchange for them. You will need at least a separate "develop" repository then.
I personally wouldn't use the full "flow" with hg on bitbucket.
For my projects the "develop" branch is the same as master/default, since I don't roll out releases with git (other than development builds, that wouldn't use the release branch anyways). I don't need a separate "production" branch, since tags can mostly be used for production usage.
I also don't create a separate "release-preparation" branch. There is only a point in time when I only apply bugfixes on develop and stop merging features. That obviously won't work when you need to work at the same time on features that are dependendant on features not to be released in the next release.
Always using the full "git flow" is easy because git branching is easy and light-weight.
Depending on the branching model you use and how supportive the other tools are,
using the full "hg flow" might not be "worth it".
The hg guide actually discourages use of named branches for short-lived branches.
See Feature separation through named branches.
The "easy" branching concept promoted in the guide is forking/cloning. Bookmarks would be the natural way to translate git flow if the tool/bitbucket support would be better (and bookmarks longer a core hg feature).
Disclaimer:
I prefer git when I can choose. I do use hg, but not as my personal choice.
You also might have considered most of this, but since you didn't state any of these details and accept an answer (in the comments) that is quite different to what you are asking, I wanted to elaborate a bit.
Edit:
To follow-up on the comments:
I think hg bookmarks are comparable to git branches because both are just movable pointers to commits.
The main difference is, that when you delete a branch in git, the commits are possibly lost (when not part of other branches or pointed to in a another branch before they are garbage collected). When you delete a bookmark in hg, then the commits are still part of the repository (part of the (named or default) branch) unless manually stripped.
Anonymous heads are related, but only as something the bookmarks point to. Without bookmarks pointing to them the anonymous heads are not usable as a branch to work with (for more than just a local merge) and share. When you have anonymous heads in a repository you don't know what they are supposed to be or where they came from, unless you remember or have other clues. In my eyes anonymous heads are only a workaround for late implementation of bookmarks and no good implementation of remotes/remote heads.
Named branches are rather unrelated, as the only thing they have in common with git branches is having a name. They are light-weight in comparision to cloning the whole repository (forking as branch model), but not in terms of "you can't get rid of them". They are permanent.
Most places tell you not to use named branches unless you have a very good reason or it is a long-running branch.
I've used Mercurial for years locally, but now we are doing a pilot of switching over from Subversion at my company.
We're embracing the fact that developers will now be making more granular changesets--some of which may not even build. When developers push their changes to the central repository, all of these changesets will show up in the history - this is natural and expected.
My question is: how do we deal with the fact that, because changesets are more granular, this makes it possible for developers to update to a revision that doesn't build? We are coming from a world where you can checkout anywhere in the repository and reasonably expect to be able to make a release from that point. With DVCS's, how do you tell where a "safe" revision is?
This issue is somewhat addressed in this question, but I'm more interested in finding out how to deal with this using branch repos (and not named branches).
I understand there are ways to modify history (e.g. the collapse extension) so that the changes get collapsed in the history of the repository, but we'd like to preserve the history.
Looking at the mercurial and mozilla trees, I don't see a clear way to tell where safe revisions are to sync. Is this not as important as we think it is?
Do you really need to check out ANY old revision and expect it to build?
I agree with you that you should be able to expect that the tip will always build.
This can be easily achieved, like Lazy Badger already said, by some kind of "don't push unfinished work to the main repo" policy / mutual agreement.
Concerning older revisions:
if you want to build older official releases of your software again (like, you're at version 1.6 now and want to make an v1.2 executable), you can expect the 1.2 tag to build as well if everybody always sticked to the "don't push unfinished work" policy.
if you want to take ANY revision and build it...well, do you really need this? Any bugs in previous versions will probably refer to official releases (see the "1.2 tag" stuff above), and not to something in between.
if you really need a buildable version from in between the official releases (for whatever reason), you'll have to look at the commit messages and find the commit that says feature 'foo' finished (and not the one that says started implementation of feature 'foo').
Yes, this requires a bit of thinking / common sense, but I can't imagine that you will need this really often.
Political solution may be "don't push crap into main repo", isn't it?
Technical solution will be not tag, but one bookmark ("KnownAsGood"), applied to the last working HEAD of default branch and agreement between devs "Update not to tip, but to bookmark"
Who'll test commits and move bookmark is another question from "project management" tag
If you're using feature branches and merging them without fast forward merges, you still have only stable builds on the mainline, but can see the unstable stuff on the feature branches if desired.
You can always tag your commits. These could be major/minor releases, successful builds or however you like. You can see the mercurial and mozilla tags in their repos.
What's the difference between a tag and a bookmark in Mercurial? I can't seem to find any discussion of how the two differ.
Lets consider your repository as a "choose your own adventure books", with different points of view.
A tag is like a stamp that the editor put on your manuscript to say "ok, we keep a trace of your current work, in case shit happens."
A named branch would be a chapter. You have to choose at one point which chapter you'll have to write, and they are there to stay. Some will merge back, some will end (sorry, you died.)
A bookmark is, well, a bookmark. It follows you while you're reading (committing) the book. It helps you to keep tracks of "what you were reading at that time", so you can remove them, move them to a different "chapter". When you share the book (push), you usually don't share your bookmarks, unless you explicitly want to. So you usually use them on anonymous branches because their life cycle is shorter than named branches.
Bookmarks are used when you want a mnemonic (foo_feature) that points to a changing commit id as your work progresses. They're more light-weight that regular Mercurial branches, and somewhat similar to the way git branches work.
Tags generally point to fixed commit ids. They can be reassigned manually, but this is discouraged.
There are actually five concepts to play with:
tags
local tags
bookmarks
lightweight branches
named branches
Lightweight branches are what happens if you just use mercurial. Your repository history forks and sometimes merges as you change things and move around your history.
The other four are ways of annotating lightweight branches and the changesets that make them up.
named branches and tags are mercurial-only concepts where the branch names and tags actually get recorded in the repository by making more commits to the repository. They'll tend to propagate to other repositories in ways which are not necessarily obvious.
local tags and bookmarks are much more like what git calls tags and branches. They're metadata rather than being mixed in with the versioned objects. So they're not represented as part of the repository history. They tend to be local to your repository, and won't propagate unless you propagate them deliberately.
At least I think that's how they all work. After about twelve months of using mercurial daily I haven't really got to grips with its model(s). If anyone knows better than me then feel free to edit this answer so it's correct.
How I actually use these things in practice.
I'm working on a single shared repository with about 20 other people. I make many experiments and lightweight branches in my own private repository, which never get pushed to our main central repository. Occasionally once an experiment has worked out I'll modify the main line and push a changeset into the central repository, from which it will find its way to everyone else's machine.
I'll occasionally push some changesets to a co-worker if they're one of the people who's comfy with how mercurial works. But several people are a bit scared of it and prefer if I send them diffs that they can apply with patch.
For experiments I expect to be short lived and private, I just let lightweight branches happen where they may, and remember what's going on. If I feel my memory slipping about a twig that's been around for a bit, I bookmark it.
I use local tags to mark revisions I might like to come back to one day. They make interesting past states easier to find.
I myself almost never make non-local tags or named branches (except by accident, and I destroy them if I do). But our release people do. Our released major versions all have their own named branches off from the main line, and minor versions have tags on those branches. That ensures that these important branches and tags look the same to everyone.
Again, I've no idea whether this is how one's supposed to use mercurial, but it seems to be a model that works well for our size of team.
If three or four of us wanted to collaborate on an experiment, that would probably be worth a named branch, which we'd probably share between ourselves but not push to the central repo. I don't know how well that would work out!
The biggest difference is that a bookmark is automatically moved forward when you commit. Here's an example:
hg init
..edit a file..
hg commit -m 'my commit' # creates revision 0
hg tag -r 0 mytag # creates revision 1
hg bookmark -r 0 mybookmark # doesn't create a revision
hg update 0 # get back to r0
..edit a file..
hg commit -m 'another commit' # creates revision 2
At that point mytag is still pointing to revision 0 and mybookmark is now pointing at revision 2. Also the tagging created a changeset and the bookmark didn't.
Also, of course, the bookmark created a revisio
I'm struggling to find the mercurial workflow that fits the way that we work.
I'm currently favouring a clone per feature but that is quite a change in mindset moving from Subversion. We'll also have issues with the current expense we have in setting up environments.
Using hg pull --rebase seems to give us more of a Subversion-like workflow but from reading around I'm wary of using it.
I think I understand the concepts and I can see that rewriting the history is not ideal but I can't seem to come up with any scenarios which I personally would consider unacceptable.
I'd like to know what are the 'worst' scenarios that hg pull --rebase could create either theoretical or from experience. I'd like concrete examples rather than views on whether you 'should' rewrite history. Not that I'm against people having opinions, just that there already seem to be a lot of them expressed on the internet without many examples to back them up ;)
The first thing new Mercurial converts need to learn is to get comfortable committing incomplete code. Subversion taught us that you shouldn't commit broken code. Now it's time to unlearn that habit. Committing frequently gives you a lot more flexibility in your workflow.
The main problem I see with hg pull --rebase is the ability to break a merge without any way to undo. The DVCS model is based on the idea of tracking history explicitly, and rebasing subverts that idea by saying that all of my changes came after all of your changes, even though we were really working on them at the same time. And because I don't know what your changes are (because I was basing my code off of earlier changesets) it's harder for me to know that my code, on top of yours, won't break something. You also lose the branching capabilities by rebasing, which is really the whole idea behind DVCSs.
Our workflow (which we've built an entire Mercurial hosting system around) is based on keeping multiple clones, or branch repositories, as we call them. Each dev or small team has their own branch repository, which is just a clone of the "central" repository. All of my new features and large bug fixes go into my personal branch repo. I can get that code peer reviewed, and once it's deemed ready, I can merge it into the central repo.
This gives me a few nice benefits. First, I won't be breaking the build, as all of my changes are in their own repo until they're "ready". Second, I can make another branch repo if I need to do a separate feature, or if I have something longer-running, like for the next major version. And third, I can easily get a change into the central repo if there's a bug that needs to be fixed quickly.
That said, there are a couple different ways you can use this workflow. The most simple, and the one I started with, is just keeping separate clones. So I'll have website-central, website-tghw, etc. It works well, especially since you can push and pull between them locally. More recently, I've started keeping multiple heads in the same repo, using the remotebranches extension to help manage them and hg nudge to keep from pushing everything at once.
Of course, some people don't like this workflow as much, usually because their Mercurial server makes it hard to make server-side clones. In that case, you can also look at using named branches to help keep your features straight. Unfortunately, they're not quite as flexible as Git branches (which is why we prefer branch repos) but they work well once you understand how to close branches, and why you can't really get rid of them once you start one.
This is getting a bit long, so I'll wrap it up by encouraging you to embrace the superior branching and merging that Mercurial provides (over SVN). There is definitely a learning curve, but once you get the hang of it, it really does make things easier.
From the question comments, your root issue is that you have developers working on several features/bug fixes/issues at one time and having uncommitted work in their working directory along with some completed work that is ready to be pushed back to the central repository.
There's a really nice exchange that covers the issue well and leads on to a number of ways forward.
http://thread.gmane.org/gmane.comp.version-control.mercurial.general/19704
There are ways you can get around keeping your uncommitted changes, e.g. by having a separate clone to handle merges, but my advice would be to embrace the distributed way of working and commit as often as you like - if you really feel the need you can combine the last few local commits into a single changeset (using MQ, for example) before pushing.
Subversion shop considering switching to Mercurial, trying to figure out in advance what all the complaints from developers are going to be. There's one fairly common use case here that I can't see how to handle.
I'm working on some largish feature, and I have a significant part of the code -- or possibly several significant parts of the code -- in pieces all over the garage floor, totally unsuitable for checkin, maybe not even compiling.
An urgent bugfix request comes in. The fix is nice and local and doesn't touch any of the code I've been working on.
I make the fix in my working copy.
Now what?
I've looked at "Mercurial cherry picking changes for commit" and "best practices in mercurial: branch vs. clone, and partial merges?" and all the suggestions seem to be extensions of varying complexity, from Record and Shelve to Queues.
The fact that there apparently isn't any core functionality for this makes me suspect that in some sense this working style is Doing It Wrong. What would a Mercurial-like solution to this use case look like?
Edited to add: git, by contrast, seems designed for this workflow: git add the bugfix files, don't git add anything else (or git reset HEAD anything you might have already added), git commit.
Here's how I would handle the case:
have a dev branch
have feature branches
have a personal branch
have a stable branch.
In your scenario, I would be committing frequently to my branch off the feature branch.
When the request came in, I would hg up -r XYZ where XYZ is the rev number that they are running, then branch a new feature branch off of that(or up branchname, whatever).
Perform work, then merge into the stable branch after the work is tested.
Switch back to my work and merge up from the top feature branch commit node, thus integrating the two streams of effort.
Lots of useful functionality for Mercurial is provided in the form of extensions -- don't be afraid to use them.
As for your question, record provides what you call partial commits (it allows you to select which hunks of changes you want to commit). On the other hand, shelve allows to temporarily make your working copy clean, while keeping the changes locally. Once you commit the bug fix, you can unshelve the changes and continue working.
The canonical way to go around this (i.e. using only core) would probably be to make a clone (note that local clones are cheap as hardlinks are created instead of copies).
You would clone the repository (i.e. create a bug-fix branch in SVN terms) and do the fix from there.
Alternatively if it really is a quick fix you can use the -I option on commit to explicitly check-in individual files.
Like any DVCS, branching is your friend. Branching a repository multiple ways is the bread and butter of these system. Here's a git model you might consider adopting that works quite well with Mercurial, also.
In addition to what Santa said about branching being your friend...
Small-granularity commits are your friend. Rather than making lots of code changes in a single commit, make each logically self-contained code change in its own commit. Then it will be a lot easier to cherry-pick changes to merge between branches.
Don't use Mercurial without using the Mq Extension (it comes pre-packaged in the default installation). In addition to solving your specific problem, it solves a lot of other general problems and really should be the default way that you work (especially if you're using an IDE that doesn't integrate directly with Hg, making switching branches on the fly a difficult way to work).