Really needed two heads in two distinguished branches - mercurial

We have this situation on TortoiseHg and Bitbucket where it is stored the shared repository:
The merge between the job of dev1 and dev2 shall be done by dev1; but dev1 cannot see the job of dev2 because the latest cannot push his job on the bitbucket repository since he is stopped by HG with this reason "abort: push creates new remote head 2221daef6518 on branch 'Federico Development'"
I fear that problem has been originated by one commit by dev2, the one that is marked in the picture with the 2 red circles: he committed on federico branch locally while federico was also working and committing on the same branch.
Whatever was the original cause of the problem, we would like to let the dev2 to push to the shared repository his work as a different branch head with respect to dev1 so that dev1 can pull the dev2 job and merge the two heads. Is it possible any workaround to get this result?
Secondarily, we would like to understand the origin of the problem for a better understanding and to prevent it in the future:
is it true that the problem has been originated by the commit of dev2 ono dev1 branch?
why HG still stops even if after that unlucky commit dev2 has changed the branch with a second commit?
is there any way to assign to every user a specific branch or, in other words, to deny the commit access on a specific branch to some users?

Mercurial by default does not allow multiple heads on one branch to be pushed to server. In you case, dev2 created a new commit on dev1 branch and that created a new head.
Now answering your questions one by one:
Yes, the problem orignated because dev2 created a new commit on dev1 branch which resulted in dev1 branch having multiple heads.
Commits in mercurial are part of the commit information. So the first commit which dev2 did is still on dev1 branch even after dev2 created a new commit on new branch.
Yes, you can write a precommit hook to achieve that.
Following is a way you can solve this problem for now:
dev2 can push using the extra head using --force flag. This will push the new head to the server. This way the commits will be exchanged but you will end up with multiple heads on dev1 branch which you will need to resolve by merging or some other way.

Related

Mercurial how to achieve prod-test-dev

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

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/

cannot push to remote repo after merge

branching out -
[default]$ hg branch talks
[talks]$ <... some commits ...>
[talks]$ hg update default
merging back -
[default]$ hg merge talks
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
pushing to remote repo -
[default]$ hg commit -m "merging talks to default"
[default]$ $ hg push
abort: push creates new remote branches: talks!
(use 'hg push --new-branch' to create new remote branches)
Further investigation revealed that remote repo doesn't want me to have multiple heads at the remote end. But I just did a merge to merge the two heads into one, isn't it?
The graph from hg serve also seems to agree with me (I hope)
However, I also see two heads from hg heads
[default]$ hg branches
default 9:85752ecd6326
talks 8:2b00714d76d5 (inactive)
The solution is in the abort message: use 'hg push --new-branch'. You've created a named branch called talks so it needs this extra switch, regardless if you have merged the named branch back to default.
I'm guessing you've misunderstood the branch feature. You've just created a branch who's name will live forever in the repository. I suspect you didn't really want to do this. You might want to investigate the bookmarks feature for local branches that don't end up with names that live forever in the repository.
Mercurial balks at pushes that add new global branch names to the repository being pushed to because that's so very rarely what you really want to do. hg push --new-branch will tell Mercurial that yes, you really mean to do that.
The two heads you're seeing are misleading. Notice how one head is listed as '(inactive)'. That just means it's the last change on the global branch, but not an actual head. You frequently want to see the heads of branches, even if those heads actually have children and are not really heads.
As a small aside... I wrote the code that added that feature to the 'heads' command awhile back. :-)

Merging branches in tortoiseHg does not seem to work

