How to push/pull only your changes to many mercurial branches? - mercurial

I have the following mercurial setup, with 3 or more repositories (all of the are remote)
trunk
branch_a - cloned from trunk
branch_a_me - clones from branch_a
local - cloned from branch_a_me
Inside branch_a_me I committed and pushed several change-sets but now I do have to assure that they are going to reach all the other branches.
I have to mention that even local is in sync with branch_a_me, there are changes that were made to all the other repositories and I do have to be sure that only my changesets are pushed/pulled to the others.
How can I achieve this with mercurial, preferably in a manner that would be easy to replicate the process later?

There's no such command in the repo.
The way it's supposed to be done, is that You merge Your code to places necessary.
So basically what You do is, select the branch to be merged, and the branch to merge Into.
Click merge, and resolve all the conflicts.
This can be automated by some batch script, and telling the repo to resolve all conflicts by taking Your code over the branch that changes are being merged into. NOT THE WAY TO GO.
The Way to go would be to merge Your changes to the MASTER branch, that all over's are inherited from. The moment people will try to merge their changes with the MASTER, they will get Your changes.

Related

Mercurial automatic merge

I'm a newbie in using mercurial and control version system in general,
I know that:
There exists a Central Remote repository
Everybody has a local repository, obtained by cloning the central one creating a branch
Everyone makes changes to a working space area, these changes are then committed to the local repository.
After changes have been performed locally, they are merged with the centralized repository or the centralized repository is overwritten by means of a rebasing
In mercurial when we make a pull and two conditions hold:
the central repository has been changed since we made the last pull.
we updated our local repository since the last pull.
A merge occurs in the local repository.
Mercurial sometimes wants me to make a manual merge, some other times the merge is managed automatically,I would like to know in what situation this happens.
Your workflow is just terrible, your mercurial-lingo is dirty
Read hg help merge
... Returns 0 on success, 1 if there are unresolved files
by checking this exit-code you can always know results of (even unattended) merge and perform needed operations.
But BEWARE:
Rebase uses repeated merging to graft changesets from one part of
history (the source) onto another (the destination).
thus - if you have exit-code 1 on merge, you, most probably, will get merge-conflict also on rebase (and the need of handwork anyway)

How to graft from other repository?

I have two repositories with tho different mercurual named branches, say V1 and V2. The branches are divergent since about one-two years. I'd like to graft some changesets from one repo into the other, without pulling the changes.
I don't want to pull the changes for multiple reasons.
I don't want to conflict developers with history of multiple branches, because there will be enough local branches to care about.
I want to have single branch central repos and developers could accidently push the second branch. The central branches would interact with SVN and should have only one branch per repo. I know I could use central hooks, to prevent such a push, but I don't want questions like, can't push, or how can I do that.
The size of the repo would grow to multiple gigabytes (before pull about 700MB). As I understand, it's because of deficites of current mercurial storage format.
I know, the transplant extension can do the work. I tried it, but I can't force other developers to handle rejects instead of simply use a merge tool. Is there an other way?
In fact there are more then two repos with each a branch, but for the example simplicity two should be enough.
You might be able to do the work in an intermediate repo:
Pull in the changes
Do whatever grafting/rebasing/transplanting you need
Strip out the things you pulled in step 1. or if that doesn't work:
Pull only the changes from the branch you want into the actual repo
You'd end up with a repository that includes your desired change sets, but not all the history from the unwanted branch.
Follow-up to #DanMan
Pull needed branch into intermediate repo
Strip unwanted changesets in clone
hg pull CLONE in real target
Write a tool, a hg-extension or extend the graft command so it can graft from a second repository, similar to the transplant extension.
Yes, the implementation is not so easy as adding the second-repo-functionality in the transplant command. The transplant extension simply uses a patch from an other repo instead of one from own repo. But I think also for graft there is no technical reason, not to do that.
If I understand right, grafting of a single file change is not more than calling the merge tool with the files:
(base) the parent of the to-graft changeset
(my changes) the target revision, on which to graft
(theirs) the to-graft refision
So in order to graft a file change from an other repo, the whole file from other repo is needed before the to-graft changeset was applied (base) and after it was applied (theirs). Technically it should be no problem.
Additionally the implementation
need to determine, which files are affected by the changeset to graft
need to handle deletions correctly
need to handle file renamings (not sure, how complicated it is)
All that should be possible, I see no real technical problems.

how to undo a commit pull

I faced today my first mercurial problem. I was in my repo, I modified a file and I did a
hg commit
hg pull
followed by
hg update
hg rollback
to repair what I've done, (but actually I didn't push anything)
The problem is that when I did the pull (that I should do before the commit, the head changed and so hg heads looks like :
- Modif from yesterday
- My modif
- Modif from last week
and now I see that someone also did another modification (via the http interface). What should I do to repair my local repo, (if possible modifying my summary) and push it after the 2 others modifications.
Thanks a lot. Quiet confusing, was easier on my "one-man" repo..
Your local repo doesn't need "repairing". This is a very standard case that you will see often if you use Mercurial a lot.
The issue is multiple heads.
You can either merge your heads, assuming your working directory is your version and there is only the other head:
hg merge
This will result in a merge changeset (same as if you were merging across branches).
Or you can enable the rebase extension to re-base your version onto the tip of the branch (the other head):
hg rebase --source<YourVersionNumber> --dest<TipVersionNumber>
This will not result in a merge changeset, and will simply transplant your changes on top of the changeset you specify as if they were born of that changeset all along (hence rebase or "new"basing).
Multiple heads is a funny sort of inner-branch branching... you can continue checking stuff in against your own head and change between heads using hg update. We block multiple heads per branch on our server, so our push would fail. I'd advise keeping multiple heads local as they are less clear-cut than branches.
I tend to work with Mercurial in one of two ways:
If the work is large in scale I will branch it off and follow Continuous Integration practices (constantly merging the main branch into my own etc). I then re-merge back into main when I am happy with the end result.
If the work is small in scale I will simply work against main branch and "merge" heads every so often. I say "merge" as I usually use rebase. Re-basing works great if the changes are simple and conflicts are unlikely.
My hard and fast rule: if I can't use rebase I put it on a branch born of main.

How do I merge two Mercurial repos into a single one

I have to separate Mercurial repositories. One is the main trunk for the project, while the other is a branch with a set of additional changes.
There is one central location for the project repository, in which I'd like both the trunk and the branch to be available. What I'd like to do is merge the two repositories into a single one, but still allow the branch to be accessed via tags, or something similar. This would allow developers to check out the main code, but also be able to switch to working on the branch if it requires further changes. I also want to make sure that any code in the trunk doesn't accidentally make it into the branch. Any changes to the branch should be explicit and intentional.
What is the best way to accomplish this?
As Brandon says, just push from the branch repo to the trunk, or pull the branch into the trunk.
You can then choose if you want to merge branch & trunk together, or keep them separate. If you push from branch to trunk, you may get a warning about multiple heads. Just do a push -f if you want to keep them separate. (pull may not give a warning)
You can merge the branch changes to the trunk and still be able to do further work on the branch later if you want. In general, I tag every release so I can easily get back to anything that went out the door.
When you created the branch, did you clone it to another directory? If so, it will be harder to find the branch after pulling it into the trunk repo. You may want to read up on bookmarks to label the branch. Also look at how multiple heads work.
Note: The other option is to use named branches which labels the branch permanently. You wouldn't need to do anything extra to switch over to it later.

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.