I have the following situation:
I have some changes on a branch, and another dev had closed and pushed the same branch.
When I tried to push I got the "push creates new remote head" message, but when I pulled there was nothing to pull, and when I attempted to merge I got the message that the branch only had one head.
The solution to this problem was to merge, but specify a revision using -r
I merged to the revision where my colleague had closed the branch, and then I was able to commit and push and all was good again.
The issue was that mercurial will not merge with a closed head, unless you specify the revision.
When searching SO I couldn't find this specific problem with this solution, so I thought worth adding in the hope that it will help someone else.
Related
I'm currently dealing with the fallout from BitBucket dropping HG support. We're going to be giving hg-git a try because, while my preference is self-hosting, my boss isn't quite mad enough at Atlassian to move away from BB yet. Taking this opportunity to clean up our existing HG repo before the conversion to GIT. Have used hg convert to remove some accidentally committed binaries to reduce size, etc.
One thing I've noticed is that we've got about two dozen old branches that are technically "open", but have been merged into default (no closing commit, but they're months to years old). Is there any way I can use a tool like hg histedit or during the hg convert to go back and specifically mark old branch heads with --close-branch?
Looking through docs I can find things about editing files, editing the contents of commits, or modifying commit messages, but nothing I can find mentions meta-data around whether a commit is "closed". I know this is just a flag on a given commit, but I don't know how to retroactively add it via any HG extension.
Edit: Just to add a bit more clarity, I recognise I can just update to each of these old branches & add a new commit that just closes the branch. There'll be a lot of dangling-looking, closed heads, but that'd work fine enough. However, I also then have to give each of them a bookmark in HG as well, or these additional "closing" commits are lost in the hg-git conversion. I'd rather avoid having to add ~30 additional branches to the git branch-list, just to have them show up as closed properly in HG without having to use revsets.
What I want to do isn't "essential" in the grand-scheme of the repo, but I'd be surprised if editing a commit's metadata to say --close-branch were impossible.
I tested out the rebase idea with a mock repository and it seemed to work.
Here was the starting repo:
And here was the state after rebase:
I think this example matches what the question was asking about. The original dangling close-branch changeset was moved to precede the merge.
I updated to default and ran the following command:
hg rebase --dest=4 --source=3 --keepbranches --config=ui.merge=internal:merge
I actually used Tortoise Workbench to execute the rebase and that is the command it used. So the final argument for ui.merge is probably not strictly necessary.
As you may have already noticed using hg convert its a really good idea to make new clones when you go to modify the repository. Thus if it gets messed up you have an easy undo option. I'd certainly recommend that approach for this operation as well.
I'm fairly new to version control in teams. So far I've mostly used it solo.
I've read that the following workflow is recommended:
Commit locally, pull master, merge master into my branch, merge my
branch into master, push. Several times a week or even day
So that's what I tried to do. However, when I was done with my feature, and tried to push, tortoise hg told me, that this would create new remote heads.
hg help push tells me about two options:
Merge first: Did that
Use -f: I know enough not to do that.
I think I understand the concept of rebasing - which I don't think applies here, since I'm the only one who did anything in this commit tree. Of course I've pulled.
So my question is: How can I resolve this specific situation?
Also, recommendations for where to learn proper version control workflow would be nice. Everything I find tells me what the commands are, but I've failed to find clear instructions on when to use them.
I've added a picture of the project. Commit 147 was mine, and I could push it just fine. All oher commits are also made by me.
hg reports a "head" for every named branch. In your screenshot, you are needing to push rev 154, which is the head of your kjeld branch. It is an outgoing changeset because you are pushing rev 155 and you must therefore push 155's entire history as well. Others will get that branch when they pull your changes and will have a head on their version of kjeld (note that it will most likely not be numbered 154 since those numbers are repo specific). You will be fine though since that head is a close-branch changeset so it will not appear in their default list for hg heads and hg branches.
One way to avoid your current issue is to use bookmarks to temporarily note what that head represents e.g. issue-45, big-feature-2, etc. and only push when merged into mainline development.
For us, we set up a "private" repo for each dev on the server where they store/backup work in progress. It is expected that there are multiple heads, dead branches, and other gunk in these "private" repos. The dev repo, however, only ever has a single head and must pass the build and build tests.
In response to your comment about your "private" branch: When you push your tip you will also push your branch named kjeld. Others who want to work on that code must pull it to get the tip of your development. It will not be a "private" branch.
Please can someone guide me through a process here?
I'm a bit of a newb in Mercurial so I'll post a pic to be more specific.
Here's the tree of our repo right now:
We have 2 branches: processors and extra libraries.
We created extra libraries after processors to test certain issues. Then we closed it and continue working on processors.
Now it occurred the need to change back to extra libraries in #645 to push some new stuff for testing. Is this possible now? and how can I do it with TortoiseHG?
Thanks in advance!
PS: Sorry for the silly question but I want to be very careful on this repo..
Closed branch is usual branch, which just have some additional meta-info in branch-head.
If you want to "reopen" closed branch, you have
Update to head's changeset (645)
So some (needed) changes in working dir and commit: changeset 658 will be new head of active named branch, tip of repository and closed named branch will become open
I forked someone elses repository on Bitbucket and made some changes (and pushed them to my forked repo). In the meantime, the original author made substantial changes (pretty much a rewrite).
I want to update my repo to be exactly the same as his (but with my changes still present on that tag) in a way that he can easily pull my new changes without the previous changes I made affecting anything.
I pulled his changes into my local version, which left me with 2 heads. I want to just take his head as the tip/default. I tried to resolve this (based on some SO answers) by doing:
hg update -r [myrev]
hg commit --close-branch
hg update -r [hisrev]
This seemed to put me in a state I wanted. My working directory looks like his. However, when I tryed to hg push I'm told this will create multiple remote heads, and I'm not sure if this is what I want (the message makes it sound scary!)
So, have I done this correctly? Should I force the push? Will this do what I want (eg. keep a copy of my changes so I can get to them, but in a way that generally won't interfere?). If so, was this the best way to achieve this?
Heads on a closed branch are still heads, so if you want to push those changes you'll need --force.
The other option, is to merge that head into what you want to be your default branch, but select none of its changes. This can be done non-interactively using:
hg update [hisrev]
hg --config ui.merge=internal:local merge [myrev]
hg commit
You'll be down to one head, and it will have only his content, but yours is still available in the history.
I love the flexibility of named branches but I have some concerns about the prolifieration of heads.
Even when the branch is closed, it still shows up in the heads. I have an idea for how to clean up the output from "hg heads"
My question to the gurus: "What am I missing?"
First off you may ask, Why might I want to totally hide the head of a named branch? For various reasons:
the feature is a bad idea
the feature is a good idea that is not ready for merging to tip, but maybe in a few months
the branch is a patch release to an older tagged version
edit: It turns out the prolifiration of heads is a symptom of the older version of mercurial I was using. Closing the branch hides the head of the branch it on newer Mercurial versions.
My idea is to have a "dead" head branch onto which all these closed branch heads will be merged.
The dead head would be parented by changeset 0 and serve the sole purpose of bundling up the stray heads that are not needed right now.
The deadhead has only other deadhead children, which never get merged back into the default branch.
You can use hg commit --close-branch to mark a branch as closed:
http://www.selenic.com/mercurial/hg.1.html#commit
Closed branches will not show up in hg branches or hg heads by default (only if the -c/--closed option is specified), so I'm not sure how you're seeing "clutter"?
What exactly would you gain by merging things?
There seems to be a downside to leaving dead heads which is not solved by later versions of Mercurial.
Suppose you have a lot of closed branch heads and only a single non-closed active branch. Suppose further that at some later point you make a bad commit (rev bad) on top of the non-closed head (rev good). Before you push you'd like to clone your repository dropping that bad commit. That is usually a simple thing to do -
hg clone --rev good BadRepo FixedRepo
This unfortunately does not pull the closed branch heads since they are not ancestors of rev good. All those branches which were closed will not be closed in the cloned repository. I tested this with Mercurial 2.3.1.
Thoughts?
p.s. The hgflow extension does close feature and release branches before merging. This avoids the closed heads problem.
Regarding the clone being an ugly approach, it has worked quite well and easily for me. The clone replaces the repository with the bad commit. The clone is a local effort. That bad repository is just discarded. I usually realize I've made a bad commit very soon after.
The -b option is just a way to rephrase the --rev by using a branch name instead of a change set identifier. Using the --rev option does pull the entire topological tree under the revision. If the revision is the head of the branch then the --rev clone is the same as the -b clone. -b leaves the same problem that I described with the --rev option. Branches which were closed in the original repository get reopened if they were left as heads.
If the pattern is to leave closed heads then they will soon greatly outnumber relevant heads. Getting those closures into a clone is quite an effort unless you do a full clone.
I feel I've muddied the waters with why I might do a partial clone. I'll restate my concern about closure heads more carefully.
For any partial clone from repository X to repository Y, if there exists a branch B in repository X with a closure head and that branch is included in the clone for purely topological reasons, then branch B will not be closed in repository Y. Further if the merging pattern is to generally leave closure heads then the number of closure heads is of order development time.
This is a concern to me so I close my branches before I merge. I use hgflow (http://nvie.com/posts/a-successful-git-branching-model). A possible partial clone would be to clone the development branch and follow that with a pull of the master branch (e.g. if you wish to eliminate dead ends). If feature and release branches had been closed after their final merges then those branches would be reopened in the clone.