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.
Related
We are using Mercurial. I think there is a problem with a changeset. To make sure, I want to go back to the state before that changeset.
How do i do that ?
You can use hg up {REVISION}~1 to update your working copy to the state before the problematic changeset.
When you don't already have published the changeset, you can use hg strip to remove the changeset (warning: strip is a destructive operation).
If the changeset is already published, you can use hg backout at the top of the branch to get mercurial to reverse-apply the changes of the problematic changeset.
I have tried the
hg log --rev "branch([changeset])"
but what I got is a collection of all the changesets in this branch.
What I do want to get is the name of the target branch (e.g. default) instead of the whole collection.
Is there a way to achieve this goal?
That's... not what revsets are for. You want to do something rather different:
hg log --rev [changeset] --template "{branch}\n"
See hg help templates.
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.
I'd like to get an hg status list for a range of revisions, and also filter the list for a given branch name.
e.g. The issue with this command is that it includes changes from multiple branches, and I'm only interested in a particular branch:
hg status --rev 150:175
Is there a way to add an additional filter by branch for this list with hg or a mainstream hg tool?
You can do this using revsets:
hg status --rev "150:175 and branch(<BRANCH_NAME>)"
I believe that you can use revsets (hg help revsets) to do this. There are a large number of options for selecting revisions, but I think that what you want would be something along these lines:
hg status --rev "150:175 and branch(mybranch)"
Revsets can be tricky at times, but they are very powerful, and so well worth reading about them in hg help.
I want to remove a changeset from history but hg export does not work for merge changesets (see https://www.mercurial-scm.org/wiki/Export). Is there a way to use hg pull for a range of revisions? For example, say I want to remove revision 999 I want to be able to say:
hg init NewRepo
hg pull ../OldRepo -r 0:1000
hg pull ../OldRepo -r 1000:tip
Any ideas?
Pull can't pull a range of revisions because every mercurial revision that exists in a repository must have all of its ancestor changesets in that revision too. So if you do:
hg pull ../oldRepo -r 1000
you get all of revision 1000's ancestor revisions too.
In general, mercurial is about building an immutable history -- if you regret a changeset you don't remove it you create a new one that undoes the work of the changeset you no longer like. If you can't abide having full history in your repo you need to use something like the strip or convert extension. Both work as advertised, but provide plenty of opportunities to shoot yourself in the foot. If you can stand it, just undo the onerous changeset in a subsequent changeset and move on.