How to 'hg merge' without affecting the working directory? - mercurial

Suppose that:
I have a repo called MyRepo.
I have uncommitted changes in my working directory.
I do a pull from Repo1 and that creates a branch in MyRepo
I want to do a merge of what I already had in my repo with what I have just pulled.
As described here, the merge process changes the state of the working directory.
In my scenario, I don't want to loose the uncommitted changes that are in my working directory because at that point, I'm interested in changing the state of MyRepo; not the state of my working directory.
Is there a way to go through the merging process, including resolving conflicts manually, without affecting the content my working directory? Can this process be done in temporary files only? Or should I shelve my changes, do the merge and then unshelve to restore my working dir to the state it was before the merge?

Use shelve or attic extensions to temporarily stash your changes while you merge.

You could clone your repository to your latest checkin, merge the changes with the clone, commit, and then pull the new changeset from your cloned repository back into your current one.

You can't do that. As the documentation says, merge really is a working tree operation. Resolving conflicts without testing the result is crazy. Either shelve or commit the changes and then do the merge. If you don't want the commit to be visible anywhere, you can commit the change, update to the previous revision, merge the new branch, apply the temporarily committed patch and strip that temporary branch.

Just do it in a clone.
Clone MyRepo to MyRepo-merger, which will pull over all the committed changes, but not your uncommitted changes
Inside MyRepo-merger do a pull from Repo1.
Inside MyRepo-merger do all the hg merges you want
Inside MyRepo-merger push to either Repo1 or the original MyRepo
Pushing back to MyRepo won't alter the working dir of MyRepo, so that's a safe action.
Remember in Mercurial that clones are incredibly fast and cheap -- on modern file systems they use hardlinks under the covers so they're not even taking up much space on disk.

I'm pretty new to mercurial, but couldn't you clone from your local repository and copy your working copy over to the clone? You could then run your merge in the original? You'd preserve the state of your working copy in the clone while being free to allow the change of the original's working copy.
Test this first. I've never done it in hg.

Related

Commit changes to another repo

I use two mercurial repositories, one for the current stable version and one for new development. I accidentally developed a new feature inside the current stable repo and now I want to commit the changes to the new dev repo and not to the current stable repo. Is there a way to do this? I have not committed any of my changes yet.
Use
hg diff >changes.patch
To create a patch of your changes. Then, go in the other repo, update where you need your changes to be, and issue
hg import --no-commit changes.patch
With the proper folder to changes.patch You should then be at the same place you were on the other repo, too.
However, if both repos are equivalent, whether you commit and push your changes from the current repo or the other, they could eventually be replicated on both, so think about the necessity of moving the changes across repos. Use branches to handle different feature development.

creating a new branch in mercurial: "abort: push creates new remote head"

I am trying to do something very simple: create a new branch. But I messed up. Where did I make the mistake, and how do I fix it?
I am the only user of Mercurial. I had revision 54 committed and pushed to remote repository. I wanted to create a branch based on revision 53, so I updated my local copy to revision 53, made changes, and committed (ignoring the warning about "it's not the head"). Then when I am trying to push to remote repository, it says
abort: push creates new remote head
Maybe I needed to tell Mercurial that I want to create a new branch? If so, how and at what point?
Thanks!
You tell Mercurial that it can go ahead with
$ hg push --force
You need to force it since multiple (unnamed) heads are normally discouraged. The problem with them is that people that clone the repository wont know which one to use. But since you're the only user you can just go ahead and push.
The alternative is to use a named branch (with hg branch) and then you'll use
$ hg push --new-branch
to allow the creation of a new branch on the remote. Named branches have the advantage that they make it easy to distinguish the two branches. They have the disadvantage that they are permanent. Permanent means that you cannot remove the branch name from the changesets on the branch — the name is literally baked directly into the changeset.
Bookmarks provide a way to have non-permanent branch names, see hg help bookmarks.
Another reason for this error: probably there are some UNMERGED changes form the central repo in your default branch.
hg up default
hg merge
hg ci -m "Merge"
hg pus
I did this. Using TortoiseHg ... this is how I fixed it:
In settings, I enabled the Strip extension then right clicked the branch i did not want, Modified History - strip. If you have pushed, then it needs to be stripped from all other repositories, including workmates who have pulled your unwanted branch.
An alternative is to merge the unwanted branch into your main branch, but do not take any of the changes from that branch - I am unsure of how that mechanism works.

