views:

56

answers:

4

I recently started using Mercurial and like the way I have VCS protection for my individual development without checking it in to the central repository, then I push to the central repo when I have something ready for the rest of the team.

When I "hg commit" I write a commit message relevant to the addition since the last time I committed. I may have 5 or so local commits before I'm ready to push stuff to central. When I do push, if I don't specify a revision, all of my local commits and their messages get added to the central repository, but I don't want to clutter the central log with all my local smalls steps. When I push and specify the local revision, I think only that revision and its commit message get pushed, right?

The problem is, I want to push with a commit message that summarizes all of my local "offline" work, because that's what I'm really adding. However, the commit message that gets pushed is whatever I most recently wrote. Say I'm working on feature A and I have five local commits for it; "Added A.1" "Added A.2" "Cleaned up code in foo.cpp" and so on, ending with "Added A.4." What I want to log to the central repository is "Added A, cleaned up foo.cpp" but if I push that last revision it just sees "Added A.4." Now, when there have been updates to central I need to merge in locally before I push, my local commit message is "Merged in tip". Clearly that's not a good commit message to push back.

What's a good practice here? I'm not aware of any mechanism to change an existing commit message, or to push with a new commit message. I don't want to make a trivial change to my local repo simply to enter a new commit message before changing; that's just silly. I must be missing something because this seems basic. Or am I not thinking about mercurial the right way?

+1  A: 

I don't believe that Mercurial supports that form of a feature set. The best way to go about that would be along these lines:

1) After your changes are finished, clone your 'central' repository to a new folder.
2) Export patch files of all your changes from your original working repository.
3) Import the patch files in to your newly cloned pristine folder.
4) Commit all the changes at once in the newly cloned folder, and push those changes.

Making a script to do those steps shouldn't be too difficult!

Chris Rueber
The clone is over ssh so the script would need to be interactive, but it seems like this approach would work. Thanks! Is this just not the usage model that is generally accepted?
jasper77
+2  A: 

You're looking for the Mercurial Queues extension. In Mercurial:The Definitive Guide, chapters 12 and 13 cover them in detail.

Niall C.
+1  A: 

When you push and specify a revision, all of the ancestors of that revision that aren't already in the other repository will be pushed. If the changeset depends on those before it, then this is probably the behavior you want.

If you want to send a single changset (and it's independent of it's ancestors) you can reorder you're local history so the changeset you want to send is the ancestor. The histedit extension will allow this. If you want to condense your local changes and send them as a single changeset, you can "fold" them together using histedit.

If you want to get around the issue of having lots of "merging" message, you can rebase your local changes when you pull from the central repository. The result will be that your changes are parented by their latest change and the development history is linear.

Queues are a (good/popular) solution, but designed to solve a slightly different problem (maintaining patches against another repository). Of course, I say that not having ever used the mq extension. If what you really want is to have a local history that's different than the central one (e.g. maintaining all your local messages) then queues are the only solution that I know of.

0x4b
+1  A: 

Pushing five changesets is perfectly acceptable and it will make it easier for others to review the code. Just try to make logically consistent changesets; I usually try to ensure that the code compiles and passes tests after each commit.

There are some extensions (collapse, rebase, histedit, mq) that allow you to alter changesets after the fact. The collapse extension is what you want here: it allows you to collapse (combine) your five local changesets into a single changeset that you can then push to the server.

It is important to realize that they do so by creating new changesets and throwing the old ones away. This has the consequence that you should only use them on private changesets, i.e., changesets that has not yet been shared with anybody else.

If you by accident manage to alter a changeset that has already been pushed to your central repository then it's no catastrophy -- what happens is that you will end up with both the original changeset plus the altered changeset. This is because hg push is append-only and so you cannot alter a changeset that has been pushed to a central repository.

Martin Geisler
I chose this solution because it looks like "collapse" is really what I'm looking for. It will let me commit with abandon for any little improvement I make locally, then tidy up into one or few more comprehensive changesets before sharing my updates. I realize that might weaken mercurial's merging in some cases, if it can no longer see all the little steps taken, so I'll be careful. Thank you.
jasper77