Mercurial how to achieve prod-test-dev - mercurial

I want to follow the structure of prod-test-dev.
In a git environment I would have a single project folder with 3 branches(prod-branch, test-branch, dev-branch).
How is this achieved with mercurial? As far as I understand you need to have 3(!) different projects. A project representing the production branch, another the dev etc.
This seems inefficient. Is there another way to achieve this? It can be that I have not really understood branches.
Update with pic showing the flow when I create this 3 branches in Mercurial:

Basic prod-test-dev flow would look like this:
Create new repository (or start with existing one). For start you have to create three named branches with following commands:
hg branch prod
hg commit -m"prod branch"
hg branch test
hg commit -m"test branch"
hg branch dev
hg commit -m"dev branch"
After you are done your repository will look like this:
For development process you would update repository to dev branch and do some development there. After you have commited all changes to dev and are ready to release that code to testing do following update to test branch select dev branch in and perform merge with local (dev branch). Do the code fixing in test branch and when you are done merge back changes from test to dev branch (update to dev, select test branch - merge with local). Repeat cycle until you are ready for production. Then update to prod branch, select test and merge with local - and you will have your production code ready in prod branch.
After one development test production cycle your repository would look like this:
You should also never close any of those three branches since they represent base for your workflow.

As Lasse noted - just use Mercurial branches (named branches better) in The Right Way (tm)
Here my log of 2-branches repository with single-direction sync

Related

switch branches in hg while preserving files

While developing my software i create a set of test-cases which an be automatically done via make tests. To keep things organized i put those in a sub-directory tests. To keep my commits organized as well and not to clutter my development branches, i created an extra branch tests where i commit the test units.
My problem is: when i commit the units to the test branch and switch back to development, said tests are deleted
D:\Project>hg branch test
D:\Project>edit...
D:\Project>hg add
D:\Project>hg commit
D:\Project>hg up dev
2 files updated, 0 files merged, 3 files removed, 0 files unresolved
How can i preserve those files?
(i tried the solution for Mercurial: Switch working directory to branch without losing changes? but it still deletes the files)
EDIT See my own answer below
Those test files don't exist in your development branch, so when you check out the development branch they won't be in the working directory. DVCSs like Mercurial and git don't let you have one directory checked out at one revision/branch and another one at another revision/branch.
The answers to which you linked are for bringing the changed and their files over into another branch, they're not what you're asking for.
So the way you want to do it (separate branches) isn't going to work, but there are plenty of other/better options
One choice would be to make your tests a patch that's managed by a mq (Mercurial Queues) repository, which can itself be versioned. Then when you where in your dev branch and wanted to run the tests you'd do:
hg qpush # tests show up
... run tests, edit tests ..
hg qrefresh # save the changes you made to the test
hg qpop # tests vanish again
MQ is poweful, but sometimes a little hard to wrap your head around.
Another choice would be to make your tests a parent repository and your actual code a child repository of that parent. Your disk layout would look like:
parent/
tests/
existingrepo/ # <-- the repo you already have w/o tests
Then people could clone and you could push the existingrepo w/o tests, but the outer repo would include a pointer to it and the two would be versioned in lockstep. Again, sort of tricky, but has some nice results.
The third option, and my preferences is to get over the "To keep my commits organized as well and not to clutter my development branches" mentality. Tests are just as important as the primary code, they should be versioned with the code, and they're not cluttering anything, they're providing valuable tools to help comprehend what the code is doing. You can always use hg log --exclude tests/ to see a history that excludes them when that's convenient.
To take that plunge just do:
hg update development
hg merge tests
and you're good to go.
when i commit the units to the test branch and switch back to development, said tests are deleted
It's expected and correct result: branches store diverged lines of development, you add something only in test branch, before merge this data will exist only in branch on creation
In order "To keep my commits organized as well and not to clutter my development branches...", but have tests in development branch you can use at least two ways:
Periodically merge tests branch to development (all changes in tests will appear in development), but use log only for changesets in development branch, maybe without mergesets from tests. It's rather simply revset, you can even write log command with revset into aliases and use aliased command when needed
As Ry4an mention, you can instead of branch-separtion, perform repository-separation with subrepo|guestrepo technique - if tests are stored in subdir of main repo, convert /tests into nested repository -> subrepository and have two independent, but linked repos (future reading: Subrepository in Mercurial wiki and Subrepositories in Mercurial Kick Start Exercises)
to achive what i wanted i eventually created a subdirectory for the repo:
project/
main.cpp
makefile
.repo/
.hg/
and created a new make target:
REPO := .repo
init: $(REPO) $(REPO)/.hg
$(REPO):
mkdir -p $(REPO)
$(REPO)/.hg:
hg init $(REPO)
commit : | $(REPO) $(REPO)/.hg
ifdef BRANCH
hg -R $(REPO) update -C $(BRANCH)
endif
find . -regex "^\./[^.].*" -exec cp --parents {} ./$(REPO) \;
# the regex prevents "hidden" dot-folder from copying
# one could use --link to save time and drive usage/space
# but i am concerned about hg auto merging and overriding (per hardlink)
# my actual changes
hg -R $(REPO) commit $(EXTRA)
so i could just issue make commit BRANCH=tests to commit to arbitrary branch without losing all changes not relevant to the branch. Implementing of hg add as wipe .repo, copy file there hg -R .repo add $(filename) is left as exerciser for the reader

