In mercurial, how do I apply a reverse-patch to a particular file?

djsadinoff picture djsadinoff · Jul 6, 2009 · Viewed 9.3k times · Source

Related to Mercurial: Merging one file between branches in one repo , I'm trying to perform a backout operation on a single file, even though that file was one of many participants in the revision being backed out.

HG being the changeset-oriented tool that it is, it doesn't want to operate on files.

Closest I could find was to use hg export to create a diff, hand-edit the diff, and then hg import to patch the file in reverse order.

..but then I hit this annoying situation where http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html claims that there is a --reverse option to hg patch when there is not.

So the closest thing I can think of is to generate a hand-edited patch as above, and then using vanilla patch -R to apply a reverse patch.

The hg backout command would seem to be useful here, but is actually a red herring.

There has GOT to be a better way, no?

Answer

Ry4an Brase picture Ry4an Brase · Jul 7, 2009

You can do it using just the -I (include names matching the given patterns) argument for backout with a single line:

hg backout --merge -I thefiletorevert -m 'message' OFFENDINGREVISIONID

Example Script:

hg init testrepo
cd testrepo
echo -e "line1\n\nline3" > file1
echo -e "line1\n\nline3" > file2
hg commit -A -m 'changes to two files'
perl -pi -e 's/line1/line 1/' file1
perl -pi -e 's/line1/line 1/' file2
hg commit -m 'put spaces in line1'
perl -pi -e 's/line3/line 3/' file1
perl -pi -e 's/line3/line 3/' file2
hg commit -m 'put spaces in line3'
hg backout --merge -I file1 -m 'remove spaces from line1' 1

Sample output:

adding file1
adding file2
reverting file1
created new head
changeset 3:6d354f1ad4c5 backs out changeset 1:906bbeaca6a3
merging with changeset 3:6d354f1ad4c5
merging file1
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

Resulting File Contents:

file1:line1
file1:line 3
file2:line 1
file2:line 3

notice that file1 is missing it's space in line one after the backout of the middle changeset, and the verbose log shows only one file changed in the backout:

$ hg log -v -r tip
changeset:   3:6d354f1ad4c5
tag:         tip
parent:      1:906bbeaca6a3
user:        Ry4an Brase <ry4an@mini>
date:        Mon Sep 14 12:17:23 2009 -0500
files:       file1
description:
remove spaces from line1