0

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…

  1. 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?).

  2. 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.

  3. 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.

Benjohn
  • 13,228
  • 9
  • 65
  • 127
  • [Backing out multiple consecutive changesets in Mercurial](http://ehsanakhgari.org/blog/2010-09-09/backing-out-multiple-consecutive-changesets-mercurial) seems useful as an implementation of option 2. I'll give it a try, though I don't entirely understand it! – Benjohn May 20 '14 at 13:54
  • I note: `rollback` is the mercurial term for undoing just the most recent commit. `backout` is the term for attempting to remove the effect of _any_ _one_ specific change set. – Benjohn May 20 '14 at 13:57

2 Answers2

3

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.

Community
  • 1
  • 1
Edward
  • 3,292
  • 1
  • 27
  • 38
  • Thanks Edward – I'm unsure with your 2 how I tell Mercurial that my new line of development should become `default`, instead of the old abandoned line? – Benjohn May 21 '14 at 08:43
  • Ah, `default` is _the_ anonymous branch? All branches may have multiple `head`s? I close the `head` on `default` at the end of my abandoned line of development (and tag it, if I wish), then start a new `head` on `default` growing from the last good version? This makes sense. It's only downside is it doesn't mark the abandonment as well as I would hope, but I'm not too fussed by that. – Benjohn May 21 '14 at 08:49
  • What I've done (but it's nice to know better option for next time!) is to `hg revert -r ` at the `head` of `default`, committed that, and continued working from there. This leaves the `default` branch being linear, rather than becoming a tree. I would have preferred it to have become a tree, with the abandoned limb being closed and ignored, as you suggest I could have done. – Benjohn May 21 '14 at 08:52
  • 1
    Yes, default is _the_ anonymous branch(es) and there is no compelling reason to force things linear since they actually diverged. Sounds like you found something that worked for you, though, which is what matters! – Edward May 21 '14 at 14:19
1

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.

Oben Sonne
  • 9,893
  • 2
  • 40
  • 61
  • Thank you! I had been keeping away from the experimental commands, but perhaps I should reconsider? Can I ask – why would I null merge the abandoned work, rather than just closing its head and leaving it, kind of floating, on a limb apart the line I continue on? – Benjohn May 21 '14 at 08:59
  • That's a personal preference. For me a null-merge expresses the intent to abandon the changes from another head, in the sense of "I do not need it anymore". Keeping the head present (though closed) may be interpreted as "may be continued in the future". – Oben Sonne Jul 11 '14 at 21:32