Is there a way to skip a commit when pushing - mercurial

I had commited an exploratory and buggy changeset locally. The bug has been fixed in the next local commit. Now I want to push the debugged version but in a way that skips the buggy local commit. Is there a way to do this simply.

Short answer: no.
Long answer: you can leave a chain of recent commits out of a push but you can't miss out parts of the chain when you push. This is because mercurial tracks the changes you made at the point of committing and your most recent changeset probably doesn't make sense outside of the context of the buggy one.
Options:
Some people would recommend using the MQ extension to avoid this problem in the future.
Some people would recommend using the MQ extension to strip out both changesets and then re-commit only the fixed version. This can cause trouble, particularly if you've already shared your changesets with anyone.
Some people (including me) would recommend just leaving your repository as it is and pushing both changesets. There's only shame in a buggy changeset if you don't fix it.

4 Some people (including me) would recommend using the MQ extension for folding two consecutive changesets into single before push
5 Some people would recommend using the histedit or colapse extension for folding two consecutive changesets into single before push

You could try this :
Export the commit you want to go through as a patch
Re-clone your repository in a new directory
Apply the patch
Now perform the single commit to your shared repository

Related

Mercurial: devs work on separate folders, why do they have to merge all the time

I have four devs working in four separate source folders in a mercurial repo. Why do they have to merge all the time and pollute the repo with merge changesets? It annoys them and it annoys me.
Is there a better way to do this?
Assuming the changes really don't conflict, you can use the rebase extension in lieu of merging.
First, put this in your .hgrc file:
[extensions]
rebase =
Now, instead of merging, just do hg rebase. It will "detach" your local changesets and move them to be descendants of the public tip. You can also pass various arguments to modify what gets rebased.
Again, this is not a good idea if your developers are going to encounter physical merge conflicts, or logical conflicts (e.g. Alice changed a feature in file A at the same time as Bob altered related functionality in file B). In those cases, you should probably use a real merge in order to properly represent the relevant history. hg rebase can be easily aborted if physical conflicts are encountered, but it's a good idea to check for logical conflicts by hand, since the extension cannot detect those automatically.
Your development team are committing little and often; this is just what you want so you don't want to change that habit for the sake of a clean line of commits.
#Kevin has described using the rebase extension and I agree that can work fine. However, you'll also see all the work sequence of each developer squished together in a single line of commits. If you're working on a stable code base and just submitting quick single-commit fixes then that may be fine - if you have ongoing lines of development then you might not won't want to lose the continuity of a developer's commits.
Another option is to split your repository into smaller self-contained repositories.
If your developers are always working in 4 separate folders, perhaps the contents of these folders can be modularised and stored as separate Mercurial repositories. You could then have a separate master repository that brought all these smaller repositories together within the sub-repository framework.
Mercurial is distributed, it means that if you have a central repository, every developer also has a private repository on his/her workstation, and also a working copy of course.
So now let's suppose that they make a change and commit it, i.e., to their private repository. When they want to hg push two things can happen:
either they are the first one to push a new changeset on the central server, then no merge will be required, or
either somebody else, starting from the same version, has committed and pushed before them. We can see that there is a fork here: from the same starting point Mercurial has two different directions, thus a merge is required, even if there is no conflict, because we do not want four different divergent contexts on the central server (which by the way is possible with Mercurial, they are called heads and you can force the push without merge, but you still have the divergence, no magic, and this is probably not what you want because you want to be able to checkout the sum of all the contributions..).
Now how to avoid performing merges is quite simple: you need to tell your developers to integrate others changes before committing their own changes:
$ hg pull
$ hg update
$ hg commit -m"..."
$ hg push
When the commit is made against the latest central version, no merge should be required.
If they where working on the same code, after pull and update some running of tests would be required as well to ensure that what was working in isolation still works when other developers work have been integrated. Taking others contributions frequently and pushing our own changes also frequently is called continuous integration and ensures that integration issues are discovered quickly.
Hope it'll help.

Mercurial: abandoning multiple, contiguous commits, on the `default` branch

