exporting mercurial patch against an old revision - mercurial

I am very new to software development, so this is no doubt a very basic question. I got a mercurial repo of an open-source project. I copied it and worked a bit. Commited. Worked more, then did second commit. So my tree looks like 1(from net) -> 2 (mine) -> 3 (mine) (changed numbers of course).
Now I want a patch to send to the rest of the world. However, I have two patches. How can I make it one?

hg export -a -o FILENAME x:y
Where x is the first revision and y is the last. All it really does is concatenate diffs of each revision in the range into the same file.
Run hg help export for more information.

Related

Create patch for series of existing changesets that were created without using MQ?

I've recently started to work on an open source project which uses Mercurial.
I'm a new user to Mercurial, so I read the HG book and started working.
My goal was to write code and always pull and merge changes from the upstream
so I can stay up-to-date. The area that I am working on is also under heavy
development by others so I do want to merge my changes after a long period of
time. I cloned a repo. So, my workflow is like this:
I created a bookmark mybook
hg up mybook
Write code
3.1 hg commit -m 'new functions'
hg up default
hg pull
hg update
hg up mybook
hg merge default
Go to step 3.
In my mind this is the simplest workflow that allows me to stay up-to-date. I
also have only one HEAD because I always merge.
Since I am not a contributor yet, I am not allowed to push changes to remote
repo.
Recently I wanted to show my work to a project lead and he said send me a patch.
And this is where I am stuck. hg out shows 10 changesets. First of which
appeard already a month ago. They're numbers are 3341, 3342, 3345, 3346, 3349, 3356, 3360, 3365, 3366, 3368. The changeset numer 3368 is the tip.
I've recently read the chapter about the MQ extension. And this extensions seems to be what I need. But the problem is that I wrote code without using the MQ
extension.
So, how can I make use of the MQ extension on already created changesets so that
I can make a patch to send to the project lead so that he can apply it and see
my changes?
I've just issued hg qinit. What's next?
Issueing hg qimport -r 3341 gives
abort: revision 3341 has unmanaged children
Reading the book and googling further does not help me. I need an advice.
PS I've tried not using hg and MQ at all: simple diff -urN old/ new/ but I
want understand how to do it with the MQ.
Thank you.
Yeah, don't use MQ. It's a parallel system, meant for keeping things out of the history, and more important you don't need it.
You were asked for "a patch", not a complete history of your work, so I would recommend sending it in the form of a single before-after diff. hg export will give you a series of diffs, for all the work you've done, including the merges. I find it's far easier to read and review a single diff (before applying it). But instead of plain diff, use hg diff which knows to only look at tracked files, and has a number of other nice features (including the --git option, which provides richer metadata). This should do it:
hg up mybook
hg diff --git -r default > mywork.patch
Before sending it off, do an hg up default and apply the patch to check that it works without conflicts. And mention to the recipient which version of default you are patching against.
Edit: As you can read in the comments, #LazyBadger is a fan of the step-by-step patch generated by export. I prefer the single-step patch
since my history is usually TMI: Nobody cares about all the times I added a forgotten file, or noticed a bug too late and fixed in in the next commit, etc.
Take your pick.

Mercurial: Move a collection of files to an unrelated repository

I have a bunch of files, its actually a c# project and the files related to it, the whole hg repository is a solution with many projects.
I need to move those (with history) to another existing repository .
What is the best way to do this?
Say, you have A and B repositories. Your goal is to extract an 'a' folder in A and merge it with B to make B_with_a, while preserving histories.
1) Extract 'a' in A and make Aa. You can do this with hg convert:
~$ hg convert A Aa --filemap list.txt
where list.txt is
include a
2) Pull Aa to B - to make B_with_a_yet_merged. You have to use -f since they are not related.
~/B$ hg pull ./../Aa -f
3) Merge two branches in B_with_a_yet_merged to make B_with_a
~/B$ hg merge (with the last rev in Aa)
PS.
Don't forget to backup A and B beforehand! When I first did this, I messed up repositories three times.
After a poke around hg commands I found bundle, seemed to have made the trick. More details soon
Update: tried this and didnt work. It brought the files when I unbundled it, and I was able to merge, but for some reason the graph was off.
I just thought I d post for completeness

