Merge branches locally - mercurial

I have a repository called 'Myproject' and within that we have a branch "MyProject-new changes"
I have cloned the "MyProject" repository in my local machine as
c:/MyProject
and similarly cloned "MyProject-new changes" as
c:/MyProject-new changes"
Both the repositories have the latest changes after pull and merge.
Now, I need the changes from "MyProject-new changes"(branch) changes merged into "MyProject" locally.
Once I merge, I don't want to commit these changes..I will revert back the changes as the branch changes are being worked. I just want to integrate the new changes and see the results for time being.
Please let me know the following
How do I merge locally the code from "MyProhect-new changes" to "Myproject"
How do I revert back MyProject once I tested it.

So you need a test site where you can test merge. Usually people create separate clone for experiments. This gives you easy way to revert changes — just delete experimental clone. So lets start from making another clone of MyProject and update on the latest commit in branch default.
Suppose revision 25 is the latest revision in branch default. You can update on it with command hg up -r 25.
Suppose revision 37 is the latest revision in MyProject-new changes. You can merge latest changes from MyProject-new changes into branch default with command hg merge -r 37. After that you'll have merge result in your working directory.
Since you work in the separate clone you can commit without doubt. Commit with hg ci -m 'merge with new changes' and test the result. When you finished your tests you can simply delete experimental clone.

The simplest way is to make a complete clone of your repository, merge and test to your heart's content, and throw out the repository when you're done. #Kirill explains how to do that.
But why do that? Maybe you'll come across problems, or small merge conflicts, that you'll fix in the clone. It will be a pity to throw away this work-- you'll probably need it in the future. You could simply keep the clone around, of course, but I suggest reconsidering your premise: Why don't you want to merge the two branches?
You have a main branch (default) and a feature branch new-changes, and you want to safely see how they work together. Here's two ways you can do this without cloning the repository:
To keep the default branch safe, simply merge from default into new-changes:
hg update new-changes # switch to the branch
hg merge -r default
You can now test new-changes and fix any problems. This is a very common workflow: Changes to default are incorporated into long-running branches to keep them from drifting too far apart. When you're eventually ready to unify the two lines of development, merge new-changes into the default line and everything will work correctly.
If you want to keep both branches pure for the time being, you can create a new branch testing and merge both existing branches into it. You can keep it around and eventually merge it into default, or close it if new-changes turns out to be a failed experiment. (Detail: If testing is rooted at the head of one of the branches, there'll be "nothing to merge" from that branch. You'll only need to merge the other one.)
If you don't want to risk messing up your main repo, you can of course clone it and try one of the above approaches on the clone. Once you're satisfied that it worked correctly, push everything back to the main repo.

Related

Mercurial: abandoning multiple, contiguous commits, on the `default` branch

