views:

81

answers:

4

I'm assigned the development of a feature for a project. I'm going to work on that feature for several days over a period of a few weeks. I'll clone the central repo. Then I'm going to work locally for 3 weeks. I'll commit my progress to my repo several times during that process. When I'm done, I'm going to pull/merge/commit before I push.

What is the right way push my feature as a single changeset to the central repo? I don't want to push 14 "work in progress" changesets and 1 "merged" changeset to the central repo. I want other collaborators on the project to see only one changeset with a significant commit message (such as "Implemented feature ABC").

I'm new to Mercurial and DVCS so don't hesitate to provide guidance if you think I'm not approaching that the right way.

<My own answer>

So far I came up with a way of reducing 15 changeset to 2 changeset. Suppose changesets 10 to 24 are "work in progress" changesets. I can 'hg collapse -r 10:24 -m "Implemented feature ABC"' (14 changesets collapsed into 1). Then, I must 'hg pull' + 'hg merge' + 'hg commit -m "Merged with most recent changes"'. But now I'm stuck with 2 changesets. I can no longer 'hg collapse', because pull/merge/commit broke my changeset sequence. Of course 2 changesets is better then 15 but still, I'd rather have 1 changeset.

</My own answer>

A: 

I'm not too clear on why you want to merge your changesets locally before pushing up. Perhaps you can avoid having to merge them, by implementing a new feature and committing it as one changeset.

On the other hand, I read somewhere that clones are cheap, so what about cloning yourself a master copy, then when you want to implement a feature: clone your master copy to a feature copy, implement the feature, commit and push the feature clone back to your local master clone.

When all your features are in your master clone, push that up to the central repo. This double-push might rid you of the lost changeset sequence, if you have to merge changesets (I'm assuming here, this is not a fact). All this effort seems like it's just easier committing small and committing often, anyway :)

Smaller commits also make code less likely to error during merges.

Wez
+4  A: 

This is a duplicate question, (whose answer is the CollapseExtension which you found) but I'll take the opportunity to try to talk you out of the practice. :)

Clearly it's not my place to talk you out of trying to compress your changesets, but you might want to consider that half the value of version control is answering "why" not just "what" months and years later. An accurate representation of how a feature came about, and in what stages, might be of future value. Discarding it seems so... unversioncontrolly. Worry less about how pretty your history is and focus on how useful it can be.

Even if you do collapse you definitely should be pushing two changesets, the feature and the merge of the feature. Merge changesets are par for the course and not to be avoided. They have some very important info, namely their parentage, and do a great job of making the feature you've added something that can be moved elsewhere in the tree easily by keeping the merge details out of of the feature details. Don't try to avoid them!

Also, you should be pushing to some repo off your machine at least nightly, right? Set up a development clone on the server that only you access or something.

Ry4an
@Ry4an: Thanks, I appreciate the advise. I want to adopt best practices. If there is nothing wrong with pushing intermediary changesets to a central repo, I'll do that. I just don't want people to complain that I'm polluting the repo.
Sly
Different projects have different attitudes, and there's no "wrong", but yeah, I'd much rather "See someone's work" than not. If I want to see all the deltas combined it's just a 'hg diff -r first -r last' away, but it's not possible to split them back out if they're in a single changeset.
Ry4an
One reason not to collapse too many changes into one changeset could be the bisect feature of Mercurial (or Git). Using bisect it should be possible to (semi-)automatically locate changesets that fail a test. However, I don't know if that feature is really used in real projects, but it would be one reason for having multiple small changesets instead of one changeset containing thousands LOC since locating bugs would be easier. Personally, I would prefer many changesets with useful commit messages over huge changesets unless the repository activity demands it (e.g. the Linux kernel).
Energiequant
A: 

With the bundled rebase extension, see hg help rebase, --collapse option.

Be sure to make a backup before doing that though, as you’re rewriting (local) history.

Laurens Holst
A: 

I'm the OP. I found another solution using the Mq extension.

The workflow would be:


// Clone, enable qinit.
hg clone …
hg qinit -c

// Create new queue
hg qnew -m "Implement feature ABC" FeatureABC

// Work and commit to the queue repo
work on feature
hg qrefresh
hg qcommit -m "wip"

// Work and commit to the queue repo
work on feature
hg qrefresh
hg qcommit -m "wip"

// Work and commit to the queue repo
work on feature
hg qrefresh
hg qcommit -m "wip"

// Now, I'm ready to integrate
hg qpop        //remove my patch
hg pull -u     // get changesets form central repo
hg qpush       // reapply patch, 
do some testing and final adjustments
hg qrefresh    //reapply the patch
hg qfinish -a  // freeze the patch changeset

hg push // push to central as a single changeset

What do you think? It's complex but I think it works. Because of the complexity, I'm not sure I'll do that but it's an option.

Sly