Context:
7 devs
1 product
3 branches:
Version 3.6 (stable)
Version 3.7 (stable)
Master (dev)
Rules & Policies in place:
Any fix made in an earlier version must be merged in all future versions.
Integration is continuous: if you fix something in 3.6, you must integrate and test in 3.7 and in master before you push.
When possible, rebase your work before you commit so that stuff you committed two days ago locally will actually be put back on top. I know this is a matter of preference and has pros and cons, but this is what we like best as a team.
Our problem:
We have too many useless merge operations to do. Here is a scenario:
Normal integration work:
Joe and Bill work on two different fixes that go in 3.6.
Joe is done, he pulls (and rebases)
Joe tests one last time in his 3.6 branch
Joe switches to 3.7 and merges 3.6 - merge 1
Joe tests again, this time in the context of 3.7
Joe switches to 3.8 and merges 3.7 - merge 2
Joe tests again, this time in the context of 3.8
Joe is ready to push
Bill did pretty much the same thing but pushed right after Joe pulled
Joe tries to push but the operation fails because it would create a new head
Painful (useless) merges:
Joe pulls, he gets stuff from Bill in 3.6, 3.7 and 3.8
Joe updates to 3.6 and merges changes he received from the pull - merge 3
Joe updates to 3.7 and merges changes he received from the pull - merge 4
Joe still in 3.7 merges 3.6 - merge 5
Joe updates to 3.8 and merges changes he received from the pull - merge 6
Joe still in 3.8 merges 3.7 - merge 7
Joe tries to push and prays that nobody pushed something to 3.6 in the meantime.
We are thinking of writing an extension (or batch or program) to automatically merge this kind of situation. So when Joe finds out that he cannot push, he would just run MergeUpAutomagically. But before we try to fix this, I want to make sure we are using the right workflow.
If I understand, you are using named branches in same clones.
I find it easier to use a different clone for each version (releases, devs), where each clone contains a named branch related to the version (and also changesets from the older branches). We have "official" clones where we synchronize (pulls and pushes).
Advantages:
No need to "switch" by doing hg updates (in my situation I use Eclipse instances with a different work space for each project). I used to work with named branches in same clones but found it confusing.
Easier to see where the changesets come from (from which named branches-versions). Also, if someone pushes from a higher version to an older one by mistake, it is easy to spot.
Synchronization is more "atomic". We pull and push for each "official" clone-named-branch, then pull between "official" named branches (from older to newer).
In your situation, maybe Bill pushed before Joe, but had only time to do it in 3.6 and Joe realized that before synchronizing to higher versions (not sure it would help in your situation). Also, maybe it is not necessary to synchronize the "dev" branches as often as the "releases".
Related
2 main branches:
stable - used for release and for hotfixes.
default - used for all other development and all features
Please see revisions 8 and 9 specifically. I added a 2 separate features in revisions 3 and 4, worked on them separately, merged them into default in revisions 7 and 8. They are not complete at this time.
My question is, did I do this correctly considering that I am not done with the features and did not close the feature branches? The connected blue and pink lines at revision 8, along with the blue extension at revision 9 are confusing me.
I'm pretty new to source control, so any explanations are appreciated.
You just have two heads on your tree, which are at revisions 8 and 9 specifically now. You could run "hg heads" on the command line in that directory to see some textual information about them both. At this point, you could update to either head, make changes and commit, then update to the other head, make changes and commit, etc. Also, you could merge your feature branch into the default and then just have one head. It depends on how long you want to keep your feature branch separate.
More interestingly, are you planning to keep using the "stable" branch? If so, I guess that you could "hg update" to r1, and then merge things from your other branches to there.
Side note: You may be interested in reading about "hg flow", and its branching model. See for example:
https://andy.mehalick.com/2011/12/24/an-introduction-to-hgflow
http://www.carl-berg.se/post/hgflow-git-flow-for-hg
I have run into an interesting situation that I do not know how to describe. So I here is a screenshot of it (note that two programmers are working here with a central repository that both synchronize with):
The image on the left is updated to the other programmer's core (which is now the head) and the image on the right is updated to my core before the merge to dev.
As you can see, I have one Core branch #372 merging into Dev. The other programmer forgot to merge with my changes at #372 (which I had already pushed to the central repository before this changes from 375 and onwards) and continued on.
So now I have a core branch that merged into dev, and is sort of left headless. The other programmer's core is now going to be the one I am going to start with. That is not an issue. What is an issue is seeing two cores and the messy tree with confusing branching.
What can I do to end up with one core branch only? Or is this ok to have?
As you can see, I have one Core branch #372 merging into Dev. The other programmer forgot to merge with my changes at #372 (which I had already pushed to the central repository before this changes from 375 and onwards) and continued on.
That's not what I see. #372 is a parent of #373 on both sides. Both graphs, if you remove #381+ and #372+, are the same. They've been drawn differently just because the parent of the current working copy is different.
Granted, it looks a little odd, but there's no issue here. After #372+ is committed, it will need to be merged with #381 (or whatever the current Core head is by then) at some point, but that's nothing exceptional.
Right now, Core actually has 0 topological heads since changesets 381 and 372 were both merged with dev. On your graph you see that long line extending from changeset 372 because your working directory is on that changeset right now. The line is indicating that any commits you make will be children of 372. The other programmer's working directory is on changeset 381, which is why his graph looks different. Once you update to 381 your graph will look the same as the other one.
So to answer your question, this won't be an issue since Core's branch heads have all been merged into dev. Also if you did end up with multiple topological heads on Core, mercurial would warn you about it when you pulled in the new head.
My dev team is just starting out with Mercurial and we're confused on the following point:
We are a php webdev team.
We have 3 developers. Most of what we are doing now is bugfixes on a very new product. Also doing some new feature development.
We have 2 QA people. Every bugfix and feature must be tested before it is allowed to go live.
So far, each developer has his own repository. We have a central sever called WebDev with it's own repo. A developer pulls from WebDev, then makes some changes (ie, fixes a bug), and pushes to Webdev. Then a QA tester will test the code on the central server (so testing on the code in WebDev) and if it works, he will push that code to our production server.
This does not work well, because... what happens when Developer-1 (dev-1) fixes a bug, and pushes to WebDev. At the same time, dev-2 fixes a different bug and pushes to WebDev. the QA person tests the code there, and approves the second bugfix but not the first. How would he push the second changeset to production without the first one as well? We seem to be losing all the advantages of a version control system.
I've read up a lot on branching, but I cannot figure out how to make this work for us... do we create a new branch for every bugfix and new feature, and the only after it is tested, QA will merge into the default branch on WebDev? Is that the best way, or is there something I am missing?
Thanks!!
----UPDATE----
thanks to everyone who answered so far. here is where i am holding now... i can think of two solutions.
1) dev-1 fixes a bug for bug-101. he pulls from webdev, merges and commits locally. he sets it in-testing. QA pulls directly from his repository, and test locally. if it passes, QA will pull from webdev ->merge -> push to webdev (and if its a big change, can review again there to make sure it is fine). so we are only testing one thing at a time, WebDev only contains changes that have been tested locally by the testers and is always stable.
2) create branches for everything. dev-1 creates branch "bugfix-101" then pushes to webdev without merging it. QA can test the branched code, and if it's approved, merge it with the default branch. I have four questions on this method - (a) is it possible to push an open branch to a remote repository? (b) if QA merges and closes the branch on webdev, the next time i pull, will my local repo also close and merge the branch? and (c) how do you test from the branched code? when i run the web app in the browser, how do i test from the branch?? (d) are there performance issues with creating so many named branches (assuming that most of them will get closed quickly)?
Thanks again.
Folow up to Bassam:
Your team is obviously missing the (really easy) branching and merging in Mercurial and working with a monolitic (?) default branch.
Just change your thinking and workflow slightly and you will see a big difference:
Each QA-member has a permanent clone of the repo and only pulls a developer's repo on request (it's faster, pulled changes are more visible); maybe branch QA also have sense
Use a separate branch for each and every big change (feature or bugfix)
When a dev has a changeset X in branch "Bugfix Y" in his repo finished and ready to test, he asks QA to "pull and test changeset X"
QA does that, maybe merges "Bugfix Y" to the "QA" branch in his repo (as a "test passed" sign?) and merges the "QA" branch to mainline ("Stable" or "default" branch), and finally pushes the results to needed destinations (WebDev and Prod?)
On every next request step 4 must n\be repeated
This way you never mix in one approve-cycle more than one development action
This is a good place to use tags. Have either the dev or qa person tag the release containing only the changes they want, and then the qa person can clone the repository at the tag level (or update the repository to the tagged changeset if that fits better for you... your preference). Then do the test using the tagged version of the code.
As a side note, it would be worth looking into these two answers on the Kiln stackexchange site to see Fog Creek's repository strategies (see how they eat their own dog food):
http://kiln.stackexchange.com/questions/354/release-repo-suggestions/355#355
http://kiln.stackexchange.com/questions/500/should-i-use-more-than-one-repository/504#504
Update
There is a good description in this post about why it is better to fix bugs in a stable branch and push them back to dev, while using a dev branch for features (which get pushed back to the stable branch as well... two way pushing/pulling). This is how we do it as well. It is not directly answering your question, but is related enough that I thought I'd include it.
Creating branches with Mercurial is a breeze, use that :) I would create separate branches for different feature and different bugs and have the QA person merge them to the main branch whenever the ensure that a bug is fixed.
Another alternative is to use named branches which is essentially the same thing but instead of seperate branches, your named branches is going side by side with the default branch until they are ready to be merged in.
Note: We have been alternating between both strategies at my work place.
We have these Mercurial repositories:
Trunk
|
|
|---------myapp_1_0_23 (created off release 1.0.23)
|
|---------myapp-newstuff (created off rel 2.0.4)
Release schedule (nothing yet released):
v1.0 from myapp_1.0.23, any add'l changes in this repo will get merged to the trunk
v2.0 from the trunk
v3.0 or v4.0 released based on a merge of myapp-newstuff and the trunk. At the time of the merge the trunk may have v2.0 code or some new features that we'll release from the trunk as v3.0
After making changes in myapp_1.0.23, we merge them to the trunk, but let's say we also need them in myapp-newstuff so we also merge them there. What then happens when we eventually merge myapp-newstuff code to the trunk?
The trunk already has changes made in myapp_1.0.23 so what happens when we merge those same changesets from myapp-newstuff back to the trunk? Will Mercurial be smart enough to know those changesets are already in the trunk?
Mercurial will handle this situation just great -- because you're using 'merge'. When you're using export/import (or transplant), cherry picking as it's called, and you have the same changesets in there multiple times with different node ids (due to different parents) then Mercurial can't know "Oh, this one's already here". However, so long as you're merging Mercurial will do a great job of saying "oh, this repo already has that changeset so I don't need to re-apply it".
The general rule of thumb is: "Make every change with as early a parent as you can and then merge down". If I have a bug that's in version one, two, and three, I fix it in one and then merge into two and then merge into three. If instead you fix it first in three, then you have to try to get it into two without bringing all the other changes in version three with it -- which is hard and often requires the very cherry picking we're trying to avoid.
Since I want to diff all the changes I made since 7 or 10 days ago, without seeing the changes of other team members, so I keep a clone, say
c:\dev\proj1
and then I keep another clone that is
c:\dev\proj2
so I can change code for proj1, and then in another shell, pull code from it, and merge with other team members, and run test. And then 10 days later, I can still diff all the code made by me and nobody else by going to the shell of proj1 and do a hg diff or hg vdiff.
I think this can be done by using branch as well. Does having 2 clones like this work exactly the same as having 2 branches? Any advantage of one over the other method?
The short answer is: Yes.
Mercurial doesn't care where the changesets come from, when you merge. In that sense, branches and clones work equally well when it comes time to merge changes.
Even better: The workflow you described is exactly the strategy in Chapter 3 of the Mercurial book.
The only advantage of branches is that they have a name, so you have less incentive to merge right off. If you want to keep those proj2 changes separate, while still pushing and pulling them from proj1, give them a real branch. Again, functionally, they're the same.
And yes, this is characteristic of DVCS, not uniquely Mercurial.
Note : I'm more familiar with git than hg but the ideas should be the same.
The difference will become apparent if you update both the clones (which are both editing the same branch) e.g. for a quick bug fix on the integration sandbox.
The right way would be for you to have a topic branch (your first clone) which is where you do your development and another one for integration (your second clone). Then you can merge changes from one to another as you please. If you do make a change on the integration branch, you'll know that it was made there.
hg diff -r <startrev> -r <endrev> can be used to compare any two points in Mercurial's history.
Example history:
rev author description
--- ------ ----------------------
# 6 me Merge
|\
| o 5 others More other changes.
| |
| o 4 others Other changes.
| |
o | 3 me More of my changes.
| |
o | 2 me My changes.
|/
o 1 others More Common Changes
|
o 0 others Common Changes
If revision 1 was the original clone:
Revs 2 and 3 represent your changes.
Revs 4 and 5 are other changes made during your branch development. They are pulled merged into your changes at rev 6.
At this point, to see only changes by me before the merge, run hg diff -r 1 -r 3 to display those changes only.
Why not simply have two branches? (Branching/merging is much easier and safer in a DVCS like Hg or Git than in a centralised VCS like TFS or SVN!) It would be much more secure and reliable.
This will become apparent e.g. when you will want to merge the two branches/clones back together. Also, editing one branch from two different physical locations can easily lead to confusion and errors. Hg is designed to avoid exactly these kinds of situations.
Thomas
As some answers already pointed out, branches (named or anonymous) are usually more convenient than two clones because you don't have to pull/push.
But two clones have the distinct advantage of total physical separation, so you can literally work on two things at the same time, and you don't ever need to rebuild when you switch project.
Earlier I asked a question about concurrent development with hg, with option 1 being two clones and option 2 being two branches.