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? :-)
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.
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.
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.
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.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With