Mercurial Patch Queue Use Cases - mercurial

I use mercurial patches in the following cases:-
When I need to pull from a remote repository and have outstanding uncommitted changes. Then I simply create a patch, qpop it, pull from the remote repository, and then import the patch again.
When I need to upload patches to reviewboards. I simply make a patch and upload it.
How else do you use Mercurial Patch Queues? I feel that its a very powerful Mercurial extension and that I am not using it to its fullest potential.

The Mercurial wiki has a good section on use cases:
In summary:
Saving the current state of the working copy so you can easily revert to it later on
Preventing a "tangled working copy" - if you're halfway through a change and want to change something else
Provide mutable, rearrangeable commits so you can get 'history' looking just right before pushing.

You don't really need Mercurial patches for this. If you have outstanding uncommited changes when you pull, they will be merged with the tip.
Example:
C:\>hg init db
C:\>cd db
C:\db>echo >file1
C:\db>echo >file2
C:\db>echo >file3
C:\db>hg ci -Am codebase # Create a code base with 3 files.
adding file1
adding file2
adding file3
C:\db>echo a change >>file2 # Outstanding change to file2.
C:\db>hg st
M file2
At this point we'll clone the database and commit a change that we can pull.
C:\db>hg clone . \db2
updating to branch default
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\db>cd \db2
C:\db2>echo a change >>file3
C:\db2>hg ci -m "file3 change" # Commit a change to file3.
Back in the original database...
C:\db2>cd \db
C:\db>hg st # Still have uncommitted change
M file2
C:\db>hg pull \db2
pulling from \db2
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
C:\db>hg st # We have the new history, but haven't updated.
M file2 # file2 has uncommitted change.
C:\db>type file3 # file3 is unchanged.
ECHO is on.
C:\db>hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\db>hg st # We've updated, and file2 *still* has
M file2 # uncommitted change.
C:\db>type file2
ECHO is on.
a change
C:\db>type file3 # But file3 now has committed change
ECHO is on. # that was pulled.
a change
So the moral is, you can just pull and update, even with uncommitted changes. If there are merge conflicts, normal merge behavior occurs as well.
For patch exporting hg export <rev> will export patches for review.

When you create a patch queue on Bitbucket, it lists some of the common uses for patch queues in the right pane. Their explanation is very good and answers your question directly. Quotes from it are below.
Patch queues are good for:
Developing features you intend to submit for upstream review
Because patches in patch queues can
be modified, they provide an ideal way
to develop a feature in a
history-tracked manner, while still
allowing you to easily incorporate
feedback
Experimenting with adding a new feature
Patch queues don't clutter your
project's history, so you can safely
use them as a way to quickly try out
an idea, and keeping it in version
control, without cluttering up your
project's history with failed
excursions. If you decide to keep the
experiment, you can easily turn a
patch queue into a set of traditional
Mercurial commits
Maintaining private customizations for another project
Because patch queues are not part of
the official change log for a project,
they are ideal for maintaining private
customizations for an upstream
project. For example, you might
maintain a patch queue that makes
program better integrate with your
company's workflow
Patch queues are not good for
Long-running branches
Because patch queues are highly
volatile, they do a poor job tracking
the long-term history of your source
code. For this reason, long-running
branches, such as those that
correspond to product releases, should
be kept in repositories or named
branches.
Group development
Patch queues do not track merge
history, which makes them a poor
choice for doing group development,
where you really wish to see when a
given set of features was merged into
a repository. When in doubt, you
should stick to a traditional fork,
but mastering the power of patch
queues will give you tremendous
flexibility in your workflow, and
provide you with greatly enhanced
collaboration abilities.

MQ is a great tool to manage concurrent development. Blatant self-plagiarism and self-promotion from my own answer:
3 Use MQ with one patch (or multiple consecutive patches) per project.
Pros: simple and easy.
Cons: must qrefresh before switching and rebuild after; tricky
and risky if projects are not
orthogonal.
4 Use one MQ branch per project.
Pros: ultra flexible and scalable (for the number of concurrent
projects)
Cons: must qrefresh and qcommit before switching and rebuild after;
feels complicated.