Requirement
I'd like to abandon a line of development on the default branch, winding back to a revision from about 15 change sets back, and have default proceed from there.
My setup
This is a solo development project with one other guy testing infrequently. I push (frequently) to bitbucket for backups and sharing with the tester. Several of the changes I want to abandon are pushed to BitBucket.
Options
Any of these would be fine…
The abandoned change sets to continue to exist in the repo. It would be nice if they could live on their own branch abandoned-experiment-1, say, that I can close and ignore, but this would need them to move on to a retrospectively created branch (which seems like it would be an awesome feature?).
Some kind of merge to happen where I add a new revision to default that is the rollback to the revision I want to continue from.
The change sets to be destroyed, but I suspect there's no way to achieve that without replacing the BitBucket repo and my tester's repo, which I'm not keen on.
I'm not too sure how to evaluate which options are possible, which is best, or whether there are other, better options. I'm also not sure how to actually proceed with the repo update!
Thank you.
You do have several options (Note that I'm assuming that you are dispensing with all changes in the 15 or so revisions and not trying to keep small bits of them):
Easiest is kinda #2: You can close anonymous branches just like named branches; Tag the tip first with abandoned-development if you wish; hg update to the point you wish to continue from; and continue to code as normal. (You may need to create the new head for new development before you can close the old one. I haven't tested it yet.)
Regarding #3: Based on my cursory read, it does appear that bitbucket has a strip command. If you (both locally and on bitbucket) and your tester strip the offending changesets, you can carry on your merry way and pretend like they never existed.
Achieving #1: If you are definitely set on getting them to a named branch, you could strip them at the remote repos and then hg rebase them onto a new branch locally and then close that branch.
Personally, I try not to mess with history when I can avoid it, so I'd go with the easiest.
Mercurial now has (yet experimental) support for changeset evolution. That is you are able to abandon or rebase already pushed changesets. Internally this works by hiding obsolete changesets (i.e. practically nothing is stripped, only new replacement revisions are added to the history, that is why it works across multiple clones).
To extend #Edward's suggestions, you could also update to the last good revision, continue to commit from there and then merge in the head of the bad changesets using a null-merge:
hg up <good-revision>
... work ... commit ...
hg merge <head-of-bad-revisions>
hg revert --all -r .
hg commit -m 'null-merge of abandoned changesets'
This may be what you thought of as option 2.

Is there any way of deleting a branch that has been pushed to a repo shared by all developers?

I have accidentally pushed a branch to a repo. Is there anyway I could alter the repo ( and remove the branch )? Closing it is not a solution.
You got a couple of options, none of them easy, and none of them will leave you with a "phew, saved by the bell" feeling afterwards.
The only real way to fix this problem is to try to avoid it in the first place.
Having said that, let's explore the options here:
Eradicate the changesets
Introduce further changesets that "undo" the changes
The first option, to eradicate the changesets, is hard. Since you pushed the changesets to your central repository, you need direct access to the repositories on that server.
If this is a server where you don't have direct access to the repositories, only through a web interface, or through push/pull/clone, then your option is to hope that the web interface have methods for eradicating those changesets, otherwise go to option 2.
In order to get rid of the changesets, you can either make a new clone of the repository with the changesets, and specify options that stop just shy of introducing the changesets you want to get rid of, or you can use the MQ extension and strip the offending changesets out.
Either is good, but personally I like the clone option.
However, this option hinges on the fact that any and all developers that are using the central repository either:
Have not already pulled the offending changesets from the central repository.
Or are prepared to get rid of said changesets locally as well.
For instance, you could instruct all your developers to kill their local clones, and reclone a fresh copy after you have stripped away the changesets in the central repository.
Here's the important part:
If you cannot get all developers to help with this, you should drop this line of thought and go to option 2 instead
Why? Because now you have two problems:
You need to introduce barriers that ensure no developers can push the same changesets onto the server again, after you got rid of them. Note that relying on the warning by the server to prevent new branches being pushed is perhaps not good enough, as developers might have branches of their own they want to push, and thus not notice that they'll be pushing yours as well.
Any work any developer has done based on any of the offending changesets must either be rebased to a new place, or eradicated as well.
In short, this will give you lots of extra work. I would not do this unless the offending changesets were super-critial to get rid of.
Option 2, on the other hand, comes with its own problems, but is a bit easier to carry out.
Basically you use the hg backout command to introduce a new changeset that reverses the modifications done by the offending changesets, and commit and push that.
The problem here is that if at some point you really want to introduce those changesets, you will have to fight a bit with Mercurial in order to get the merges right.
However, there will be no more work for your fellow developers. The next time they pull, they'll get your correction changeset as well.
Let me just restate this option in different words:
Instead of getting rid of the changesets, keep them, but introduce another changeset that reverses the changes.
Neither option is good, both will generate some extra work.
We've ran into a similar problem once, when we had to remove a branch from the server repo from which all devs regularly pull. Backout wasn't an option because the problematic branch had already been pulled by everyone.
We stripped (hg strip from the MQ extension) the branch in the server repo. From now on, if a developer tried to push, he had a message “push creates new remote branches”, even though they didn't actually created any. We created a batch file with the strip command, distributed it among the devs and explained the “new remote branches” is a signal to run the batch file.
This approach takes some time and effort before everybody gets rid of the branch, but it works.
If the 'backout' option described in Jason's comment above doesn't do it for you, you can remake the repo up until the point of your mistaken push using hg convert, which (despite its name) also works with hg.
eg hg convert -r before-mistaken-push /path/to/original /path/to/new
You might have to play with the usebranchnames and clonebranches settings.

How do I permanently remove (obliterate) files from history?

I commited (not pushed) a lot of files locally (including binary files removing & adding...) and now when I try to push it takes a lot of time. Actually I messed up my local repo history.
How could I avoid this mistake in the future ? Can I transform a set of local revision 1->2->3->4 to 1->2 with 2 being the final revision of the local clone ?
edit: since I was in hurry I started a new remote repo from scratch with revision 4. In the future I will go with the marked answer as it seems easier but I will dig other solutions to see the truth. Thx for your support.
It's not clear from your question whether those changes got pushed. If they're still local, you can more or less get rid of them easily. convert is one option. You can also use MQ (mercurial queues). Check the EditingHistory wiki article for a detailed explanation. It recommends MQ being the simplest approach.
To prevent that kind of mistakes, you should probably add a hook to reject 'bad' commits, given that you can describe them programatically ;)
Mercurial history is immutable, you can't delete using the normal tools. You can, however, create a new repo without those files:
$ hg clone -r 1 repo-with-too-much new-repo
that takes only revisions zero and one from the old repo and puts them into a new repo. Now copy the files from revision four into the new repo and commit.
This gets rid of those interstitial changesets, but any repo you have out there in the wild still has them, so when you pull you'll get them back.
In general once you've pushed a changeset it's out there and unless you can get everyone with a clone to delete it and reclone you're out of luck.

Using mercurial's mq for managing local changes

I have a local mercurial repository with some site-specific changes in it. What I would like to do is set a couple files to be un-commitable so that they aren't automatically committed when I do an hg commit with no arguments.
Right now, I'm doing complicated things with mq and guards to achieve this, pushing and popping and selecting guards to prevent my changes (which are checked into an mq patch) from getting committed.
Is there an easier way to do this? I'm sick of reading the help for all the mq commands every time I want to commit a change that doesn't include my site-specific changes.
I would put those files in .hgignore and commit a "sample" form of those files so that they could be easily recreated for a new site when someone checks out your code.
I know that bazaar has shelve and unshelve commands to push and pop changes you don't want included in a commit. I think it's pretty likely that Mercurial has similar commands.
I'm curious why you can't have another repo checked out with those specific changes, and then transplant/pull/patch to it when you need to update stuff. Then you'd be primarily working from the original repo, and it's not like you'd be wasting space since hg uses links. I commonly have two+ versions checked out so I can work on a number of updates then merge them together.