Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to back out multiple changesets in mercurial?

Tags:

mercurial

Is the most reliable method to go one-by-one, using the backout command for each of many changesets, or is there a way to create one big reversal changeset to cover a whole bunch of [edit: non-contiguous] changesets.

If one-by-one, does order matter? (Should one go last-to-first?)

Does the best method differ if there are merges among different sub-projects along the way?

Does this tend to go smoothly in your experience? :-)

like image 521
Joshua Goldberg Avatar asked May 21 '12 20:05

Joshua Goldberg


People also ask

How do I revert a changeset in Mercurial?

Revert changes already committed To backout a specific changeset use hg backout -r CHANGESET . This will prompt you directly with a request for the commit message to use in the backout. To revert a file to a specific changeset, use hg revert -r CHANGESET FILENAME . This will revert the file without committing it.

How do you undo a pull in mercurial?

There is only one level of rollback, and there is no way to undo a rollback. It will also restore the dirstate at the time of the last transaction, losing any dirstate changes since that time. This command does not alter the working directory.

What is backout in mercurial?

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.

How do you Uncommit in Heartgold?

A simple way to 'uncommit' your last commit is to use hg strip -r -1 -k. In case the link breaks, the documentation mentioned by @phb states: hg rollback Roll back the last transaction (DANGEROUS) (DEPRECATED) Please use 'hg commit --amend' instead of rollback to correct mistakes in the last commit.


2 Answers

If you have no merges along the way, you can either back out every individual change (in reverse order), or, if there are many of them, do it with one big inverse patch.

If you have good changesets atop the ones you need to back out, better commit the inverse patch on top of the most recent bad changeset, then rebasing them onto the tip of the branch.

1 -- 2 -- A -- B -- C -- 3 -- 4
                     \
                      C'B'A'

$ hg up C
$ hg diff -r C:2 > backout.diff
$ hg import --no-commit backout.diff
$ hg ci -m "Backout A, B, C"
$ hg up 4
$ hg rebase -s C'B'A -d .

There will be problems if you want to back out merge changesets, see this wiki page for more information.

In such a case, if possible, consider re-doing the branch and stripping the old lineage. Otherwise, you might have to abandon the branch altogether, salvaging the good changesets via graft or transplant.

like image 105
Helgi Avatar answered Sep 27 '22 23:09

Helgi


There is --collapse option for rebase.

Helgi's answer can be upgraded into:

1 -- A -- 2 -- B -- 3 -- C -- 4 -- 5
                          \
                           C' -- B' -- A'

$ hg update --clean C
$ hg backout --rev C --message "Backed out changeset: C"
$ hg backout --rev B
$ hg commit --message "Backed out changeset: B"
$ hg backout --rev A
$ hg commit --message "Backed out changeset: A"
$ hg rebase --collapse --source C' --dest 5
$ hg commit --message "Backed out C, B, A"

which will result in the following

1 -- A -- 2 -- B -- 3 -- C -- 4 -- 5 -- C'B'A'

However, backing out in separate branch may result in [logical] conflict in the subsequent merge.

1 -- A -- 2 -- B -- 3 -- X  --  4 
                     \           \
                      B' -- A' -- M

if X depends on A or B, then M will have conflict (at least logical conflict).

like image 23
Afriza N. Arief Avatar answered Sep 27 '22 23:09

Afriza N. Arief