Mercurial: Fix a borked history - mercurial

So working on a project recently (by myself - no other developers), I somehow managed to seriously bork the history with some (apparently) bad merges from cloned repositories.
What I would like to do - need to do - is fix this by just deleting the last 8 commits (according to hg glog)
Yes, I have made a few changes to the code after the borking began, however, only a few tweaks here or there - nothing I can't fix fresh from memory.
How can I get rid of the last 8 commits and start over from where I messed up?

Make a clone of your repository - when you do this, you can specify the last commit that should be cloned.
So, if your repository has 100 changesets and you want to get rid of changesets 93 to 100, just do this:
hg clone -r 92 BadRepository CleanRepository
--> the CleanRepository will only contain changesets 1 to 92.
If you use TortoiseHG, you can do the same in the Clone dialog (there is a textbox "Clone to revision:")

Related

Can't push branch to remote Hg repo

I spent yesterday searching via Google and looking through SO for an answer but couldn't find anyone having the exact problem I'm having.
A while ago, I created a branch at Rev 176 in my local Mercurial repo and at Rev 196 created the named branch, "Port to VS2010." See the TortoiseHg screen cap below. I've been able to successfully push the other, "006-x86 and x64 Builds" branch to the remote repo but whenever I try to push the new branch, I get this error in the log:
abort: push creates new remote head 207852dab969!
hint: merge or see "hg help push" for details about pushing new heads
Short of merging or forcing it, how can I push this branch? It represents a tentative solution that will probably never be needed, but I wanted to keep it around just in case.
(Note: You'll notice three gaps in the Rev column. They represent immaterial changsets for the "006-x86 and x64 Builds" branch. I removed them in order to shorten the image.)
Update:
Per Lazy Badger:
acs_FromBuildServer_edited% hg heads -T "{node|short} {branch}\n"
% hg heads -T "{node|short} {branch}\n"
24af28a99211 006-x86 and x64 Builds
69be2af28b7c Port to VS2010
207852dab969 default
86e00db4ba95 005-No Register CardContext
9df44947cc8b 004-Hack typedef boost shared_ptr
81055bcdb3cc 003-Use boost shared_ptr
6358126f4757 002-Add Meyers Fix
1e23ed012883 001-Solution
bcc01f6fbef4 default
[command completed successfully Fri Feb 12 11:15:36 2016]
acs_FromBuildServer_edited%
Actually, you only have two choices. You can merge or you can force it. I think in your case you want to force it.
Typically, you don't want to force a new head because other developers might not be aware of the new head. Since this is an experiment you just want to keep for posterity then it's fine to force it. If you find out you need it you would merge it at that time.
It seems you have possible mix of two unrelated problems
anonymous branching (2 heads of some branch)
pushing new (not existing on remote) branch
New (named) branch have to be pushed with added option to default push command (--new-branch in CLI) or "Allow push to new branch" checkbox in THG GUI
Pushing additional head in bad idea in common, better to find this new head in pre-existing branch and merge
Well, as expected, you have two heads of default branch
207852dab969 default
...
bcc01f6fbef4 default
and according to error message head 207852dab969 (r195) is new, not pushed yet. No, closing branch will not allow you to push branch. If you don't want to merge or force push, you can move diverged history (from branchpoint) to another named branch

How to clone from a specific revision to the last one using Mercurial?

In Mercurial , How to clone from a specific revision to the last one using ?
For example repo A have one line history from changeset 0 to changeset 100. and I want to clone A to my local repo from changeset 90 to last one (100).
Looking through the help, I noticed the -r flag but that only clone 1 specific changeset.
And if there is no way to do it can somebody explain why its not implemented ? its considered a bad thing to do ?
Thanks.
You can't.
The current state of the project is all changesets from the beginning of time up until the specific changeset, you cannot prune older changesets without rewriting the history of the repository to permanently get rid of them. This will also make the repository incompatible with the original that contains the old history.
In short, you will have to do one of the following:
Prune the old history, permanently getting rid of it, which will make it impossible to push/pull with original clones that still has that history
Live with the history
The parameters to the clone command that specifies revsets thus only allow you to set an upper limit. This may allow you to avoid whole branches, if they aren't merged into the branch you end up cloning, but the clone command will always clone everything from the beginning of time.
For every changeset you clone, every predecessor will be cloned as well, and this cannot be avoided.

Can't push new heads - fail to see how they would be created

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.

Mercurial undo three hg push

I'm using mercurial VCS, I've mistakenly pushed three commits and I want them to be undone, can this be achieved?
I'm pretty sure no changes were propagated to anyone from the repository I pushed to, so I'm confident that this won't break anyones code...
I've tried hg rollback but since I have pushed I cannot undo anything in the right way. Also I know about hg backout, but I'm not sure if I should use this one for what I need...
Thanks!
EDIT
This is the graph log, I forgot to mention that some commits were part of a merge, but they too need to be undone...
tip
|
a
| \
| b
| /
c
|
d
I need to return the tip to c, or d if there is no other way to prevent that because of the merge...
If it's already pushed, there are only two things that you can do now:
1) If you are able to delete the central repository and replace it by another one:
You can clone the central repository, but tell Mercurial to clone only up to changeset "c".
Then you can take this repository (which doesn't have the wrong changes) and replace the "old" central repository (the one which does have the wrong changes) with it.
Disadvantage: if someone already pulled the unwanted commits and later pushes again, they are in the repository again.
So you need to make sure that either no one pulled the mistakes, or everybody who did deletes his clone.
2) If option 1 is not possible, you can use hg backout to undo the effects of the wrong changes - not the changesets themselves.
Quote from the link:
Backout works by applying a changeset that's the opposite of the changeset to be backed out. That new changeset is committed to the repository, and eventually merged.
So the three wrong changesets will remain in the repository, plus another three will be added, each of them reverting the effects of one of the three wrong changesets.
If you do it like this, it doesn't matter if someone else already pulled the wrong changes...as soon as he pulls the three "backout" changesets as well, everything is okay again.
If you're positive the push is the last thing that happened to that remote repository, meaning neither you nor anyone else has pushed to it, you can login to that system and run hg rollback.
If it's a repository on a machine to which you can ssh you can run this command on your local system:
ssh you#there hg -R /path/to/the/repo rollback
As always please do be really careful with rollback. It undoes the last action on the repository without altering the working directory at all, and it's not always clear what the last action was. For example, this is datalosss:
...hack...
hg commit -m 'important work'
hg update somewhere else
hg rollback
Yikes!

