Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Mercurial do a reverse-patch?

Scenario: I've "inherited" a program, kept under Mercurial, that only works on my system with specific tweaks to certain files that are checked in. I do not want to check these tweaks in.

My most recent solution to this is to create a mercurial patch file (hg diff > patchfile) containing these tweaks; when I need to check in my changes, I'll just reverse-apply the patch, commit, and re-apply the patch. (If I had full control of the source, I'd just move all these little tweaks to a single configuration file that isn't under version control, putting a "sample" config file under version control)

Unfortunately, it seems that while the GNU patch command supports the --reverse flag, it does not support hg's multi-file diff format as a single patch file (or maybe it does, and I just don't know the switches for it?). OTOH, hg has its own patch command that can apply the diff, but that doesn't support any kind of reverse flag.

So my question is twofold:

  1. How should this be done in mercurial? Surely hanging on to a "tweak patch" isn't the only way to handle this situation. Maybe mercurial has a plugin or something built in for such temporary, uncommittable changes.
  2. Aside from how things should be done, is there any way to reverse-apply such a mercurial diff-patch to a mercurial repo like this? There are other situations where such functionality would be useful.
like image 673
eternicode Avatar asked Nov 26 '10 20:11

eternicode


People also ask

How do you reverse a patch?

Reverse a Patch that is Already Applied (Undo a Patch) You can use the -R option to reverse a patch which is applied already. You can notice from the filesize, that the patch, which is applied already is reversed when we used the -R option.

How to undo 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.


2 Answers

Mercurial's patch command (really import) doesn't support reverse, but hg diff does. Use --reverse on that and you'll have a reversed patch that Mercurial can apply.

However, what you're describing is a very common vendor-branch style workflow, which mercurial can better support using features other than diff and patch.

Specfically, Mercurial Queues does exactly what you want.

like image 115
Ry4an Brase Avatar answered Oct 28 '22 11:10

Ry4an Brase


I found --reverse approach did not work when you have sub repos. i.e.

 hg diff --reverse -S

. In case it helps anyone, this barely tested script seems to do the job:

#!/bin/bash

DIRS="$*"

if [[ $DIRS = "" ]]; then
    DIRS=$(echo *)
fi

for arg in $DIRS; do
    arg=$(echo $arg | sed 's/^\.\/*//g')
    repo=$(echo $arg | cut -d'/' -f-1)

    grep -q "^$repo = " .hgsub 2>/dev/null
    if [ $? -eq 0 ]; then
        if [ -d $repo ]; then
            cd $repo
            hg diff --reverse | sed -e "s;--- a;--- a/$repo;g" -e "s;+++ b;--- b/$repo;g"
            cd ..
        else
            echo Error, unknown repo $repo
        fi
    else
        hg diff $arg --reverse
    fi
done
like image 45
Goblinhack Avatar answered Oct 28 '22 12:10

Goblinhack