What exactly does hg pull do?

I'm using Mercurial. What exactly does hg pull do and what other steps need to be in my workflow after I use it?
The main clone is called "farm". I made a clone of it called "myfarm" which I've been developing locally. Now I want to push the changes from my clone to the real clone hosted at googlecode.
So in the context of my own clone "myfarm", I run [hg incoming farm]. This seems to list all the changes that have been made to "farm" since I made my clone of it. Lists a bunch of stuff like:
changeset: 545:edfe4dadf
parent: 549:ea8e55929bcF
parent: 592:dfdf05dbcfA3
user: Some user
date: Some date
summary: Some comments
ok so then I ran [hg pull farm]. I'm left with the following at the command prompt:
pulling from https://blah.googlecode.com/hg
searching for changes
adding changesets
adding manifests
adding file changes
added 6 changesets with 3 changes to 2 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
Questions:
Is everything merged for me already, or do I need to run hg merge farm now?
How will I know if there are conflicts? If so, I'm also not sure if I have to run:
.
hg merge farm
hg merge
I mean, I want to merge the results of the pull, but am not sure which of the above two is appropriate.
I'm used to using svn, so in this case, I would have just done:
svn update (notified of merge changes)
svn ci
Thanks
In the case you've described, you would run hg merge. pull is just a synchronization step, it doesn't modify the local working folders not add any merges or so any other real work.
Joel Spolsky has recently published a good tutorial on version control with Subversion at http://hginit.com. I would suggest having a read through this if you're still not quite up to speed with the concepts. I would recommend reading through the tutorial sequentially (rather than skipping to the "Merge" page) because the examples he uses build upon one another and will be easier to follow if you've read the previous sections.
Hg has an svnbook too.
Chapter 3 clearly explains your problem.
hg merge is indeed what I would do.

Can I clone part of a Mercurial repository?