I use MQ for developing on top of a big Subversion repository I don't want to checkout with hgsubversion or something similar. In my working folder I initiate a new .hg repo and a Mercurial Patch Queue. I track the svn revisions with HG and my patches are on top. Whenever I feel to update the svn state, I pop all the patches, run svn update and push and refresh the patches again. When I'm confident my series is okay for commit, I can qfinish my patches one by one. (Currently a new Subversion feature "shelve" is under development, but every time I tried that, it did not work well enough, so I still use that MQ approach.)

Related

Mercurial Workflow: Need to track file in my local working copy, but not push to "trunk"

This is my setup:
I have a main Mercurial repository (call it trunk). When I want to work on a feature, I do a clone and start working on it (usually add a bookmark as well).
I use various tools to do my work, which tend to generate convenient text files in the directory. It would be very helpful for me to track those files as well. However, I need to ensure those files do not get pushed to trunk.
In a sense, I'd like a "parallel" Mercurial repository in that directory where I can track these files.
How do people manage this? I'm open to using (stable) Mercurial extensions. Ideally, I do not want to "remember" to remove stuff before pushing to trunk.
There are two possibilities: patch queues and phases. Probably for what you want to do, phases are the less-friction approach. But there is no really "parallel" solution to my knowledge.
Have a look at hg help phases for an overview and hg phase for the command to manipulate the phase of a changeset.
To be sure you never push to trunk inadvertently, you have to make your commits "secret" by default (in your HOME/.hgrc):
[phases]
new-commit = secret
Then hg push will never allow to push anything by default, you would have to selectively change the phase of the changesets you want to push.
You could also not use the above configuration and use the --secret option of hg commit when committing something you want to keep for you, but it is too risky to forget.
Note that, both with patch queues and phases, you have to be proficient with history rewriting with hg histedit, to reshuffle around the commits.

Mercurial: graft vs. record vs. qrecord vs. shelve vs. transplant vs. dirstate vs. queue

I am new to Mercurial and still somehow in the evaluation process, so these four concepts are kind of confusing for me. Some are mentioned to be an equivalent to Git's Staging/Index concept, or some even a better one than Git's Staging.
How do the four commands hg graft, hg record, hg qrecord and hg shelve (and hg transplant, but this is explained in Graft vs. Transplant already) compare to each other, and how the concepts of queues and the dirstate? In which use cases is one choosen over the other?
I know there are help pages for each one, but it still is difficult to figure out what each one does as VCS in general is a new topic for me.
The design of Mercurial simply does not include the concept of a staging area. That is, there is no intermediate state between local modification and commit.
Here is an overview of each of the concepts you mentioned:
hg graft is the equivalent of git cherry-pick. It copies a commit from one branch to another. A typical use case for this feature is to copy a bug fix from one release branch to another. This command replaces the older (and now obsolete) hg transplant extension.
hg record and hg qrecord are similar to git add --patch. They allow you to interactively select hunks for commit. So if you modified several different areas of one file, you could select which areas (i.e. hunks) you actually want to commit and which you want to leave as local modifications.
qrecord is only available if you have mq enabled. It commits to an mq patch rather than a standard commit.
hg shelve is similar to git stash. It allows you to temporarily set aside local modifications to your files (or hunks of a file). These modifications can then be unshelved when you are ready for them.
dirstate is an internal class of of the Mercurial source code. It is not exposed to the user.
Mercurial Queues (also know as mq) are probably the closest you will get to a staging area in Mercurial. Here is a description from the Mercurial wiki:
Changes are maintained as patches which are committed into Mercurial.
Commits can be removed or reordered, and the underlying patch can be
refreshed based on changes made in the working directory. The patch
directory can also be placed under revision control, so you can have a
separate history of changes made to your patches.
mq is often used to polish/rework commits that you are testing locally, but have not pushed to a public location. Some people also use it to maintain a set of modifications to 3rd party code.

