How can I purge a branch in mercurial? - mercurial

I am newbie dealing with mercurial. I did some mess trying on branches and now I want to "flat" all branches in just one "default"
josir#josir-desktop:~/bitbucket/campus$ hg branches
default 27:f28e8d8773c6
15 20:6b434f251b7e
branches has already been pushed to remote repo.
I want to purge all other branches discarding all changes on it. Reading those tutorial, I could not identify the best option to fix it.

The easiest thing is to just "close" the unwanted branches and leave them in peace:
hg update -r "branch('15')"
...
hg commit --close-branch
If you only have push/pull access to the remote repo, there's no way to remove changesets after you've pushed them. So close the branch and move on, or discard the bitbucket repo, clean the local one, and start over.
To clean up your local repo, if you have a big mess the easiest way is to pick a good revision (e.g., the tip of default, but you can choose an earlier one) and clone just that and all its ancestors:
hg clone -r <goodrev> messy-repo new-repo
The documentation (which you'd already cited) has a good explanation of this and several other branch-pruning options, but none of them are appropriate after you've pushed to a repository you don't control.

For already pushed branch you haven't any freedom: only --close-branch

When I issue hg branches, I got a two column report like the above:
josir#josir-desktop:~/bitbucket/spo$ hg branches
dev 232:31cf2690dd47 (inativo)
What have I understood for that ?
There are 2 opened branches :(
That was my big mistake. There is just ONE branch: dev
The second column "232:31cf..." is just the last commit of the "dev" branch!!!

Related

Safe way to purge history - Mercurial

I cloned a project to my local directory and made a lot of changes. My current goal is to push my changed code to a new branch in the remote repository. And eventually this new branch will be merged back to default.
My problem is, because of some stupid effort in the past a few weeks to try to recover some missing files, I end up with a few branch names that I don't want being shown in public.
Here's what I have:
$hg branches
dev-v02 197:xxxxx
dev2 194:xxxxx
dev 183:xxxxx
qa 189:xxxxx
$hg branch
dev-v02
My question is, if I push my current branch dev-v02 to the remote repository by "hg push --new-branch", and this branch later get merged back to default, will the unwanted branches show up in history of default? And if so, is there a safe way to purge them?
I do NOT want to discard my changes. I just don't want the unwanted branches showing up in "hg branches" or "hg his" commands by whoever later clones the project from the remote repository. I searched online and found "hg strip" but I couldn't tell from the article if it would also remove the changes I've made. Thanks.
Edit: I just cloned my local repository by "hg clone -r 197 original-dir dest-dir" as suggested by both kevin and chessbot and now hg branches shows:
dev-02 192:xxxxx
qa 187:xxxxx (inactive)
I guess "qa" remains because I had pushed it to the remote as a QA branch and closed it later, and I just have to live with that. I will push from this new directory from now on. Thanks guys for your help.
Try hg push --new-branch -b dev-v02 to specify that you're pushing only that branch.
(See: https://www.mercurial-scm.org/repo/hg/help/push)
Another thing you could do: Clone the repository locally on your machine, strip out the branches you don't want, and then push that clone to the server. Then you retain your history locally without pushing it to everyone else.
It depends.
Branches are permanently associated with a commit. The branch is part of the commit, and contributes to the hash. Changing the branch of a commit in the past would alter all commit hashes from that point forward. This is quite different from Git, where a branch is little more than an ephemeral pointer to a HEAD. Such pointers are implemented in Mercurial as bookmarks.
If the unwanted branches appear on commits which are (ancestors of) commits you want to publish, there is very little you can do, short of recreating the history with all-new hashes. This could (for instance) be done with hg export and hg import, along with local cloning and (probably) a certain amount of shell scripting. More efficiently, you could use the convert extension to automate the process. Since this changes commit hashes, it will likely cause serious problems if any of the commits have already been distributed publicly.
If you have no interest in sharing the offending commits, you can simply not publish them. This can be done with selective pushing. However, since you'll always have to manually exclude those commits every time you push, it's probably safer to clone and strip (or clone selectively with the -r flag). You can then push from your partial clone with impunity. Assuming you have a sufficiently recent version of Mercurial, you can also force the commits into the secret phase, so that they will not be pushed:
hg phase -fs revisions
You don't want to use hg strip, because it permanently removes the commits from the history (see Editing History in the Mercurial wiki)
If I were you, I would close the branches instead:
hg up -C badbranch
hg commit --close-branch -m 'close badbranch, this approach never worked'
hg up -C default
(source: Pruning branches in the Mercurial wiki)
After closing a branch, hg branches doesn't show it anymore.
If you do want to see closed branches, use the -c parameter:
hg branches -c
Disadvantage:
hg his still shows closed branches.
You could use the -b parameter though, to show only the default branch:
hg his -b default

creating a new branch in mercurial: "abort: push creates new remote head"

I am trying to do something very simple: create a new branch. But I messed up. Where did I make the mistake, and how do I fix it?
I am the only user of Mercurial. I had revision 54 committed and pushed to remote repository. I wanted to create a branch based on revision 53, so I updated my local copy to revision 53, made changes, and committed (ignoring the warning about "it's not the head"). Then when I am trying to push to remote repository, it says
abort: push creates new remote head
Maybe I needed to tell Mercurial that I want to create a new branch? If so, how and at what point?
Thanks!
You tell Mercurial that it can go ahead with
$ hg push --force
You need to force it since multiple (unnamed) heads are normally discouraged. The problem with them is that people that clone the repository wont know which one to use. But since you're the only user you can just go ahead and push.
The alternative is to use a named branch (with hg branch) and then you'll use
$ hg push --new-branch
to allow the creation of a new branch on the remote. Named branches have the advantage that they make it easy to distinguish the two branches. They have the disadvantage that they are permanent. Permanent means that you cannot remove the branch name from the changesets on the branch — the name is literally baked directly into the changeset.
Bookmarks provide a way to have non-permanent branch names, see hg help bookmarks.
Another reason for this error: probably there are some UNMERGED changes form the central repo in your default branch.
hg up default
hg merge
hg ci -m "Merge"
hg pus
I did this. Using TortoiseHg ... this is how I fixed it:
In settings, I enabled the Strip extension then right clicked the branch i did not want, Modified History - strip. If you have pushed, then it needs to be stripped from all other repositories, including workmates who have pulled your unwanted branch.
An alternative is to merge the unwanted branch into your main branch, but do not take any of the changes from that branch - I am unsure of how that mechanism works.

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. :-)

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.

Trying to merge back from branch to main and close branch in Mercurial

I've got a named branch (same repository) that was created in order to to spike something. I've now decided that I want to move all the changesets created in the branch back into the main (default) and then close the branch.
I've tried a number of different things, including what was outlined in this post (How to repeatedly merge branches in Mercurial) but I just can't get it working :(
Can anyone provide any pointers?
Thanks.
Merge the feature branch into default
hg up default
hg merge feature-branch-name
hg ci -m 'merged feature-branch-name into default'
Close the branch you don't want to use anymore
hg up feature-branch-name
hg ci --close-branch -m 'close feature-branch-name branch'
hg up default
Note that the close command doesn't have any disruptive effects on the repository history
It flags your branch as closed so that it won't appear in hg branches and hg heads commands output
I've managed to solve my problem using the link I mentioned in my question. The steps described in the link had actually merged my changes across however I didn't realise as I was looking in the TortoiseHg UI and couldn't see the changes there. When I performed hg outgoing via the command line it appears that the merge had worked correctly.