Graft vs. Transplant - mercurial

The release announcement for Mercurial 2.0 mentions a new graft command, which on first sight looks similar to the transplant extension. What is the difference between these two? Does cherry picking with graft solve any problems that existed with transplant, and if so, what are these?

Graft uses Mercurial internal merging, while transplant relies on patch mechanism. Therefore graft should be able to handle three-way-merges better than transplant currently does.

From the documentation of hg graft it looks like opposite to the transplant extension graft only handles branches within the same repository but can't handle different repositories.

Related

In Mercurial what's the difference between hg graft and hg rebase

I know Rebase is a (bundled) extension, while Graft is a core feature (that replaced the Transplant (bundled) extension).
graft is documented as:
copy changes from other branches onto the current branch
This command uses Mercurial's merge logic to copy individual changes from other branches without merging branches in the history graph. This is sometimes known as 'backporting' or 'cherry-picking'.
rebase is documented as:
Rebase allows moving commits around in Mercurial's history (using a series of internal merges). This has many uses:
moving changesets between branches
"linearizing" history
reordering changesets
collapsing multiple changes into one changeset
Both seem to use merging to move or copy changesets between branches.
Graft copies. Rebase moves. But rebase --keep copies.
So often it seems I can accomplish my goal of copying a changeset either way.
Does it matter which one I use? When should I prefer one over the other?
E.g. should graft only be used when copying to a different named branch? Or only when there's just a single changeset?
Edit: Could it be that rebase is a potentially unsafe superset of graft, but can only be used with draft changesets during development for editing local history, while graft is a safe subset of rebase that can be used with public changesets during maintenance for backporting?
hg graft allows "cherry-picking," as you noted in your question. For example, you can run hg graft -D "2085::2093 and not 2091" to copy only some changes from another revision. By comparison, hg rebase (with or without --keep) will grab whatever changeset you specify and all of its decendant changes.
Also, rebase allows you to collapse changesets (with --collapse). As far as I can tell, graft does not.
One more difference I have noticed: hg graft --edit 123 lets you graft revision 123 to the working directory and edit the commit message. I can't find an hg rebase equivalent. I should point out, though, that hg histedit also allows for editing the commit message while rebasing.
There are probably other differences that I am not thinking of. SO community: feel free to point those out in the comments, and I will happily revise this answer to make it more complete.
See the graft documentation and the Rebase Extension documentation for more details.

Reverse of hg backout

I'm looking for a method like hg backout, but in reverse. Specifically, instead of undoing the diffs associated with a given changset, I want to actually apply them on top of an arbitrary revision. Is this possible?
hg transplant (bundled extension) or hg graft (core, since 2.0) do this.

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: how to cherry pick during merging

Consider I have the following situation:
I have a branch br_foo from revision 4. After that there are 3 more changes made on default branch: 6, 7 and 8. I'd like to only merge changes 7 and 8 to br_foo. Is there a way to achieve this in mercurial?
Graft v Transplant
Depending on which version of Mercurial you are using, you will probably use either the new Graft functionality in Mercurial 2.x or the older Transplant Extension for earlier versions of Mercurial.
The Graft command
This was announced recently (Nov 2011) so I haven't had a chance to work with it myself.
This command uses Mercurial's merge logic to copy individual changes
from other branches without merging branches in the history graph.
This is sometimes known as 'backporting' or 'cherry-picking'. By
default, graft will copy user, date, and description from the source
changesets.
The Transplant Extension
I've used it for just this scenario. A little snippet from the description ...
This extension allows you to transplant patches from another branch or
repository.
It records the original changeset ID in the transplanted changeset,
and avoids transplanting previously-transplanted patches.
It can also be used to rebase a branch against upstream changes
(including dropping changesets that have been adopted upstream), to
rewrite changesets and to cherrypick some changesets.
Since mercurial 2.0 (released on November 1st 2011) this is handled by the new core command graft:
This command uses Mercurial's merge logic to copy individual changes from other branches without merging branches in the history graph. This is sometimes known as 'backporting' or 'cherry-picking'.
See also this other question.

Can I branch in Mercurial without cloning the repository?

Recently, I've started experimenting with Mercurial, due to the fact that it always attracted it because of its simplicity and "just works" principle. Or at least, that's how others always described it.
They also usually described it as "practically the same as git with just a few minor changes you won't notice" - only for me to discover it isn't quite so.
I'm having problem with Hg branches. Pardon me if this is an overly simple question, but in git one has a working directory and a repo (.git). In the repo one has revisions, and branches, and can jump from one to another.
I'm having trouble finding a similar model in Hg. As far as I can see, for Hg to have a "branch" one needs to clone a repo to another directory? Is there a way Hg could work just like git does - i.e. one working dir., and one repo, in which you can do things as regard to branching and revs?
Mercurial supports a very rich set of ways to branch. See http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
In brief, you can create a named branch by running
hg branch NewBranch
and switch to that branch using
hg up NewBranch
or switch back to trunk using
hg up default
In Mercurial, if you go to any particular revision, you can always edit your working copy and commit, thereby making another "head." Merging works on head revisions by default. You can use hg head to see what heads are in your repository. This seems to be the most "idiomatic" way I have found branching to work in Mercurial.
Take a look at section about branches in my answer to "Git and Mercurial - Compare and Contrast" here on StackOverflow.
The information about various options available for branching in Mercurial (anonymous heads, not-propagated (I think yet still) bookmarks, and global (world-wide) commit labels aka named branches) was taken from http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/, and expanded using feedback on #mercurial IRC channel on FreeNode.