We are converting the cvs repository which has two branches (one is the MAIN and the other is the FEATURE,rest all can be ignored) into a mercurial repository.
We are using the inbuilt tool convert with the following command.
hg convert cvs_source_dir hg_new
where cvs_source_dir = Updated Directory with only Feauture branch changes from CVS.
hg_new= new name of mercurial repository .
After converting ,the hg_new repo has all History data from CVS.
when we did an hg update it points to MAIN branch code .
And if we update it to FEATURE to get the code from FEAUTURE branch as per CVS , by using
hg update FEAUTURE , all the files which dont have a revision in the FEAUTURE branch is getting deleted.
How can this be solved?
If I understand correctly, branch FEATURE doesn't have some files that exist in branch MAIN, so when you hg up to branch FEATURE, these files are missing.
I think it is a feature that hg up brings your working directory into the status when you committed (-c will check the uncommitted changes), so the files that do not exist in branch FEATURE will gone.
This post shows a method to get the file you want from another branch. If you have a list of files, iterate the list and get every file to your current working directory.
[Updated]
A graph to show how to make it right:
(1) your current status
A -- B -- C -- D (MAIN)
\
- E -- F -- G (FEATURE, missing files)
(2) step 1:
A -- B -- C -- D (MAIN)
\
- E -- F -- G (FEATURE, missing files)
\
-H (FEATURE, a head adding all missing files from A)
(3) step 2:
A -- B -- C -- D (MAIN)
\
- H - (rebase) - E' -- F' -- G' (FEATURE, missing files)
Related
In my project, I haven't been using hg remove, hg mv or hg addremove due to ignorance. Consequently, every time I've renamed or moved a file, the history of that file has been messed up and now when I look at an individual file's history, I will only see a portion of the history.
What I'm looking for is a way to go back and retroactively fix all of those renaming mistakes so that the file history will stay together. What I imagine would be most likely is a way to edit the data in ".hg\store\data" to make this work. I've been experimenting, and I see the lines copy: and copyrev: in the data for the files I've renamed, so I suspect that has something to do with it.
Assume that I have control of the central repository and that there are no clones of it currently.
Summary:
Since you have full control of the repo this can be 100% fixed using normal hg commands.
The principle idea is to insert new changesets in the right places which effectively correct the original ones.
Let's say your history looks like this:
A-B-C-*
(* is your working folder)
and it was in B that you renamed a file in the filesystem without renaming it in hg.
Do this:
hg up A
hg revert -r B --all
hg mv oldfilename newfilename
hg commit -m <message>
The key here is using revert which is used to copy changes from a changeset into your working folder. This only works this way because you have updated to the predecessor of the changeset you are reverting.
at this point your history looks like:
A-B-C
\
B'-*
where B' is the "corrected" variant of B. Continue with:
hg rebase -s C -d B'
and you have:
A-B
\
B'-C-*
You can now clean up by doing:
hg strip B
leaving just:
A-B'-C-*
Of course where I used revisions like B you need to type the actual revision # or hash.
You could also use TortoiseHG or some other GUI to do a lot of these steps.
This answer covers the situation where you do NOT have full control of the repo. Its a little trickier and you can't get quite as clean of a result, but it still can be dealt with using normal hg commands.
The principle idea is to insert new changesets in the right places which effectively correct the original ones, and merge them after the fact.
Let's say your history looks like this:
A-B-C-*
(* is your working folder)
and it was in B that you renamed a file in the filesystem without renaming it in hg.
Do this:
hg up A
hg mv oldfilename newfilename
hg commit -m <message>
at this point your history looks like:
A-B-C
\
B'-*
where B' is the "corrected" variant of B. Continue with:
hg up C
hg merge B'
hg commit
and you have:
A-B-C-D-*
\ /
B'
If you look at the file history of the file in question, it will look something like this:
o D merge
|\
| o B' rename file
| |
o | B change where the file should have been renamed
|
o A some earlier change
/
o ...
|
o ...
So the history is all linked together for the file. Its just a little weird that B looks like it started from nowhere (because it actually did).
I have the following versions
v 3
v 2
v 1
I want to create a new version, v 4, that looks exactly like v 2. I do not want to create a new branch.
I have tried:
Right-click v 2 and then "browse at revision" and then 'revert to revision' and 'revert all file'. Committing this does create v 4 looking like v 2, but it also creates duplicate '.orig' copies of all the files, which are a bother to delete.
Right-click v 2: "Update". This creates a new branch, which I do not want. This used to work without creating a new branch, but it now longer does and I don't know what is different.
EDIT: there can be any number of version between the one that I want to copy and the latest version.
Backout v.3:
Select this changeset in CSET-view - RClick - Backout
hg update tip
hg revert -r V2 -C
hg commit -m deja vu
I have two named branches, SPRINT_009 and SPRINT_010. Some changesets have been committed to SPRINT_009 that I would like to merge into SPRINT_010. I was able to merge the changesets from branch_one back into default without any trouble. I am having problems merging the changesets from branch_one into branch_two.
default A -- B -- C -- G -- H -- I -- J -- K -- L -- N -- O -- P
\ \ /
SPRINT_009 D -- E -- F ----------------- ---------- ----------
\
SPRINT_010 M
Here are the commands I am using:
hg update branch_two
hg merge branch_one
However I get the following message:
abort: merging with a working directory ancestor has no effect
Does anyone know what exactly I am doing wrong?
**EDIT: I've added a picture of the graph. The drawing is conceptual **
The problem was that I hadn't performed an hg pull before attempting the merge. Normally we do our development on a Windows machine using TortoiseHg. We modified the name of one of our resources on the support branch, from fooBAR to fooBar and ran into the mercurial case folding problem. We were trying to get around this by merging the branches on a Linux box. I am so used to using TortoiseHg that I forgot the most basic of commands!
Is the most reliable method to go one-by-one, using the backout command for each of many changesets, or is there a way to create one big reversal changeset to cover a whole bunch of [edit: non-contiguous] changesets.
If one-by-one, does order matter? (Should one go last-to-first?)
Does the best method differ if there are merges among different sub-projects along the way?
Does this tend to go smoothly in your experience? :-)
If you have no merges along the way, you can either back out every individual change (in reverse order), or, if there are many of them, do it with one big inverse patch.
If you have good changesets atop the ones you need to back out, better commit the inverse patch on top of the most recent bad changeset, then rebasing them onto the tip of the branch.
1 -- 2 -- A -- B -- C -- 3 -- 4
\
C'B'A'
$ hg up C
$ hg diff -r C:2 > backout.diff
$ hg import --no-commit backout.diff
$ hg ci -m "Backout A, B, C"
$ hg up 4
$ hg rebase -s C'B'A -d .
There will be problems if you want to back out merge changesets, see this wiki page for more information.
In such a case, if possible, consider re-doing the branch and stripping the old lineage. Otherwise, you might have to abandon the branch altogether, salvaging the good changesets via graft or transplant.
There is --collapse option for rebase.
Helgi's answer can be upgraded into:
1 -- A -- 2 -- B -- 3 -- C -- 4 -- 5
\
C' -- B' -- A'
$ hg update --clean C
$ hg backout --rev C --message "Backed out changeset: C"
$ hg backout --rev B
$ hg commit --message "Backed out changeset: B"
$ hg backout --rev A
$ hg commit --message "Backed out changeset: A"
$ hg rebase --collapse --source C' --dest 5
$ hg commit --message "Backed out C, B, A"
which will result in the following
1 -- A -- 2 -- B -- 3 -- C -- 4 -- 5 -- C'B'A'
However, backing out in separate branch may result in [logical] conflict in the subsequent merge.
1 -- A -- 2 -- B -- 3 -- X -- 4
\ \
B' -- A' -- M
if X depends on A or B, then M will have conflict (at least logical conflict).
What I came up with is inelegant, but got the job done, despite that the changes I needed to back out were interspersed with other work and had some internal branching. Here's what I did. (Comments and improvements are welcome.)
Got a list of all of the changesets (which I then used to generate the commands below):
hg log -r 'keyword(xyz)' --template '{rev}\n'
Generated a patch for each changeset:
hg diff -p -U 8 --reverse -c 15094 > 15094.rev.patch
hg diff -p -U 8 --reverse -c 15095 > 15095.rev.patch
...
Then, applied each reverse patch. Here the order matters, last-to-first:
hg import -m "reversing changeset 15302" 15302.rev.patch
hg import -m "reversing changeset 15292" 15292.rev.patch
...
This process was interrupted several times for merges that didn't go through automatically, where I had to manually apply changes to a file from its .rej file and then manually commit, before picking up the imports where it had left off.
Finally (in another clone... did I mention I did this all in a clone?) I compressed the whole set of reverse changesets into one changeset using hg histedit -o and its fold command.
Now I've got a single changeset that I should be able to reverse and apply if I decide to put the work back in at a later date (Although if I cross that bridge, I might apply the "forward" patches piecemeal again in order to get better blame/annotate information)
This is how you can do it with TortoiseHg.
Of course you can do the same with the command line.
Given this history, where you wan't to get rid of changeset A, B and C:
1 -- 2 -- A -- B -- C -- 3 -- 4
First update to revision 2.
Then rebase the first of any later revisions you wan't to keep - in this case revision 3.
Your history now looks like this:
1 -- 2 -- A -- B -- C
\
3 -- 4
Now update to revison 4.
And finally use "Merge with local" to merge revision C onto revision 4.
At this point it is crucial that you select the option "Discard all changes from merge target (other) revision".
The description may not be the most logical, but it means that you merge the old tip C back to the default branch - but without the changesets A, B and C.
The result is:
1 -- 2 -- A -- B -- C --
\ /
3 -- 4
Commit and you're done.
If you don't want the "backout" changesets in your history, you could also do something else:
Make a clone of your repository, but only up to the last changeset that you don't want to get rid of.
See Mercurial: Fix a borked history for an example how to do this.
If your repository was a local one, that's all you have to do.
But if the bad changesets were already pushed to a central repository, you'd need server access to delete the repository there and replace it by your clone.
Plus, if someone else already pulled from the repo with the bad changesets, they need to delete and re-clone (otherwise the bad changesets are in the central repo again as soon as one of the other people pushes again).
So it depends on the circumstances whether this solution is a good one for you...
I have a local mercurial repository (for now) within which I have already made several commits, each commit is a self contained bug fix. Is it possible to pick which of the bug fixes (commits) I want to be included when it is time to build a release version of my application.
To elaborate, assuming A, B, C, D, and E are commits I have already done to my repository and each of them relates to a bug fix like so:
A <- B <- C <- D <- E <- working dir
I need to be able to for example pick which of the bug fixes will go into the release version (this depends on the time allocated for deployment as well as testing outcomes). So for example I might get a report saying the release should only contain bug fixes A, C and D.
Is it possible to construct a release version containing only the A, C and D commits (Keeping in mind that each commit is self contained and does not depend on the other commits to actually be there)?
Probably having a branch for each bug fix and then merging into a release branch is the easiest way to accomplish this (or is it not?), but the current situation at hand is as described above with no branches.
This isn't the normal work mode of Mercurial (or git). A repository can only contain a changeset if it also contains all of that changeset's ancestors. So you can't get D into a repo without also having A, B, and C in there.
So here's:
What you Should have Done
Control the parentage of your changesets. Don't make C the parent of D just because you happen to have fixed D after C. Before you fix a bug hg update to the previous release.
Imagine A was a release and B, C, and D, were all bug fixes. If you do a loop like this:
foreach bug you have:
hg update A
... fix bug ...
hg commit
hg merge # merges with the "other" head
then you'll end up with a graph like this:
---[A]----[B2]--[C2]--[D2]----
| / / /
+-[B] / /
| / /
+-----[C] /
| /
+---------[D]
and now if you want to create a release with only, say, B and D in it you can do:
hg update B
hg merge D
and that creates a new head that has A + B + D but no C.
Tl;Dr: make a change's parent be as early in history as you can, not whatever happens to be tip at the time.
What you can do Now
That's the ideal, but fortunately it's no big thing. You can never bring exactly D across without bringing C (because C's hash is part of the calculation of D's hash), but you can bring the work that's in D into a new head easily enough. Here are some ways, any of which will work:
hg export / hg import
hg transplant
hg graft (new in 2.0)
hg rebase (only possible if you haven't yet pushed)
Any of those will let you bring that patch/delta that's in D over -- it will have a different hash ID and when some day you merge D in for real (using merge) you'll have duplicate work in two different changesets, but merge will figure it all out.
If this was my tree and it hasn't been pushed anywhere, I'd (assuming an empty patch queue and MQ enabled):
hg qimport -g -r B: # import revisions B and later into mq as "git" style patches
hg qpop -a # unapply them all
hg qpush --move C # Apply changes in C (--move rearranges the order)
hg qpush --move D # Apply changes in D
hg qfin -a # Convert C & D back to changesets
hg push <release server> # Push them out to the release branch
Then you can hg qpush -a; hg qfin -a to get B & E back into changesets.
Final Result:
---A---C---D---B---E
Advantages:
Nobody needs know you didn't do things in this order to start with (evil grin)
You could modify any of the change-sets whilst doing this
Alternatively, with graft in 2.0:
hg update -r A # Goto rev A (no need to do anything special for A)
hg graft C # Graft C on to a new anonymous branch
hg graft D # Graft D
This will give you
---A---B---C---D---E
\
--C'--D' <-You are here
An hg push -r D' should just push the new, cherry-picked, head.
You can then hg merge to get one head again with B and E included.
Advantages:
Non destructive, so true history is kept, and no chance of loss if you muck up
hg tags the new changesets with the hash of the original version, so totally trackable
Probably a little simpler.
While it's somehow strange way and release-policy, you can do it in different form. You have to manipulate with two main objects: changesets and branches
Version 1
You use two branches (default + f.e "release 1.0"). Default branch is mainline of your work - all changesets commited to this branch. At release-time, you branch first needed-for-release changeset into (new) branch, transplant or graft rest of needed in release changesets from default to this branch, head of release 1.0 will be prepared for release this way.
Next release will differ only in new branch name
Version 2
One branch used, MQ extension added. Variations:
all changesets are MQ-pathes and only needed for release are applied to repo
changesets are changesets, only unwanted for release converted to mq-pathes, later qfinish'ed and returned to repo