Mercurial: shelving committed files

I have two repos, dev and testing. In dev, I've made several commits since the last push to testing. However, now I want to shelve all those commits, make a different change, push it to testing, and then get those commits back. Shelving only works on uncommitted files.
What should I do? Backout or rollback or revert each commit in reverse order? Rename dev, clone testing to dev, make changes, push to testing, push to renamed dev, delete dev, rename renamed dev back to dev?
What's the cleanest/easiest way to do this?
For clarity to other readers: the actual HG shelve command is not the correct approach for this situation; it does not work on already-committed changes, but nor is it necessary to use in this case.
Here's what you can do:
In dev, update to the version before the commits you don't want to push to testing.
Make your desired changes in dev and commit. This will create a new head (which will also be the new tip).
Push to testing
In dev, merge the tip with the other head that contains the changes you have avoided pushing, then commit.
Original suggestion (not possible to implement in this case):
Clone dev into a new repo and update to the version before the commits (or just clone testing instead)
Make the change you want, commit and push to both testing and dev
Discard the clone
Pull the testing from testing into dev and merge the heads at your leisure, establishing a single head once more
Another workflow may be: Use MQ extension
Enable MQ extension for repository
Init MQ
Convert needed changesets into MQ-patches (How to convert N local topmost commits to an MQ patch? and "Converting to and from permanent revisions" topic in Chapter 12. Managing change with Mercurial Queues of HG Book)
Unapply all created patches 'hg qpop -a'
Make change, commit, push
Return back patches into changesets state (hg qpush -a + hg qfinish -a)

Mercurial workflow help - how to make a tag of a tag and get it to central repo?

I'm new with HG, I'm looking for some advice on how to handle this scenario.
We have a central repo hosted at Kiln. The three guys on my team code away and eventually are ready with our code which we tag and release as Version1. We then happily start working on our next major version. While working on it, there's the need to fix a critical bug in Version1 so James clones his repo using hg clone -r Version1 http://centralrepo where he makes his change and tags it as Version1.1.
Now, how does Version1.1 get back to the central repo? Using hg push causes an abort because there are two remote heads. Without it being in the central repo, Doug can never come along and make a fix to Version1.1 if it ever becomes necessary.
How can I modify my process so that all my tags are always stored on the central repo and easily pulled into the dev branch?
UPDATE/EDIT
With the suggestion from Joel, I made the following tweaks:
On the Kiln website, I create my main active dev repo. Once I have the code in there, I create a new branch from it.
I clone my ActiveDev branch: hg clone http://activeDev code-activeDev
I clone my Stable branch: ht clone http://stable code-stable
I setup a tag on my stable branch: hg tag V1.0 and then push it to the stable branch and to the active dev branch. When going to activeDev I use the -f command. Now both branches are identical.
I do an hg pull and start on a new feature in ActiveDev. Then push that feature back to central:
hg com
hg push
Stable gets a bug fix, then pushed to it's own repo using the same two commands. Now when I try to push that fix to the activeDev branch, I'm again given the 'you are making two heads, use -f' message. However, if I force it, the new feature I pushed earlier in activeDev is blown away by the fixes I did in stable.
Did I do something wrong? Am I missing a step somewhere?
Basically, you need to merge the fix so that there is only 1 head again. There is a way of managing 2 branches that makes doing bugfixes on released versions (in parallel with development) easier:
The process I use is to create a named branch called Stable in addition to the default branch. I work on new features and whatnot on the default branch. Whenever I do an actual release of code, I merge that over to the Stable branch and only tag things like v1.0, v1.1, etc. on that branch.
Then I can continue development on the default branch, but when a bug comes up that is relevant to a previous version I can put that fix on the Stable branch and recompile. When ready, I merge fixes from the Stable branch over to default to make sure that Stable is always just a subset of default.
If you start using this, the first time you push that named branch to central you will have to use hg push --force, but only once.