Is it possible to clone part of a Mercurial repository? Let's say the repository is quite large, or contains multiple projects, or multiple branches. Can I clone only part of the repository?
E.g. in Subversion, you might have trunk and branches. If I only want to get trunk (or one of the branches) I can just request [project]/trunk. If I clone the hg repo I'll get trunk and all of the branches. This might be a lot of information I don't want. Can I avoid getting this?
Alternatively, if I want to have multiple projects in one hg repo, how should I do this? I.e. so that I might just get one of the projects and ignore the others.
Yes you can. I'm sure you've moved on, but for the sake of those who will wander here later, I followed the docs at ConvertExtension, and wrote a simple batch script:
#echo off
echo Converting %1
REM Create the file map
echo include %1 > ~myfilemap
echo rename %1 . >> ~myfilemap
REM Run the convert process
hg convert --filemap ~myfilemap .\ ..\%1
REM Delete the file map
del ~myfilemap
cd ..\%1
REM update the new repo--to create the files
hg update
Name it something like split.cmd, and put it in the directory for the repo you want to split. Say for example you have C:\repos\ReallyBigProject, and a subfolder is C:\repos\ReallyBigProject\small-project. At the command prompt, run:
cd\repos\ReallyBigProject
split.cmd small-project
This will create C:\repos\small-project with a slice of the relevant history of revisions from the larger project.
The convert is not enabled by default. You'll need to make sure the following lines exist in your .hg\hgrc file (c:\repos\ReallyBigProject\.hg\hgrc in my example):
[extensions]
hgext.convert=
#Nick
"E.g. in Subversion, you might have trunk and branches. If I only want to get trunk (or one of the branches) I can just request [project]/trunk. If I clone the hg repo I'll get trunk and all of the branches. This might be a lot of information I don't want. Can I avoid getting this?"
Absolutely. Just use hg clone -r <branch> and get only the branch you want. If you have lots of branches, you need a -r <branch> for each one. <branch> doesn't have to be a named branch: you can simply have multiple unnamed heads (or named heads using bookmark, though those still aren't perfect, because currently they don't show up with push/pull/clone).
Keep in mind that in DVCSes, Mercurial among them, branches are often short-lived and merged back into each other frequently. If you pull a branch you will still get the common history it has with any other branches.
To my knowledge, that's not possible. But compared to Subversrion, cloning the whole repos may not be slower than just a branch from SVN.
Quoting from UnderstandingMercurial:
Many SVN/CVS users expect to host
related projects together in one
repository. This is really not what hg
was made for, so you should try a
different way of working. This
especially means, that you cannot
check out only one directory of a
repository.
If you absolutely need to host
multiple projects in a kind of
meta-repository though, you could try
the Subrepositories feature that was
introduced with Mercurial 1.3 or the
older ForestExtension.
#Nick said:
"This is a pretty big omission since a lot hosting sites only offer one repo. With svn I can effectively have as many repos as I want by only taking one branch from the main one. The subrepos sound like a hack."
Subrepos (aka submodules) are not as ideal as "narrow clones" its true. But at least for having many distinct projects in one hosting site's repository, you can have multiple code-bases in one repository. This won't allow you to slice up different sections of one repository / sub-directories of a project , but it will let you manage multiple projects. What you do is have lots of named branches each rooted at the empty (or null) changeset (i.e. they have no common root revision). It can get a little messy to track the branches but it does work.
For example:
hg init
hg branch project-1
# Changes, commits, repeated as needed
hg update null
hg branch project-2
# Changes, commits, repeated as needed
You now can see all your projects:
> hg branches
project-2 5:42c2beffe780
project-1 2:43fd60024328
The projects are unrelated (though you can merge them):
> hg debugancestors
-1:000000000000
Most usefully: you can clone only the project you want, and the others won't mix in:
> hg clone <repository> -r project-1
The graph for this would look something like this (hg log -qG):
# 5 | project-2 | {tip}
|
o 4 | project-2
|
o 3 | project-2
o 2 | project-1
|
o 1 | project-1
|
o 0 | project-1
You can do this for as many projects as you need, listing each with hg branches, and jumping between them with hg update. This takes some care, because named branch support isn't perfect. It isn't always intuitive for one thing (read about hg clone -u in Mercurial 1.4 -- the pre-1.4 behavior is surprising when cloning). But it does work.
Mercurial and Git only permit cloning on the entire repository. Thus it is recommended that each project gets its own repository.
Mercurial has a forest extension to ease having a "forest" for project repositories. The extension keeps each project in a separate repository, but provides options to update/push/pull all the forest repositories together.
It's possible to ask Mercurial to clone just a branch using hg clone -r branchname (see Mercurial clone from a branch).
With Google's NarrowHG extension extension it's possible to perform a narrow clone (see How do I clone a sub-folder of a repository in Mercurial? for a similar question).
I know that it is nearly 10 years after this question was asked, I I stumbled across
this question by accident.
There is a new mercurial extension call sparse that allows you to do this.
Here's a possible improvement to Vadim Kotov's solution that supports spaces in the small-project name/subfolder:
#echo off
echo Converting "%~1"
REM Create the file map
echo include "%~1" > ~myfilemap
echo rename "%~1" . >> ~myfilemap
REM Run the convert process
hg convert --filemap ~myfilemap .\ "..\%~1"
REM Delete the file map
del ~myfilemap
cd ".\%~1"
REM update the new repo--to create the files
hg update

How can I do a changeset based merge instead of file-by-file based merge with Mercurial?