Discard a local branch in Mercurial before it is pushed

Many times it happens that I have few commits on my local Hg repository which I don't want to push and sometimes I want to remove the local branch altogether. But I cannot rollback more than one commit which leaves me no choice than creating a new clone and download the whole repository again. This feels stupid, since if I could just delete my local branch which has not affected the remote repository in anyway, then I wouldn't have to create and setup a new clone. So, is it how it is in Mercurial or is there some way to discard a local branch?
Thanks!
If you enable the mq extension (bundled with Mercurial), you can use hg strip. Be careful, though, as this will modify the history of your repository. The safe method is to clone your repository up to the revision preceding the creation of the branch you want to discard, then to pull the remaining changesets that you want to keep.
I know its too late but it may be useful for any one:
If your branch is not pushed yet.
First rollback changes hg rollback only if you have done commit but
not yet pushed
Second run hg update --clean
Third run hg branch any-existing-branch
Fourth run hg pull -u
If you find yourself doing this often perhaps you should be using bookmarks instead of named branches. http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/

Copy Mercurial repository with uncommitted changes

I have an mercurial repositry a bitbucket.org and a clone on my wokstation. The clone has some uncommited (unfished) work in it. I have to copy these clone to my laptop because I will be on a trip for one or two weeks and want to do some work.
Is there a simple and save way to copy the repository with its uncommited changes to another device? I knew I could clone the repo from the workstation to my laptop but this won't copy uncommited work.
Simply copy the entire repository's folder.
Just commit that work. That work needs to be finished to be committed is left-over CVS/SVN thinking. Commit it, and then update to its parent and work on whatever else you want to work on. When eventually the work is done you're pushing a changegroup not individual changesets, so no one will have the uncompiling stage at the end of those interstitial changesets on them.
Avoiding committing work in Mercurial (using shelve, attic, copying repos, etc.) is the only way to lose work -- avoid it.
I prefer my first answer (commit it) but if you positively can't bring yourself to commit unfinished work then you should be using Mercurial Queues with a patch queue that lives in its own repository. This is easily done with:
hg qinit --create-repo
Then you import your uncomitted changes as a patch using:
hg qnew --force name-for-this-work
then you can:
hg qcommit -m "work in progress"
Then you can qclone that repo and get both the work in progress and the base repository on which it's overlayed. More details are available in the Mercurial book's chapter on queues.
Really, though, there's just never a good reason to have uncommitted work for more than an hour or two.

How do I get changes to propagate to all subrepos in Mercurial?

I have recently switched from Subversion to Mercurial for source control and in doing so have split up one repository into several. I used subrepos to manage the dependencies between repositories. The problem is that pull is not suprepo aware so I have to go into each subrepo and pull changes in order to update a repository. Is there a better way to do this?
pull is not suprepo aware
hg pull should be subrepo aware, provided it is used with the -u (--update) option.
The hg update should, when it comes to subrepos, take them into account:
Whenever newer Mercurial versions encounter this .hgsubstate file when updating your working directory, they'll attempt to pull the specified subrepos and update them to the appropriate state.
Subrepos may also contain their own subrepos and Mercurial will recurse as necessary.
The OP CoreyD adds:
That has not worked for me.
I create two repos /repo and /sub and I clone sub into repo (/repo/sub).
Then I create an .hgsub file in /repo with this a line like this sub = ../sub and commit it.
When I make changes to /sub and then do an update in /repo /repo/sub is unchanged.
Am I doing something wrong?
That looks about right:
SubRepos or submodules (for Git) are all about referening a precise configuration (changeset ref for hg, or commit ref for Git, as explained in this SO question)
When you change anything outside of /repo, you don't change the .hgsubstate file within /repo recording the exact configuration (changeset reference).
Hence no change at all.
You could rather do your /sub changes directly in /repo/sub, commit them, then commit /repo.
Then, a clone of /repo would have the new configuration.