Cómo hacer que el parche ignore los trozos ya aplicados

Tengo un file de parche muy grande que bash aplicar a mi código. El problema es que algunos de los cambios en mi parche ya existen en el código. ¿Hay alguna manera de hacer que el parche ignore con gracia los cambios que ya se han aplicado?

La opción -N no hace lo que quiero. Si encuentra un trozo ya aplicado generará un file de rechazo y no aplicará más trozos a ese file. Quiero que simplemente ignore ese trozo y continúe aplicando el rest del parche. La única vez que quiero que genere un file .rej es si un trozo no se puede aplicar y no parece que ya se haya aplicado.

¿Hay alguna forma de hacer esto?

Necesitarás patchutils instalados para esto.

Este script dividirá un parche grande en paches separados más pequeños, cada uno de los cuales contiene solo un hunk para un file. A continuación, puede aplicar estos parches con patch --forward .

 #!/bin/sh -eu PATCH=$1 OUTDIR=$2 test -f "$PATCH" && test -d "$OUTDIR" TDIR=$(mktemp -d) trap 'rm -rf $TDIR' 0 INDEX=0 TEMPHUNK=$TDIR/current_hunk lsdiff $1 | while read FNAME do HUNK=1 while : do filterdiff --annotate --hunks=$HUNK -i "$FNAME" "$PATCH" > "$TEMPHUNK" HUNK=$((HUNK+1)) test -s "$TEMPHUNK" && \ { mv "$TEMPHUNK" "$OUTDIR/$INDEX.diff" INDEX=$((INDEX+1)) } || break done done 

Editar : guarde el script en hunks.sh y hunks.sh :

 ./hunks.sh path/to/big.diff path/to/output/directory 

Eventualmente resolví esto usando una solución similar a la de Artyom.

Paso 1: explote el parche en muchos parches separados, uno para cada trozo.

Usé este script para hacer esto:

 #!/usr/bin/python2 import sys header = [] writing_header = False patchnum = 0 patch = open(sys.argv[1], "r") out = open("/dev/null", "w") for line in patch.readlines(): if line.startswith("diff"): header = [] writing_header = True if line.startswith("@@"): out.close() out = open(str(patchnum) + ".diff", "w") patchnum += 1 writing_header = False out.writelines(header) if writing_header: header.append(line) else: out.write(line) out.close() 

Ejemplo de uso:

 $ cd directory_containing_patch $ mkdir foo $ cd foo $ explode.py ../huge_patch.diff 

Esto poblará el directory actual con files llamados 0.diff 1.diff et cetera.

Paso 2: aplique cada parche, descartando parches ya aplicados.

Usé este script para hacer esto:

 #!/bin/bash if [[ $# -ne 1 || ! -d "${1}/" ]]; then echo "Usage: $0 dirname" exit 1 fi find "$1" -name \*.diff | while read f; do OUTPUT=$(patch -s -p1 -r- -i"$f") if [ $? -eq 0 ]; then rm "$f" else if echo "$OUTPUT" | grep -q "Reversed (or previously applied) patch detected!"; then rm "$f" fi fi done 

Ejemplo de uso:

 $ cd directory_containing_code $ apply_patches.bash directory_containing_patch/foo 

Esto eliminará cualquiera de los parches generados previamente que se aplican limpiamente o que ya se han aplicado. Todos los parches que quedan en foo son rechazados y deben ser examinados y fusionados manualmente.