How to push just one specific patch in Mercurial Queues? - mercurial

This is what I did :
hg init
hg qnew -m "p1" p1.patch
; some changes
hg qrefresh
hg qpop
hg qnew -m "p2" p2.patch
; some changes
hg qrefresh
hg qpop
Now those 2 patches were separate features and have nothing to do with each other. They need to be independent of each other.
Now I do (because I want only the 1st feature)
hg qpush p1.patch
It says :
applying p2.patch
applying p1.patch
and it gives me both the changes I made !
Am I doing something wrong?
It pushes other patches also when I tell it to push a specific patch.

You forgot one thing: set of MQ-patches is queue (FIFO queue). I.e if you can see more than one patch in hg qseries, you have to remember - qpush|qpop will apply|unapply patches not in random order, but in sequential order: push from bottom to top, pop in reverse order
Random access (and changing order of patches in a series as side effect) is --move option for qpush. In your case (using only one patch at a time) and patches names
hg qpop -a
hg qpush --move p1.patch
hg qpop -a
hg qpush --move p2.patch
In order to avoid mistakes you can redefine qpush (for this repository) in aliases section for always use --move option

Related

Editing the author for specific changesets

At the moment I am looking at transitioning from subversion to Mercurial at work, and as such the Mercurial repository is not yet published.
I have used the authormap argument to transform our usernames to the Mercurial format, which went fine.
Unfortunately two people have been commiting under the same name. The repository is not very large, so I would like to change the authors to match the right people. For that reason I would like to ask:
Is there any way to change the author for a specific changeset, or a list of changesets?
You can use the bundled extension Mercurial Queues (MQ) to change commit authors. Note that MQ will only work as long as history is linear. If there are branches you need to first rebase them off to a temporary side branch, and then after editing rebase them back.
First qimport the changes up till the first changeset you want to modify:
hg qinit
hg qimport -g -r <first-revnr>:tip
Then use qpop or qgoto to navigate to the respective changesets:
hg qgoto <revnr>.diff
And then use qrefresh to change the user info on the currently active changeset:
hg qrefresh -u "Some User <user#example.com>"
You can verify with hg log whether the user was correctly updated. After this, repeat for all other changesets.
When you are done, qpush all patches and use qfinish to finalize the repository.
hg qpush -a
hg qfinish -a
You could as well use the evolve extension. After setting up the extension
hg amend -U && hg prev
for a stack of commits and then hg evolve --all at the end.
Evolve introduces a meta-graph that says which commit replaces which commit.
So when we do hg amend -U a bunch of times, we create commits with a different author that replaced the old commits. hg evolve --all the will use the replacement information to figure out where to move commits that were based on our pre-replaced commits.
Credits to mercurial developers on IRC #mercurial.

Mercurial - Working with Queues similar to Shelves?

