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.
Related
Is there a way to graft a commit onto somewhere other than the current revision?
The documentation makes it sound like there isn't:
hg graft [OPTION]... [-r REV]... REV...
copy commits from a different location
And I don't see any parameters that can be passed to hg graft to do so. I'm surprised though that hg rebase allows this with the -d flag, but hg graft doesn't. Just like how sometimes I want to rebase a branch to somewhere other than the current revision, sometimes I want to graft a branch to somewhere other than the current revision.
You can use the rebase extension to achieve this. Do hg rebase -r <rev> -d <dest> --keep to rebase the onto while keeping the old rev.
Fundamentally the answer is "no", but you can still get the desired effect.
The help text for graft says "copy changes from other branches onto the current branch
" which implies that if you first update to the destination changeset, you can get the result you want.
Presumably you want to use graft to make an actual copy, vs rebase which would "move" the changeset. So this will get that result although it requires several steps.
To summarize:
hg up <destination revision>
hg graft <source revision>
hg up tip
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.
I am using Mercurial.
I have some uncommitted changes but I am on the wrong branch, how do I update to the right branch and take the changes with me?
For uncommited changes you can use the Shelve extension:
hg shelve --all
hg up correct_branch_name
hg unshelve
I asked on irc
mpm said
hg diff > mychanges; hg up -C somewhere; hg import --no-commit mychanges
which I had considered but is what I was trying to avoid.
d70 said
i think you can easily do it by "hg update"ing to a changeset that is a
parent of the branch you're trying to switch to, and then "hg update"ing to the
tip of that branch
so I did that.
hg up -r <shared root rev>
hg up branchIwant
I asked about "why" and was told "you are not allowed to update across branches" which didn't make sense to me at first. Then I realized that because I went through the shared root rev, it isn't across branches.
I usually use
hg qnew
hg qpop
hg up -c <target-rev>
hg qpush
hg qfinish qtip
But I also use jrwren’s approach of going through an ancestor quite regularly.
I'm trying to figure out how to merge branches from a separate repo into the current.
I have the following:
PJT1
- contains branches default and foodog
PJT2
- contains branch default
from PJT2, I do the following:
$ hg fetch -y ../PJT1 -r foodog -m "this is a test"
Now, if I look in PJT2, I see the correct files and changes. However, I if I do hg branches, I get the following:
[someone#myhome pjt2]$ hg branches
foodog 1:c1e14fde816b
default 0:7b1adb938f71 (inactive)
and hg branch reveals the following:
[someone#myhome pjt2]$ hg branch
foodog
How do I get the contents from PJT1's foodog branch into PJT2's default branch?
You need to merge, but keep in mind changes on branch foodog will always be on foodog -- branches never go away but they can be hidden. This sequence of commands is as close as you'll get to what you're asking:
cd PJT2
hg update default # just in case you were somewhere else
hg pull ../PJT1 -r foodog # that gets you foodog
hg merge foodog # that merges the changes into default
hg commit # commit the merge
hg update foodog # go to the most recent change in foodog (note: it is not a 'head')
hg commit --close-branch
After the merge hg branches will still show foodog unless you do hg branches --active which only shows branches that have heads on them. After the commit --close-branch you won't see foodog unless you do hg branches --closed.
It's because branches in Mercurial never go away entirely (a design feature) that they're often reserved only for life-long things like release-1.0 or stable. For short-lived efforts like bugs and features consider using bookmarks instead. Here's a great comparison of the two: http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial
You could also try using the rebase extension. It would look something like this:
hg fetch -y ../PJT1 -r foodog -m "this is a test"
hg rebase --source <sRev> --dest <dRev>
The rebase action will detatch changeset sRev and all descendents and apply the group of changes to changeset dRev. By default, the changes will be applied on the default branch. So, in your case, sRev would be the first changeset on branch foodog and dRev would be the default changeset you want to apply them to.
Finally, If you want to override this and preserve the source branch name you can use rebase option --keepbranches. Your questions indicates that this is exactly what you do not want to do, but it should still be noted.
I am trying to clean up some cloned repositories I have, basically converting clones into named branches.
What's the easiest way to do this?
The only way you can make them named branches would be to rewrite their history, because the name of the branch is part of the history. However, if you can survive without having the branches be named in the past (the future is fine) then you can just pull all the repos into the main one (without merging!) and then label your branches once they're in.
For example, if you have MainRepo, Feature1Repo, and Feature2Repo, you would do the following:
$ cd MainRepo
$ hg pull ../Feature1Repo
$ hg pull ../Feature2Repo
Now, if you look at the DAG in something like TortoiseHg, you'll see a couple different heads. From here, you just hg up and hg branch:
$ hg up feature1headrev
$ hg branch Feature1
$ hg up feature2headrev
$ hg branch Feature2
From here forward, you'll have your named branches.
Note: If the hg pull complains about the repositories not being related, you can do an hg pull -f, which will create multiple tails in the repository. This is usually not how true branches are, but it is sometimes useful.
You could use hg export to create a bundle of changes, and then hg import them to your new branches.
Let's say you have a common base, revA, and then two clones which each diverge from revA into revB and revC.
In the first clone: hg export -r revA -r revB > revB.patch
In the second clone: hg export -r revA -r revC > revC.patch
Now you have two patches containing all the changes made in the clones.
In the original repository:
hg up revA
hg branch branchB
hg commit
hg import revB.patch
hg up revA
hg branch branchC
hg commit
hg import revC.patch
And now you've got two named branches diverging from revA. If you have merges in the areas between revA->revB or revA->revC, I'm not sure this will preserve them perfectly.
Another alternative is to use the transplant extension. Or you could just push your clones' changes into one repo, and then move the heads that creates to new branches.