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.
Related
When cleaning up branches in git, I have been using something like this to differentiate between old/inactive and new/active branches.
How can I sort all branches by their modification time in Mercurial?
The concept of a branch is just different enough in Mercurial vs Git to make this a bit tricky. Depending on what you really want, the "trickiness" may be that it becomes completely trivial!
Start with hg heads, which shows all heads (see hg help heads for the definition of a head). Each head is a commit, and therefore:
has an ID;
is in one particular branch;1 and
has a date stamp.
It also has a local revision number within your repository, which won't necessarily match the revision number in some clone that has the same commit. That is:
$ hg heads
changeset: 5:5f5df3fc4f1c
Changeset 5f5df3fc4f1c in some clone might be 4:5f5df3fc4f1c or 100:5f5df3fc4f1c or some such. The number in front of the colon is the local revision number.
Now, the dates on commits are up to the machine that creates the commit, so they can be quite wildly wrong. The local revision numbers are assigned sequentially as you add commits to your Mercurial repository, though—so if a local revision number is higher, that means that you introduced the commit later. (Caveat: this could be "a lot later than actually made" if you just now brought new commits in from an old, inactive, but never-before-incorporated clone.)
In that sense, then, the output of hg heads, which is shown by default in reverse local-number order, is already in the order you probably want (or the reverse of it). Things printed later are "less active". So there's probably no work to do here other than to read through the output of hg heads (and check whether there are multiple heads within some branch).
1This differs from Git in that in Git, a tip commit is the commit to which some refs/heads/ name points. That tip defines the branch, but that commit can be in multiple branches! The tip is necessarily a head in the Mercurial sense,2 but there can only be one such head, because it's the branch's name that locates and thereby defines the head / tip commit, and each name identifies only one commit.
2Unless, that is, you mean hg heads --topo, in which case a Git commit identified by refs/heads/name might not be a head after all:
...--o--* <-- refs/heads/midpoint
\
o--● <-- refs/heads/tip
The commit identified by refs/heads/tip is a topological head while that identified by refs/heads/midpoint is not. In Git the midpoint commit is on both branches.
If you do want different sortings, it's harder: instead of hg heads, you must use hg log and use a revision specifier. Note that -r "head() and not closed()" produces the same output as hg heads, so you can start with that. The output from hg log is sorted in whatever order you choose, but defaults to the same local-numeric-revision sorting. See hg help revisions for more.
I am currently using Mercurial for sub-version control in my project. Now I am suppose to work on a new branch 2.7 but I confuse to work with branch 2.6, I have developed the new feature which the feature on 2.7 but I build on 2.6. And now I want to move this feature to branch 2.7 properly but I don't know how can I move it properly. Is there any way?
I would recommend using hg graft, which copies changes from one branch to another and unlike hg rebase is not destructive (relevant if you're doing this for the first time and may be making mistakes or if you need the feature to be present on both branches).
To copy changes to a branch dest-branch, do the following. First update to the branch you want to copy the changes to:
hg update dest-branch
Then, use graft to copy the revisions you want from the original branch, e.g.:
hg graft -r start..end
where start is the first revision you want to graft from the source branch and end is the last revision.
You may encounter conflicts if they can't be merged cleanly, which you have to resolve them (as you'd do in a merge), then use hg graft --continue to graft the remaining revisions.
The magic word is RTFM - hg help rebase
I had a change in my branch and after unseccessfull merge, I tried to revert that unsuccessefull merge with hg up -c but it created a new branch instead. I can merge it into current or discard it or what to do with it?
EDIT:
actually I did the following, I had a branch and committed changes there there. then I wanted to push my changes to server, so I pulled changes, and tried to merge with them, but there were a conflict I couldn't resolve myself and I thought: I'll revert all changes back and merge again - so used hg up -C which I thought, will revert everything I changed during my unfinished merge. But what actually happened, another branch with the same name was created, containing only that changes I committed previously and with the same name as a branch I was working in and I was switched to the branch where I was working, which didn't have my changes. So two questions here: what actually happened and why another branch with the same name was created?
Having multiple heads on the same branch, which I think is what you're saying with "a branch with the same name as current" is a normal situation and, yes, you can use hg merge to consolidate them into one head. Use the hg heads command to find the hashes of the two heads of branch X. Then:
hg update REVISION_ID_OF_ONE_HEAD # changes your working directory to match one of the heads
hg merge REVISION_ID_OF_THE_OTHER_HEAD # merges that head's changes in
hg commit # create a new changeset that is the child of both those heads thus reducing the head count by one
Also #ringding is correct that hg update never creates branches. You either already had them and didn't know or received another head when you pulled.
I stopped using hg fetch to pull and merge in another head for a Mercurial repository because I like to make the commit message say what is merging with what. Furthermore, I am moving from "merge repo1 -> repo2" to a more specific "merge head1guid -> head2guid" format.
How can I automate this so I don't have to list the heads with hg heads then copy and paste the guids for the two changesets into my commit message?
As others have pointed out in comments the one or two parents of a changeset are already stored in a changeset and shown in hg log and other command line views -- You're probably better off not re-storing them.
If you really wanted to you could do something like:
hg commit -m "merging $(hg log -r . --template '{parents}')"
but I always try to put something actually useful in the message like "Merging Jim's work on foo into Alice's work on bar"; there's no new information in re-storing the nodeids of the parents.
Note that command only works when you're committing a merge -- it'll be empty otherise.
In my repo, I have the revisions 1 to 10. I've pushed up to 5 (so the next hg push would publish revisions 6-10).
But I have to interrupt my work now and the result isn't 100% complete. So I'd like to move the revisions 6-10 into a new "experimental" branch to allow someone else to complete the work without disrupting the sources for everyone.
How can I add a branch to a non-tip revision (in my case: Starting with revision 6)? Or should I use a completely different approach?
You cannot apply a branch name after the fact without modifying your history.
The most simple approach is to ask the other users to use revision 5 as the parent for any changes they create. For example, the other users would:
hg clone <your repo> or even hg clone --rev 5
hg update -r 5
work, work, work
hg commit
When they commit a change, it will create a second head on the default branch, but that should not create any problems. You will simply need to merge the two heads together once your experimental changes are complete.
That being said, moving your changesets onto a branch can be accomplished using Mercurial Queues (MQ). The following sequence shows how it be done:
hg qinit (Create a new patch queue)
hg qimport --rev 6:10 (import r6-10 into a new patch queue)
hg qpop -a (remove all patches from your working copy)
hg branch <branch name> (create your new experimental branch)
hg qpush -a (apply all the patches to your branch)
hg qfinish -a (convert all patches to permanent changesets)
Tim already has good suggestions. Additionally you could push your experimental changes into a distinct experimental clone on your central server (I guess you use one). This clone could also be used by other developers to push their not-yet-finished work in order to let others review or continue it. It is also clear that this clone's code is not ready to be used. Once some task is finished, the corresponding changesets can be pushed to the stable repository.
Actually named branches are a good idea for your case, but the fact that their names are burned into history mostly is more a problem than a feature. IMHO Git's branch names are more practically. However, to some extend you could also handle your case with bookmarks, which are pushable since Mercurial 1.7 (not sure here). That is you bookmark revision 5 with something like stable (or whatever you agree on in your team) and revision 10 gets bookmarked with something like Aarons-not-finished-work. The other developers would then just pull stable, except your colleague who is supposed to continue your work, who would pull the other bookmark. However, personally I did not use a such workflow yet, so I cannot say if it performs well in practice.