When performing a merge with Mercurial, it wants to merge conflicting files one at a time which just isn't a productive workflow on large merge sets. Instead, what I would like to do is merge the entire changesets of both heads (like using kdiff3 to diff 2 heads). To me that sounds straightforward but I can't figure out how to achieve it.
So far, the closest I can get is to go through the merge the usual way, leave all the conflicts unresolved (a file at a time...), and then hg vdiff -rHead1 -rHead2 - but vdiff (using kdiff3) doesn't seem to have options for passing the tool an output dir (the current working dir) and instead launches with the output dir as a tempdir (possibly -o is the answer?).
Let me put it another way - I want to use kdiff to merge two heads into my working directory. I want the results in my working dir to be my merge that I can commit.
I must be missing something obvious, I can't be the only one who wants to do this.
I came up with a solution that achieves what I want but I still feel like it's a kludge.
Start with an empty working dir with 2 heads: Mine and Theirs.
Update working dir to Mine:
hg update [My head's rev here]
Perform a merge, but fail all files that Merc can't handle automatically without launching a merge tool and keep "My" files when in conflict:
hg --config "ui.merge=internal:fail" merge
See https://www.mercurial-scm.org/wiki/TipsAndTricks#head-9f405488b6d3b3d092a09aafa28db515ba44c742 for how-to merge/fail details.
Now I've got a working dir with as much as auto could figure out, but any outstanding files still untouched from Mine. (Use hg resolve -l to see the Mercurial's resolution status of current files)
Now I can vdiff my working dir against the Theirs head which gives me the high level, changeset-to-changeset merge that I was looking for.
hg vdiff -r [Theirs head's rev here]
Note: If you're using WinMerge for your vdiffs , then make sure it has an /r switch as an option which will do a subdirectory compare and - if WinMerge config is set to use Tree-View - will give a great tree comparison. From Mercurial.ini:
[extdiff]
cmd.vdiff = C:\Program Files\WinMerge\WinMergeU.exe
opts.vdiff = /e /ub /r /dl other /dr local
Now I can work the entire directory which includes the unresolved files and make project wide changes as necessary (ie. maybe resolving one file requires additional changes in another).
When done use resolve to mark all files resolved for Merc and then commit.
hg resolve -m
Whew! Here's hoping this helps someone else!
I relayed the question to #mercurial on irc.freenode.net a couple of days ago. mpm (the author of Mercurial) gave sort of an answer (it was only half an answer, so I didn't immediately pass it on here). He said that one might be able to do something where you let Mercurial merge the files automatically (and insert the <<<< and >>>> merge markers where there are conflicts).
Then use a merge tool that knows about these markers: this will let you resolve them all at once instead of doing it on a file by file basis. A starting point would be the page on merge tool configuration. It explains that
[ui]
merge = internal:merge
will make Mercurial inserte the merge markers. Here I tested it by making two files x.txt and y.txt which I then modified with conflicting changes in two clones. The merge simply gave:
% hg merge
merging x.txt
warning: conflicts during merge.
merging x.txt failed!
merging y.txt
warning: conflicts during merge.
merging y.txt failed!
0 files updated, 0 files merged, 0 files removed, 2 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
All files were processed in one go, I did not have to confirm anything per file like you describe.
The files now contain merge markers like this:
% cat x.txt
foo
<<<<<<< local
hehe
=======
foobar
>>>>>>> other
The next step is to find a tool that can take a directory tree with such files and let you resolve them. I looked at kdiff3, but did not figure out how to use it to operate on a single file alone, it seems very focused on comparing pairs of files/directories.
I'm not sure how much this half answer helps you -- maybe you also got stuck at this point? But I hope it can help others who want to have the merge markers inserted into all files and then resolve the conflicts by hand.
I think this answers your question.
sounds like you want the extdiff command:
i have these in my ~/.hgrc (I prefer meld, but you can change it to kdiff3, etc)
[extensions]
hgext.extdiff =
[extdiff]
# add new command called meld, runs meld (no need to name twice)
cmd.meld =
With extdiff your merges occur in your working directory, and moreover you can pass any extra parameters to your diff program with -o:
$ hg help extdiff
hg extdiff [OPT]... [FILE]...
use external program to diff
repository (or selected files)
Show differences between revisions for the specified files, using
an external program. The default program used is diff, with
default options "-Npru".
To select a different program, use the -p option. The program
will be passed the names of two directories to compare. To pass
additional options to the program, use the -o option. These will
be passed before the names of the directories to compare.
When two revision arguments are given, then changes are
shown between those revisions. If only one revision is
specified then that revision is compared to the working
directory, and, when no revisions are specified, the
working directory files are compared to its parent.
options:
-p --program comparison program to run
-o --option pass option to comparison program
-r --rev revision
-I --include include names matching the given patterns
-X --exclude exclude names matching the given patterns
Try setting ui.merge. See this page for more details.