mercurial team repository / picking and choosing

I have a small team and I would like to do the following:
I have my trunk, I'll just call it TRUNK
Now, TRUNK is a project that's already in production and running. Now, the inevitable defects come in, but into bugzilla and are assigned to users.
Each user clones TRUNK to their local repositories and makes changes and pushes them to a directory TRUNK/projects (projects is not a clone of TRUNK, just a regular directory)
Now, the day comes where I want to create a new build called RELEASE and I want to merge some of the bug fixes (not all, just some) into RELEASE.
Notice, I am not committed to the idea of having TRUNK/projects/[bugfixes list], but that's what I currently have now and am more than open to any / all suggestions.
What are some ideas? Is there something I can do / should do differently? Again, I am open to any / all suggestions, including completely changing the above procedure (except for using Mercurial as that's what the company makes us use)
There are two ways to do this and they diverge not at release time, but when you do the bug fixes depending on what parent you give the bugfix changesets. The "good" way uses only push, pull, and merge. The less good way (it's not entirely bad, but it's certainly sub-optimal) is called cherry picking and it has drawbacks. The tricky part is that whether or not you're going to be able to move bugfixes into RELEASE via merge without moving everything from TRUNK into RELEASE is something you have to decide before you make that change.
Here's a really complete answer for a similar question that explains what's going on: Some help with merging legacy branch in Mercurial
The key concept though, is that you can merge a changeset into any branch you want but it brings with it all of its ancestor changesets. So you want your bug fixed to have minimal ancestry. That means fixing a bug not in a new changeset in TRUNK that happens to be the latest feature you added, but instead, first, hg updateing to a changeset that already exists in both your TRUNK and your RELEASE, and there are two great candidates for that. Either:
the changeset where RELEASE and TRUNK diverged
or
the changeset where the bug was introduced
My preference is for the later. If a bug was introduced in changeset 666 then every clone, branch, and build that has changeset 666 will want your fix. So when fixing it just do:
hg update 666
.. fix the bug ..
hg commit -m "fixed bug 55" # creats changeset 999 which a new head
Then you can do this:
hg update TRUNK
hg merge 999
and you'll know you're only pulling in a single changeset. Later when you're ready to release you can do:
hg update RELEASE
hg merge 999
and you're again only getting the single changeset you want.
The advantage of this mode of working over cherrypicking (using export/import or transplant) is that your fix exists only once in your repo. If you have 99 different vendor branches for various finicky customers and you want to see if they have the fix for bug 55 you can just do:
hg log -r 'descendants(999) and heads(FUSSYCUSTOMERBRANCHNAME)'
and if there are no results then that customer doesn't have 999 and thus doesn't have the fix for bug 55 in changeset 666. When you re-do the same work with multiple changesets (which is the result of export/import and transplant) that's harder to verify.
Common practice is to create topic branches.
Each new issue/ticket/enhancement is commited into separate branch.
Anytime maintainer wants to make new release he can merge all (or only some) that branches into "default" or even new branch called e.g. "release_1_x".
To be more precise. Developer working on code can still clone repository, then create local branch and finally, after one or more commits to that branch, pushes local changes to one centralized clone (from which every other developer in team can pull/clone again).