Mercurial commit only tip

In my setup I have a central Hg repo to which I'm pushing my local changes. Say in my local clone I have a series of local commits and then I want to push the changes to the central repo. How can I push only the final state without including all of the "small" local commits that I made?
I want this because sometimes I dont want to pollute the central repo's history with all of the small local commits that I made.
Why would you want to do that? Committing small changes makes it easy to revert something. If you collect everything in one big commit, reverting a small change might not be as easy.
I agree with bjorn (and I'm upvoting his answer), what you're doing isn't a great idea -- meaningful history is a good thing. If you can't be talked out of it then what you're trying to do isn't just push the last changeset but a new changeset that is a combination of all those changesets. The easiest way to do that is to use the collapse extension, though mq or even export/import can do it. The key there is that in collapsing multiple changesets into one you're rewriting history and you're going to remove your existing changesets and replace them with that new combined changeset. Doing so violates the immutability of history that makes Mercurial so trust worthy.
How to do this without any extensions is explained in the mercurial wiki page ConcatenatingChangesets.
That page also links to a few alternative approaches with hg extensions, like the CollapseExtension.
It is possible to rewrite your history using the mq extension. Suppose the revisions you want to collapse are revs, 5,6,7 with 7 being the tip. You would accomplish this via:
# Import the revs you want to collapse into mq
# mq will create patches for each revision from 5:tip, with the name
# <local rev number>.diff
hg qimport -r5:tip
# Goto the first commit
hg qgoto 5.diff
# Fold in the other commits successively. Aside from shell magic, there is
# no command line way to specify multiple patches at once.
hg qfold 6.diff
hg qfold 7.diff
# Commit the new mq patch as a changeset of its own
hg qfinish 5.diff
Now, your repository contains only a rev 5 with the contents of what was previously revisions 5, 6, and 7.

Hg post-merge commit message, best practice?

I find myself doing the following a lot:
C:\Code>hg pull
pulling from http://server/FogBugz/kiln/Repo/Project/Rebuild/trunk
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 4 changes to 4 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
C:\Code>hg merge
4 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, dont forget to commit)
C:\Code>hg commit -m "Merged"
C:\Code>hg push
pushing to http://server/FogBugz/kiln/Repo/Project/Rebuild/trunk
searching for changes
remote: kiln: successfully pushed 2 changesets
My question is, what is a better/more useful commit message to use after merging a pull from the repository. Are there any best practices that people use in distributed version control systems for this sort of thing?
If you use the fetch extension it automates the pull,merge step into one step, fetch. The message it auto-generates is something along the lines of "automatic merge". The hg developers seem to think this is reasonable as the extension is now distributed with the base.
Merge messages don't seem to be contain a particularly high amount of information. Your message seems reasonable.
[[ offtopic, we sometimes use them as an opportunity for a pun on the word merge]]
There is no one way so here is what I have tried to adhere to.
On commit messages:
Jus remember that those messages are the only strings that would connect you to some one who is try to decipher the reasons for the commit.
Key is to provide a description that is going to be a useful commentary on code development.
So when some one uses hg log , he has a nice commentary on how the software is being developed.
Some good practices:
Link it with your bug management system:
fixes #3456, new feature #2435 etc
or a more descriptive one of what changes it is bringing in the repo
Give credits
In fact, what I do mostly is. Look at
the current state of "hg log" and see
what useful message would mean a
logical progression in understanding the latest commit.
As long as "merg" is in the message somehow, we've had fun using the opportunity to fill our mercurial logs with hilarity. For example, we've used merge messages such as "real-estate mergage loans are at an all time low" or "a Merge Griffin television production."
You can collect all the newly added changesets' commit messages into a file by
$ hg log --rev 'reverse(p2():ancestor(p1(),p2())-ancestor(p1(),p2()))' \
--template '{desc}\n' \
> commit-message.txt
then manually edit commit-message.txt, and finally use it as the log message:
$ hg commit -l commit-message.txt
You could use the rebase extension, so hg pull --rebase would rebase your repo to the central repo's tip. This negates the need for merging after a pull.
I added an alias for it:
[alias]
pure = pull -u --rebase
Works well for us.
More details are at the RebaseProject page.
For mundane merges, where you're only working with one repository, I think just "merge" is fine. Usually you don't even know everything that got merged in because it's all other people's changes anyway.
The one time I would suggest being more verbose would be when you're working with more than one repository. If you have a devel repo and a stable repo, and you're pulling bug fixes in from stable, I would just mention that in the merge: "merging with stable". Those merges tend to be bigger, so it helps explain them to people who come along later.