Requirement
I'd like to abandon a line of development on the default branch, winding back to a revision from about 15 change sets back, and have default proceed from there.
My setup
This is a solo development project with one other guy testing infrequently. I push (frequently) to bitbucket for backups and sharing with the tester. Several of the changes I want to abandon are pushed to BitBucket.
Options
Any of these would be fine…
The abandoned change sets to continue to exist in the repo. It would be nice if they could live on their own branch abandoned-experiment-1, say, that I can close and ignore, but this would need them to move on to a retrospectively created branch (which seems like it would be an awesome feature?).
Some kind of merge to happen where I add a new revision to default that is the rollback to the revision I want to continue from.
The change sets to be destroyed, but I suspect there's no way to achieve that without replacing the BitBucket repo and my tester's repo, which I'm not keen on.
I'm not too sure how to evaluate which options are possible, which is best, or whether there are other, better options. I'm also not sure how to actually proceed with the repo update!
Thank you.
You do have several options (Note that I'm assuming that you are dispensing with all changes in the 15 or so revisions and not trying to keep small bits of them):
Easiest is kinda #2: You can close anonymous branches just like named branches; Tag the tip first with abandoned-development if you wish; hg update to the point you wish to continue from; and continue to code as normal. (You may need to create the new head for new development before you can close the old one. I haven't tested it yet.)
Regarding #3: Based on my cursory read, it does appear that bitbucket has a strip command. If you (both locally and on bitbucket) and your tester strip the offending changesets, you can carry on your merry way and pretend like they never existed.
Achieving #1: If you are definitely set on getting them to a named branch, you could strip them at the remote repos and then hg rebase them onto a new branch locally and then close that branch.
Personally, I try not to mess with history when I can avoid it, so I'd go with the easiest.
Mercurial now has (yet experimental) support for changeset evolution. That is you are able to abandon or rebase already pushed changesets. Internally this works by hiding obsolete changesets (i.e. practically nothing is stripped, only new replacement revisions are added to the history, that is why it works across multiple clones).
To extend #Edward's suggestions, you could also update to the last good revision, continue to commit from there and then merge in the head of the bad changesets using a null-merge:
hg up <good-revision>
... work ... commit ...
hg merge <head-of-bad-revisions>
hg revert --all -r .
hg commit -m 'null-merge of abandoned changesets'
This may be what you thought of as option 2.

How do I put a bunch of uncommitted changes aside while working on something else

If I have a bunch of uncommitted changes and want to set it aside while working on something else instead, and then later (f.i. after several days) come back to it and proceed working. What would be the easiest workflow to accomplish this? (So far I have only experience with Mercurial's basic functionality). My usual method was to create a new branch using clone, but there might be better ways.
You have a handful options:
Shelve the items. This saves the changes and removes them from the working directory so the branch can continue. It doesn't create a change-set.
hg shelve --all --name "UnfinishedChanges"
hg unshelve --name "UnfinishedChanges"
Update/Edit: Newer versions of mercurial may need to use
hg shelve -n "UnfinishedChanges"
hg unshelve "UnfinishedChanges"
You can still use --name as an alternative to -n, but mercurial doesn't seem to like --name anymore. Additionally, the --all is no longer required and mercurial will in fact freak out over it.
Patch queue the items using mq. This isn't too dissimilar to shelve in some respects, but behaves differently. The end result is the same, changes are removed and can be optionally re-applied later. When pushed, the patches are logical change-sets, when popped they are saved elsewhere and are not part of change-set history.
hg qnew "UnfinishedWork"
hg qrefresh
hg qpop
hg qpush "UnfinishedWork"
Commit them locally, update to the previous change-set and continue working and make use of anonymous branches (or multiple heads). If you then want the changes, you can merge heads. If you don't want the changes, you can strip the change-set.
hg commit -m"Commiting unfinished work in-line."
hg update -r<previous revision>
hg strip -r<revision of temporary commit>
Commit them to a named branch. The workflow then becomes the same as option 3 - merge or strip when you are ready.
hg branch "NewBranch"
hg commit -m"Commiting unfinished work to temporary named branch."
hg update <previous branch name>
Personally I use option 3 or 4 as I don't mind stripping change-sets or checking-in partial code (so long as that doesn't eventually get pushed). This can be used in conjunction with the new Phase stuff to hide your local change-sets from other users if need-be.
I also use the rebase command to move change-sets around to avoid merges where a merge wouldn't add anything to the history of the code. Merges I tend to save for activity between important branches (such as release branches), or activity from a longer-lived feature branch. There is also the histedit command I use for compressing change-sets where the "chattiness" of them reduces the value.
Patch queues are also a common mechanism for doing this, but they have stack semantics. You push and pop patches, but a patch that is "underneath" another patch in the stack requires that the one on top of it be pushed also.
Warning, as with all these options, if the files have more changes since the temporary changes that you've shelved / queued / branched, there will be merge resolution required when un-shelving / pushing / merging.
Personally, I don't like any of the answers posted so far:
I don't like clone branching because I like each project to have only one directory. Working on different directories at the same time completly messes the history of recent files of my editors. I always end up changing the wrong file. So I don't do that anymore.
I use shelve for quick fixes (just to move my uncommited changes to another branch, if I realize I'm at the wrong one). You are talking about days, no way I'd shelve something for days.
I think mq is too complicated for such an ordinary sittuation
I think the best way is to simply commit your changes, than you go back to the changeset before you start these changes and work from there. There are some minor issues, let me illustrate:
Let's say you have the changeset A. Than you start your changes. At this point you want set it aside for a while. First of all, commit your work:
hg ci -m "Working on new stuff"
If you want, you can add a bookmark to make it easier to come back later. I always create bookmarks to my anonymous branches.
hg bookmark new-stuff
Go back to the changeset before these modifications
hg update A
From here, you work and generate the changeset C. Now you have 2 heads (B and C), you'll be warned when you try to push. You can push only one branch by specifying the head of that branch:
hg push -r C
Or you can change the phase of the new-stuff branch to secret. Secret changesets won't be pushed.
hg phase -r new-stuff --secret --force
To keep local uncommited changes, easiest way for me is just to save them as a patch file.
hg diff > /tmp/`hg id -i`.patch
and when you need to return to previous state:
hg up <REV_WHERE_SAVED>
hg patch --no-commit /tmp/<REV_WHERE_SAVED>.patch
You can just clone your repo multiple times. I tend to have a root clone, then multiple childs from there. Example:
MyProject.Root
MyProject.BugFix1
MyProject.BugFix2
MyProject.FeatureChange1
MyProject.FeatureChange2
The 4 childs are all cloned from the root and push/pull to/from the root. The root then push/pulls from the master repo on the network/internet somewhere. The root acts as your sort of personal staging area.
So in your case, you'd just clone up a new repo and start working. Leave your 'shelved' work alone in the other repo. It's that simple.
The only downside is disk space usage, but if that were a concern you'd not be using DVCS at all anyway ;) Oh and it does kind of pollute your Visual Studio "recent projects" list, but what the hey.
[Edit following comments] :-
To conclude then... what you're doing is completely fine and normal. I would argue it is the best possible way to work when the following are true: 1) it is short-lived 2) you don't need to collaborate with other developers 3) the changes don't need to leave your PC until commit/push time.

Merging from parent branch, did hg incoming path/to/baseline, how do I just merge?

I'm in my branch, and I do this:
hg incoming /path/to/baseline
And I get a few changesets in the output.
Now do I just merge to pull in the changsets to my branch?
hg merge /path/to/baseline
Will my history show what was merged?
As long as I didn't touch those files, it will be automatic right?
You should really try all this out yourself! Make a couple of test repositories:
hg init main
hg clone main clone
and then experiment away. It's easy and safe since you're only playing around on your own machine. (This is actually what happens "behind the scenes" when you ask a question here: I try to make sure that the advice I give really works, so I normally have to run a few tests on a new repository to double-check.)
If you ran the tests, you would see that
You cannot give hg merge a path name (or URL) as argument. It takes a revision as the only argument. You need to hg pull /path/to/baseline to copy the changesets into your local repository and then hg merge.
The history will indeed show what was merged. A merge becomes a merge commit in Mercurial. That is a changeset with two ancestor changesets — both lines of development leading up to the merge are still in the repository.
Merges are without conflicts ("automatic") if the changes made in the two branhces don't overlap. If you edit different files in the two branches then there's certainly no overlap. But you can also edit different regions within the same file and still have a merge without conflicts.
There is a fine tutorial on the wiki and I've also written a beginners guide. I hope that helps.

Mercurial clone cleanup to match upstream

I have a hg clone of a repository into which I have done numerous changes locally over a few months and pushed them to my clone at google code. Unfortunately as a noob I committed a whole bunch of changes on the default branch.
Now I would like to make sure my current default is EXACTLY as upstream and then I can do proper branching off default and only working on the branches..
However how do I do that cleanup though?
For reference my clone is http://code.google.com/r/mosabua-roboguice/source/browse
PS: I got my self into the same problem with git and got that cleaned up: Cleanup git master branch and move some commit to new branch?
First, there's nothing wrong with committing on the default branch. You generally don't want to create a separate named branch for every task in Mercurial, because named branches are forever. You might want to look at the bookmark feature for something closer to git branches ("hg help bookmarks"). So if the only thing wrong with your existing changesets is that they are on the default branch, then there really is nothing wrong with them. Don't worry about it.
However, if you really want to start afresh, the obvious, straightforward thing to do is reclone from upstream. You can keep your messy changesets by moving the existing repo and recloning. Then transplant the changesets from the old repo into the new one on a branch of your choosing.
If you don't want to spend the time/bandwidth for a new clone, you can use the (advanced, dangerous, not for beginners) strip command. First, you have to enable the mq extension (google it or see the manual -- I'm deliberately not explaining it here because it's dangerous). Then run
hg strip 'outgoing("http://upstream/path/to/repo")'
Note that I'm using the revsets feature added in Mercurial 1.7 here. If you're using an older version, there's no easy way to do this.
The best way to do this is with two clones. When working with a remote repo I don't control I always keep a local clone called 'virgin' to which I make no changes. For example:
hg clone -U https://code.google.com/r/mosabua-roboguice-clean/ mosabua-roboguice-clean-virgin
hg clone mosabua-roboguice-clean-virgin mosabua-roboguice-clean-working
Note that because Mercurial uses hard links for local clones and because that first clone was a clone with -U (no working directory (bare repo in git terms)) this takes up no additional disk space.
Work all you want in robo-guice working and pull in robo-guice virgin to see what's going on upstream, and pull again in roboguice-working to get upstream changes.
You can do something like this after the fact by creating a new clone of the remote repo and if diskspace is precious use the relink extension to associate them.
Preface - all history changes have sense only for non-published repos. You'll have to push to GoogleCode's repo from scratch after editing local history (delete repo on GC, create empty, push) - otherwise you'll gust get one more HEAD in default branch
Manfred
Easy (but not short) way - default only+MQ
as Greg mentioned, install MQ
move all your commits into MQ-patches on top of upstream code
leave your changes as pathes forever
check, edit if nesessary and re-integrate patches after each upstream pull (this way your own CG-repo without MQ-patches will become identical to upstream)
More complex - MQ in the middle + separate branches
above
above
create named branch, switch to it
"Finish" patches
Pull upstream, merge with your branch changes (from defaut to yourbranch)
Commit your changes only into yourbranch
Rebasing
Enable rebase extension
Create named branch (with changeset in it? TBT)
Rebase your changesets to the new ancestor, test results
See 5-6 from "More complex" chapter
Perhaps you could try the Convert extension. It can bring a repository in a better shape, while preserving history. Of course, after the modifications have been done, you will have to delete the old repo and upload the converted one.

Why does mercurial merge committed changes in the working copy?

I've been using Mercurial for a few weeks now and don't understand why when Mercurial comes to merge committed changes from two repositories it does it in the working copy?
Surely the merge could happen without the use of the working copy removing the need to shelf changes etc.
It just doesn't seem necessary to involve the working copy. Am I missing something?
There is only one working copy per repository, by definition:
The working directory is the top-level directory in a repository, in which
the plain versions of files are available to read, edit and build.
Unless your file system descends from Schrödinger's cat, you cannot have two versions of the same file at the same time, thus you cannot have two working copies.
Nevertheless, it's indeed theoretically possible to use something like a ephemeral clone (per #Ry4an) to act as the working copy of a merge, resolve conflicts there, commit, then make it disappear. You'd get a beautiful merge changeset and your intact working copy.
I can think of several ways to achieve this:
Petition hg team to do it in core
Write an extension to implement the ephemeral clone or some other way
Shelve with a temporary changeset
Shelve with MQ
I would strongly recommend #4, as I would for almost all workflow scenarios. It took me a few good days to grok MQ, but once I did I've never had to turn back.
In an MQ workflow, your working copy is always the current patch. So for the merge situation you would do:
hg qrefresh
hg qpop -a
hg update -r<merge first parent>
hg merge [-r<merge second parent>]
hg commit
hg update qparent
hg qgo <working copy patch>
You don't have to pop all patches in #2. I always do that whenever I need to deal with real changesets to avoid mixing them up with patches.
Solution #3 is really the same as #4, since a patch is a temporary changeset by definition (this is really the only thing you need for understanding MQ). It's just different commands:
hg commit -A
hg update -r<merge first parent>
hg merge [-r<merge second parent>]
hg commit
hg update -r<working copy changeset parent>
hg revert -a -r<working copy changeset>
hg strip <working copy changeset>
If you want to keep the working copy changeset and continue to commit, simply update to it in #5.
From your question it seems like you already know #4 but don't like shelving. I think shelving is good because merging is a fundamentally different task than coding (changing working copy), and shelving makes the context switch explicit and safe.
I didn't write Mercurial, so I can't say why they did it that way, but here are some of the positive results of that decision:
you can look over the results of the merge before you commit it
you can edit the results of the merge before you commit it
you're encouraged to commit frequently
If you really want to do a merge and have stuff in your working dir that you can't bear to commit don't bother with shelve just do:
cd ..
hg clone myrepo myrepo-mergeclone
hg -R myrepo-mergeclone merge
hg -R myrepo-mergeclone push myrepo
On the same file system clone is near instantaneous and uses hardlinks under the covers so it takes up almost no space past that of the temporary working copy.
As mentioned in the chapter "Merge" of HgInit:
The merge command, hg merge, took the two heads and combined them.
Then it left the result in my working directory.
It did not commit it. That gives me a chance to check that the merge is correct.
Such check can include conflicts in merge, that the user has to review:
In KDiff3, you see four panes
The top left is the original file.
Top center shows Rose her version.
Top right shows Rose my version.
The bottom pane is an editor where Rose constructs a merged file with the conflicts resolved.
So you need a working directory (a view for the merge) in order to resolve fully a merge.