I am using Mercurial Queues on a repository, and have placed those patches in a patch repository. Another contributor has cloned my patch queue and made changes of their own. I would now like to merge their changes in my local patch repository.
I am trying to find a good workflow for performing this merge that
reflects the contributor's changesets in the history of the patch repository
invokes the user's merge tool in case of conflicts
Initially, I just tried to merge the patches directly. This is okay in very simple cases, but does not work well when many things have changed, since the patches depend on line number context which doesn't seem like something I should have to worry about adjusting myself. Overall, I find examining a 3 way diff of patches to be too complex.
Is there a better way?
There's no great way to handle this. What I'd probably end up doing is creating two clones, and qfinishing your patch in one and the contributers patch in the other. That that point you'll have repos with each separate patch's net effect applied. Then you hg pull one of those clones into the other, and hg merge will let you use your graphical tools to merge the results of the patches -- and the only differences should be the differences in your patches. At this point, ideally, you'll be able to qimport the merge changeset, but you can't do that, so you have to 'hg diff -r tip-1 -r tip' to get a new diff that is the difference between before-everything-started and after-merging-the-two-results. You then 'qimport` that diff and commit it to your patch queue repo with a note saying where it came from.
Decidedly sub-optimal, but the best I can come up with. I'd love to hear a better solution.
I'm afraid that there is no automated way to merge patches.
However, one "trick" you can use is to create new patches instead of editing/refreshing existing patches when you need to amend them. When you all agree on the right way to do things, then hg qfold the patches.
That way you wont be stepping on each others toes as much since you create new patches.
Related
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.
I've forked a project from the internet, and I want to write some new features. I want to write several orthogonal features at the same time, (eg. debug helpers, new feature X, new feature Y), and have the code for all of them in my current directory, but when I commit, I want to be able to say "these files go to branch 'debug'", "those files go to branch 'feature X'", etc. Where these are branches in the 'hg branches' sense.
The reason for this is the project upstream may not want to merge my debug helpers or hacked bug fixes, but I certainly want to use them whilst developing my features.
Effectively, I just want to apply the changes in those files to the branch, but keep several branches checked out & merged to my current working directory.
Is this possible? Perhaps there's some hg extension to do this?
Thanks!
Look at mercurial queues (MQ) for things like debug helpers or local hacks. Very useful for patches that you only want locally and may want to apply to any revision/branch.
Doing the same thing with branches becomes tedious IMHO as you have to be very careful to do the changes for debug and features on different branches, and then merge them in to a local, throwaway branch in order to run anything. You can end up with lots of changesets on the feature branch that leave the tree in a broken state because you can only test after you commit.
I don't fully understand why you'd you would want to do things that way. If your features are orthogonal, you can work on them independently until they are ready to be merged. That is exactly what branches are for after all!
But to answer your question: you could commit on a branch and then, as a matter of workflow, always up to default and merge it in. That would keep the default branch as the sum of the other features. You would need to update to the feature branch before you commit, though and that could get tedious.
The other option for post-facto determining which branch you want to commit to is to use the rebase extension. In this case, you'd commit your changes and then do hg rebase -d targetBranch.
I don't recommend using history revisions as part of your standard workflow, though. That smells to me.
I've been working with Mercurial now for some time. When making (private) changes to some third party software, in the past I always created a separate named branch for these changes. When the upstream code updates, I simply merge it into my named branch.
Today I read about MQ (Mercurial Queues - chapters 12 and 13). I think I understood the concept behind MQ, so my question is:
Is there any advantage of MQ over (named) branches in Mercurial (for my scenario)?
The main advantage of MQ over named branches are:
You can revise your patches. This lets you edit history and so you can maintain a clean and logical series of patches on top of the upstream code: if you notice a mistake in a patch you refresh the patch instead of making a new commit.
The changes in your patches will be cleanly separated from the changes made upstream. When you merge two branches, you mixing the two streams of development. This makes it difficult to see the changes you've made without also seeing the changes coming in from the upstream branch.
The patch names are transient. When you hg qfinish an applied patch, there's no trace of the patch name left in the commit. So you can use MQ without coordinating first with the upstream repository since they'll never notice MQ.
You avoid merges. Instead of merging with the latest code from upstream, you rebase your applied patches. This gives you a simpler history. The history is obviously fake since you pretend that you made all your patches after seeing the code from upstream — when infact you made it in parallel with upstream and later moved your patches to the tip of upstream.
You have no permanent branch name in the changesets. People sometimes treat named branches as disposable and become upset when they realize that a named branch is fixed in history. (You can actually set the branch name with hg branch before pushing patches so this point is not so bad.)
Disadvantages of MQ are:
It's an extra tool to learn. It's powerful, but it also gives you more opportunity to shoot yourself in the foot. Running hg qdelete will really delete the patch and so you can throw away data. (I think this is fine, but we've had a Git user coming to our mailinglist complaining about this.)
You make it much harder to collaborate with others. You can turn .hg/patches into a repository and push/pull patches around between repositories but it's difficult to do that if you're more than a single developer. The problem is that you end up merging patches if more than one persons refreshes the same patch.
You have no permanent branch name in the changesets. If you're using named branches right and use stable, long-term branch names, then you will miss that when using MQ.
Good question. It depends. Personally I dislikes mercurial branching system, and I try to avoid it when I can (using pushed bookmarks instead of branch).
MQ is a great tool, with great power and great pitfalls. You can also consider using pbranch.
MQ is a great tool if you need to produce and maintain a patch-set for a project, something like adding feature-x to a project and keeping patches updated with the upstream code.
Bookmarks (or branches if you like) are good for short-development task that require to be merged into the upstream code.
Is it
pull
update
merge
commit
push
? Or can you do the commit first?
I don't like the idea of pulling and merging without having a version of my local code backed up somewhere in case the merge explodes, but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo. Not quite understanding this whole process yet; used to my nice simple SVN.
I recommend to always commit before pulling in changes to your working directory, unless you are 100% sure that your changes and the changes to be merged into your working directory will not conflict.
If you do an updating pull (hg pull; hg update, or shorter hg -u pull) and have any outstanding non-committed changes, any changes coming from outside will be combined with your changes. When conflicts happen, it might be difficult to decide how the merge result should look like, because you can't easily distinguish between your changes and the changes merged in.
When you did commit first, it is much easier to decide how the merge result should look like, because you can always look at both parents of the merge.
So, in effect it is:
hg commit
hg pull -u (if no merge necessary, go to 5)
hg merge
hg commit
hg push
Update: As Martin Geisler has pointed out, it is possible to get at the "original" changed version of a file using:
hg resolve --unmark the-file
hg resolve --tool internal:local the-file
or for all files at the same time:
hg resolve --unmark --all
hg resolve --tool internal:local -all
Still, I find the "commit first" system nicer. At the end, it is personal preference...
I don't know as there's a standard per se, but one of the ideas behind Mercurial is that you can commit as often as you like since it goes to your local repository. So you can commit to your heart's content as much as you like before you pull updates.
I tend not to commit very often, saving up for when I'm preparing to push, but that's me. I can see the utility of committing early and often. I do pull updates frequently as I work to cut down on merge fun.
One other thing I do is to keep a parallel clone of my working repo (cloned from the same repository as my working repo, not cloned from my working repo) so that I can check the original state of a file easily, and if need-be check in an out-of-band emergency fix or what-have-you without complicating my current change set.
Do edits
Commit
Goto 1 until satisfied
Pull
Merge & commit
Push if you want to.
Definitely commit before trying to do something complex like a merge. I don't think mercurial will allow you to merge before committing, but even if it did, what if the merge goes wrong. You have no pre-merge revision to go back to.
Commit early, commit often.
If you don't, you are missing out on a huge benefit of a DVCS.
but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo
Wrong statement and poor understanding of distributed workflow and parallel development.
You can merge heads before push, but not have or must. Push can put any data to repo, if it needed and intended to be so
By default, push will not allow creation of new heads at the destination,
since multiple heads would make it unclear which head to use. In this
situation, it is recommended to pull and merge before pushing.
(NB: "recommended to pull and merge before" statement)
You can use commit-pull-merge, stash-pull-unstash-merge, perform fetch with modified WC and merge on the fly, don't merge heads at all or sporadically and push --force with +1 heads - there are not common rule for everybody. And any and every such workflow doesn't produce "conflicts in the central repo", but only different DAG.
Each point of divergence, which appear in case of existing your and other changeset from commmon parent in your (or even central) repo is a point of starting anonymous branches in Hg, which (technically) are absolutely legal, applicable and usual way. How they handled is defined by policy and agreement between developers, PM, QA-team and others
I, personally, prefer finish my task (in one or more amount of commits), after it pull and maybe merge, when it approved by development-policy
...so I've gotten used to the simple stuff with Mercurial (add, commit, diff) and found out about the .hgignore file (yay!) and have gotten the hang of creating and switching between branches (branch, update -C).
I have two major questions though:
If I'm in branch "Branch1" and I want to pull in some but not all of the changes from branch "Branch2", how would I do that? Particularly if all the changes are in one subdirectory. (I guess I could just clone the whole repository, then use a directory-merge tool like Beyond Compare to pick&choose my edits. Seems like there ought to be a way to just isolate the changes in one file or one directory, though.)
Switching between branches with update -C seems so easy, I'm wondering why I would bother using clone. I can only think of a few reasons (see below) -- are there some other reasons I'm missing?
a. if I need to act on two versions/branches at once (e.g. do a performance-metric diff)
b. for a backup (clone the repository to a network drive in a physically different location)
c. to do the pick&choose merge like I've mentioned above.
I use clone for:
Short-lived local branches
Cloning to different development machines and servers
The former use is pretty rare for me - mainly when I'm trying an idea I might want to totally abandon. If I want to merge, I'll want to merge ALL the changes. This sort of branching is mainly for tracking different developers' branches so they don't disturb each other. Just to clarify this last point:
I keep working on my changes and pull my fellow devs changes and they pull mine.
When it's convenient for me I'll merge ALL of the changes from one (or all) of these branches into mine.
For feature branches, or longer lived branches, I use named branches which are more comfortably shared between repositories without merging. It also "feels" better when you want to selectively merge.
Basically I look at it this way:
Named branches are for developing different branches or versions of the app
Clones are for managing different contributions to the same version of the app.
That's my take, though really it's a matter of policy.
For question 1, you need to be a little clearer about what you mean by "changes". Which of these do you mean:
"I want to pull some, but not all, of the changesets in a different branch into this one."
"I want to pull the latest version of some, but not all, of the files in a different branch into this one."
If you mean item 1, you should look into the Transplant extension, specifically the idea of cherrypicking a couple of changesets.
If you mean item 2, you would do the following:
Update to the branch you want to pull the changes into.
Use hg revert -r <branch you want to merge> --include <files to update> to change the contents of those files to the way they are on the other branch.
Use hg commit to commit those changes to the branch as a new changeset.
As for question 2, I never use repository clones for branching myself, so I don't know. I use named branches or anonymous branches (sometimes with bookmarks).
I have another option for you to look into: mercurial queues.
The idea is, to have a stack of patches (no commits, "real" patches) ontop of your current working directory. Then, you can add or remove the applied patches, add one, remove it, add another other one, etc. One single patch or a subset of them ends up to be a new "feature" as you probably want to do with branches. After that, you can apply the patch as usual (since it is a change). Branches are probably more useful if you work with somebody else... ?