Storing separate named branches in mercurial without having to merge them

It's my first time using a DVCS and also as a lone developer, the first time that I've actually used branches, so maybe I'm missing something here.
I have a remote repository from which I pulled the files and started working. Changes were pushed to the remote repository and of course this simple scenario works fine.
Now that my web application has some stable features, I'd like to start deploying it and so I cloned the remote repository to a new branches/stable directory outside of my working directory for the default branch and used:
hg branch stable
to create a new named branch. I created a bunch of deployment scripts that are needed only by the stable branch and I committed them as needed. Again this worked fine.
Now when I went back to my initial working directory to work on some new features, I found out that Mercurial insists on only ONE head being in the remote repository. In other words, I'd have to merge the two branches (default and stable), adding in the unneeded deployment scripts to my default branch in order to push to the main repository. This could get worse, if I had to make a change to a file in my stable branch in order to deploy.
How do I keep my named branches separate in Mercurial? Do I have to create two separate remote repositories to do so? In which case the named branches lose their value. Am I missing something here?
Use hg push -f to force the creation of a new remote head.
The reason push won't do it by default is that it's trying to remind you to pull and merge in case you forgot. What you don't want to happen is:
You and I check out revision 100 of named branch "X".
You commit locally and push.
I commit locally and push.
Now branch X looks like this in the remote repo:
--(100)--(101)
\
\---------(102)
Which head should a new developer grab if they're checking out the branch? Who knows.
After re reading the section on named branchy development in the Mercurial book, I've concluded that for me personally, the best practice is to have separate shared repositories, one for each branch. I was on the free account at bitbucket.org, so I was trying to force myself to use only one shared repository, which created the problem.
I've bit the bullet and got myself a paid account so that I can keep a separate shared repository for my stable releases.
You wrote:
I found out that Mercurial insists on only ONE head being in the remote repository.
Why do you think this is the case?
From the help for hg push:
By default, push will refuse to run if it detects the result would
increase the number of remote heads. This generally indicates the
the client has forgotten to pull and merge before pushing.
If you know that you are intentionally creating a new head in the remote repository, and this is desirable, use the -f flag.
I've come from git expecting the same thing. Just pushing the top looks like it might be one approach.
hg push -r tip

How to repeatedly merge branches in Mercurial

We're using Mercurial where I work and I want to have a setup similar to how I used SVN:
Trunk
Tags
Production
Branches
Since Mercurial supports branches natively, I know how to create a named branch, but I can't find any documentation on how to repeatedly merge 'Trunk' with 'Production'.
Quite simply, I want to have a development branch for normal work and a production branch that I routinely pull changes from the development branch into. How do I do this with Mercurial?
As the previous poster mentioned, the transplant extension can be used for cherry-picking individual changes from one branch to another. If, however, you always want to pull all the latest changes, the hg merge command will get you there.
The simplest case is when you're using clones to implement branching (since that's the use case Mercurial is designed around). Assuming you've turned on the built-in fetch extension in your .hgrc / Mercurial.ini:
cd ~/src/development
# hack hack hack
hg commit -m "Made some changes"
cd ../production
hg fetch ../development
If you're using local branches:
hg update -C development
# hack hack hack
hg commit -m "Made some changes"
hg update -C production
hg merge development
hg commit -m "Merged from development"
Something like hg transplant? That's what we use on our dev and prod branches.