In a project, I have a default branch and another named branch. After a merging both branches and committing it, the graph in TortoiseHg shows that both branches have been merged. However, pushing to a remote repository (which is at the stage before branching, it only has the default branch), I get the message "abort: push creates new remote branches".
If I'm not mistaken, I'm left with one branch after merging, so why this error message? Note: the graph still shows that I have 2 heads, is it in anyway related to this?
You're getting that error message because the named branch -- and all its changesets -- still exists in your local repository: you've merged the changes into the default branch, that's all.
You see two heads because you're using a named branch: from the help text for hg heads (the command line equivalent of selecting Heads in the repository explorer):
Branch heads are changesets that have no child changeset on the same branch.
Since you have two branches in your local repository (default and the named branch), you have two heads by definition.
To resolve the error message that you're getting, in the repository explorer, there's a Push New Branch option at the bottom of the Synchronize menu; select it, then you should be able to push to the remote repository.

Named previously unnamed branch

It seems naming a previously unnamed branch doesn't really work out. It creates a nasty multiple heads problem that I can't find a solution for.
Here is the workflow...
UserA starts working on feature that they expect to be small, so they just start working(off the default branch). The change turns out to be a large project and will need multiple contributors. So UserA issues... hg branch "Feature1" and continues working, committing locally s needed.
UserA then pulls down the changes from the central repo so he can push.
At this point, why does hg heads return 3 heads? It shows 2 for default and 1 for Feature1. The first head for default is the latest change by another user on the branch(irrelevant). The second default head is the commit prior to the hg branch "Feature1" commit.
The central repository has rules enforced so that only 1 head per branch is allowed, so forcing a push isn't an option. The repo doesn't want multiple heads on the default branch.
UserA should be able to push these changes so that other users can see the Feature1 branch and help out. I can't seem to find a way to "correct" this. I don't think I can re-write the branch of the initial commits for the feature, before it was a named branch.
I know the initial changes before the named branch are technically on the default branch, but does that mean they will be heads until that Feature1 branch is merged?
I have found a solution without have to re-clone and merge changes in. I prefer this method mainly for historical purposes as I think it's valuable information on what happened with the feature (aka it started small and then was re-thought to be larger etc..)
In my example, UserA should update to the unwanted head on default and close that branch of default, as it is unwanted. This will leave 2 heads one for default and one for Feature1 as expected.
hg update -r X // X is the rev of the unwanted head.
hg commit --close-branch -m "Moved to Named Branch Feature1, cleaning up initial work"
Then update to the Feature1 branch, push and continue working.
Another workflow is almost the same except the UserA decided to push Feature1 for others to help and default has not been moved forward by anyone else. The local repo only has 2 heads and the user could push, but UserA does NOT want to just push as the tip of default would now be the changeset that really "belongs" to Feature1.
UserA should update to the latest, unwanted changeset of default. Then revert the default back to the revision before UserA starting working.
hg update default
hg revert -r Y // Y is the changeset before UserA started working on the feature
hg commit -m "Reverting changes that now exist in Feature1 branch"
Then update to the Feature1 branch, push and continue working.
The reason you're seeing two heads on the default branch in the local repo is because, after the most recent common ancestor, the changesets in the central repo have nothing in common with the changesets in the local repo.
To solve your problem:
Create a new local clone of the central repo at whatever revision you want (it will probably be easier if you use the most recent common ancestor).
hg clone -r common_ancestor central local2
Export the changes from the first local repo. Note the colon after first_local_change to get all the changes in that repo.
cd local1
hg export -r first_local_change: > ../local1.patch
Go to the new local repository, create the feature branch to import the changes into, then import them:
cd ../local2
hg branch feature
hg import ../local1.patch
hg import has an option to use the branch information in the patch file, but it's disabled by default.
At this point, you can continue using the new local repo in the original one's place. Also, I would double check to make sure that everything is as it should be in the new repo.
We found this to be a very big problem with our team (doing branch-per-feature) and ultimately stopped the hgweb.cgi script working (HTTP 414 Request too Long).
from hg help heads: hg heads with no args will show branch heads, which by definition are changesets that have no children on the same branch. hg heads --topo should give you result you need in this case.
Don't go via the central repository. Just have your developers pull from each other.