I've recently started working with MQ as I like the idea of working on isolated patches and committing without affecting the repo until the changeset is refined enough. Before that, I used to work with Mercurial's shelves extension, but found it a bit unstable. What I'm still trying to figure out in MQ is how to keep patches separate from each other and apply them in no particular order, and across different branches. Here's my normal flow -
1. Start working on a new patch:
hg qnew fix-bug-1234 -m "fix bug 1234"
# do some work
hg qrefresh
2. Get a new feature/bug to work on:
hg qpop fix-bug-1234
hg qnew some-feature -m "implement feature X"
# some work on feature X (perhaps in a different branch)
hg qrefresh
3. At this point, I'd like to get back to working on bugfix, and put aside the feature work. I thought it's as simple as:
hg qpop some-feature
hg qpush fix-bug-1234
# wrap up bug fix
hg qfinish fix-bug-1234
# get back to work on feature
However, MQ seems to always use the latest patch created in the series, and apply it regardless of the qpop/qpush command I'm using. I should note that the files I work on are completely separate as well (though they can sometimes be the same).
Am I missing something here? Should I be using hg qqueue for this? Thanks.
You could use guards. They allow you to maintain an ordering of patches without rearranging your series file, and selectively apply only a subset of patches, still in a stack-ordered fashion.
An example in your case would be:
hg qnew bugfix
# ..hack hack..
hg qrefresh
# want to switch over to working on some feature now
hg qpop
hg qnew feature
# ..hack hack..
hg qrefresh
At this point, you're in a situation where patch feature comes before bugfix in your stack. Now you can use guards to select one or the other, and switch between the two:
hg qpop -a
hg qguard feature +featureguard
hg qguard bugfix +bugfixguard
If you want to work on feature:
hg qselect featureguard
hg qpush
applying feature
now at: feature
If you want to work on bugfix:
hg qpop -a
hg qselect bugfixguard
hg qpush
applying bugfix
now at: bugfix
Note that since you selected the positive guard bugfixguard, MQ leap-frogged over feature (because it's positive guard was different than the one selected) and applied the patch bugfix instead (which did match the selected guard).
Some useful tools when working with guards are hg qseries -v, which will display a G instead of the usual U for a guarded, unapplied patch, and hg qselect -l which will display the guards associated with each patch.
Execute hg qpop -a to remove all patches from the stack
Execute hg qpush --move some-patch to apply "some-patch" without applying whatever other patches may be before it in the patch stack
No, you aren't missing anything. The mq extension does make a pretty strong assumption that patch queues are linear. If you're going to be creating multi-patch features/fixes then qqueue would work… But if your features/fixes are just single patches and you want to be able to apply one with out applying the others, it might be easier to just re-arrange .hg/patches/series (which stores the order that patches will be applied).
I do this (and hand-editing patches) enough that I've got a shell alias:
alias viq='vim $(hg root)/.hg/patches/series'
Alternately, if you don't mind applying multiple patches at the same time, you could use qgoto:
$ hg qser
0 U bug-1234
1 U feature-4321
$ hg qgoto feature-4321
$ hg qser
0 A bug-1234
1 A feature-4321

mercurial push certain revision

I have searched here, but haven't found any question related to this. I got a problem like this in mercurial:
I manage open source project in bitbucket, so i have clone of the source code in my local. But I also using that project for my own live site, so I made 2 clone of bitbucket repo
Bitbucket Repo
|
==local_clone1
|
==local_clone2-> commit1 => commit2 => commit3
(personalization) (bug fix) (add feature)
The question is, I want to push commit2 and commit3 back to local_clone1, so later on I can push to Bitbucket repo. But don't want to push commit1, since it has my personal data.
Wondering how we do that in mercurial?
This can be done without too much difficulty in this case. See Removing history in the Mercurial guide for more information.
Here's the basics of what you'll need to do:
Go to local_clone2
Get the revision number (hg tip will show you) from the current number. We'll call it 731.
hg export 730-731 > ../local_clone1/changes.diff (or wherever you like)
Go to local_clone1
hg import changes.diff
You may need to edit things manually; refer to that guide for more info in that case.
Here are a couple of options:
backout
Given a history constructed as:
hg init db
cd db
echo >file1
hg ci -Am clone # rev 0
echo >file2
hg ci -Am personalization # rev 1
echo >file3
hg ci -Am bugfix # rev 2
echo >file4
hg ci -Am feature # rev 3 <tip>
Then if the current working directory is the tip, the following commands will "undo" the personalization revision:
hg backout 1
hg ci -m backout
The advantage is history remains immutable, but shows the addition and backout of the personalization changeset.
Mercurial Queues
With the mq extension, history can be edited to remove a changeset:
hg qimport -r 1:3 # convert changesets 1-3 to patches
hg qpop -a # remove all patches (can't delete an applied patch)
hg qdel 1.diff # delete rev 1's patch
hg qpush -a # reapply remaining patches
hg qfin -a # convert all applied patches back to changesets.
The advantage is the personalization changeset disappears. The disadvantage is the changeset hashes change due to the history edit, so this should never be done to changesets that have already been pushed to others. There is also the risk of a mistake editing history.

Transplanting into one changeset

I'm trying to move changes from a couple of changesets into one changeset on the other branch. There are other changes in between that I want to skip, so I don't want to simply merge everything.
hg transplant moves the changes correctly, but now I'd like to flatten them into a single commit. How can I do that?
You can fold them by
Backup the repository, a failure during the process can destroy data
transplant the desired changes to the target branch
transform them there into a mercurial queue (hg qimport -r first-to-fold-rev:)
fold them into one patch (hg qpop until the first patch is applied, then hg qfold <<patch name>> the following patches into this one)
Edit the commit message (When there are NO OUTSTANDING CHANGES hg qrefresh -e)
apply the single patch to your repository (hg qfinish -a).
When there are further unfolded patches:
hg qpush until the head patch
hg qfinish -a
Review the new repo state (hg glog/hg incoming)
hg rebase has an '--collapse` option. I think this is what you are looking for.

How to move some changeset to a new branch in mercurial

I want to move a changeset from one branch to another. Basically, I currently have:
A -> B -> C -> D # default branch
And I want:
A # default branch
\-> B -> C -> D # some_new_branch
Where some_new_branch does not exist yet. I am used to git, so I guess there is a simple "mercurial" way I am missing.
One way is to export a patch for B,C,D; update to A; branch; apply patch:
hg export -o patch B C D
hg update A
hg branch branchname
hg import patch
To remove B,C,D from the default branch, use the mq extension's strip command.
Sounds a bit like a cherry-pick operation in git. The Transplant Extension may be what you're looking for.
With Mercurial Queue:
# mark revisions as draft in case they were already shared
#hg phase --draft --force B:D
# make changesets a patch queue commits
# (patches are stored .hg/patches)
hg qimport -r B:D
# pop changesets from current branch
hg qpop -a
#
hg branch some_new_branch
# push changesets to new branch
hg qpush -a
# and make them commits
hg qfinish -a
Without comments:
hg qimport -r B:D
hg qpop -a
hg branch some_new_branch
hg qpush -a
hg qfinish -a
Alternative to transplant or patch, you could use graft.
hg update A
hg branch branchname
hg graft -D "B:D"
hg strip B
Note that changing history is bad practice. You should strip only if you haven't pushed yet. Otherwise, you could still backout your changes.