Merging changes to a workspace with uncommitted changes

We've just recently switched over from SVN to Mercurial, but now we are running into problems with our workflow. Example:
I have my local clone of the repository which I work on. I'm making some highly experimental changes to our code base, something that I don't want to commit before I'm sure it works the way it is supposed to, I don't want to commit it even locally. Now, simultaneously, my co-worker has made some significant improvements/bug fixes which I need. He pushes his commits to our main repository. The question is, how can I merge his changes to my workspace without the requirement that I have to commit all my changes, since I need his changes to test my own code?
A more day-to-day problem we have with the exact same workflow is where we have a couple of configuration files which are in the repository. Each developer makes a couple of small environment specific changes to the configuration files, but do not commit the changes. These couple of uncommitted files hinders us from making any merges to our workspace, just like with the example above. Ideally, the configuration files probably shouldn't be in the repository, unfortunately, that's just how it has to be for here unnamed reasons.
If you don't want to clone, you can do it the following way.
hg diff > mylocalchanges.txt
hg revert -a
# Do your merge here, once you are done, import back your local mods
hg import --no-commit mylocalchanges.txt
There are two operations, as you've discovered, that makes changes from one person available to someone else (or many, on either side.)
There's pulling, which takes changes from some other clone of the repository and puts them into your clone.
There's pushing, which takes changes from your repository and puts them into another clone.
In your case, your coworker has pushed his changes into what I assume is your central master of the repository.
After he has done this, you can pull the latest changes down into your repository, and merge them into your branch. This will incorporate any bugfixes or changes your coworker did into your experimental code.
This gives you the freedom of staying current on other coworkers development in your project, and not having to release your experimental code until it is ready (or even at all.)
So, as long as you stay away from the Push command, you're safe.
Of course, this also assumes nobody is pulling directly from your clone of the repository, if they do that, then of course they will get your experimental changes, but it doesn't sound like you've set it up this way (and it is highly unlikely as well.)
As for the configuration files, the typical way to do this is that you only commit a master file template into the repository, with a different name (ie. an extra extension .template or similar), and then place the name of the real configuration file into the ignore filter.
Each developer then has to make his or her own copy of the template, rename it, and change it in any way they want, without the risk of committing database connection strings, passwords, or local paths, to the repository.
If necessary, provide a script that will help the developer make the real configuration file if it is long and complex.
Regarding your experimental changes, you should commit them. Often.
Simply you commit them in a clone you don't push. You only pull to merge whatever updates you need from other repos.
As for config files, don't commit them.
Commit template files, and script able to generate complete config files from the template.
That way, developers will only modify "private" (i.e. not committed) config files with their own private values.
If you know your uncommitted changes will not collide with the merge commit that you are creating - then you can do the following...
1) Shelve the uncommitted changes
2) Do the pull and merge
3) Unshelve the uncommitted changes
Shelf effectively stores your uncommitted changes away as into diff (relative to your last commit) then rolls back those files in your local workspace. Then un-shelving then applies that diff, bringing back your uncommitted changes.
Tools such as TortoiseHg have shelf built in.