パッチを適用済みのハンクを無視する方法


14

コードに適用しようとしている非常に大きなパッチファイルがあります。問題は、私のパッチの変更の一部がすでにコードに存在していることです。既に適用されている変更をパッチが正常に無視するようにする方法はありますか?

-Nオプションは、私がやりたいことはありません。既に適用されているハンクが検出されると、拒否ファイルが生成され、そのファイルにはそれ以上ハンクが適用されません。その塊を無視して、パッチの残りを適用し続けてほしい。.rejファイルを生成するのは、ハンクを適用できず、既に適用されていないように見える場合だけです。

これを行う方法はありますか?

回答:


7

これにはpatchutilsをインストールする必要があります。

このスクリプトは、1つの大きなパッチを小さな個別のパッチに分割し、各パッチには1つのファイルに対して1つのハンクのみが含まれます。次に、これらのパッチをで適用できます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

編集:スクリプトをhunks.shに保存し、呼び出します:

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

2

最終的には、artyomのようなソリューションを使用してこれを解決しました。

手順1:ハンクごとに1つずつ、多数の個別のパッチにパッチを展開します。

このためにこのスクリプトを使用しました。

#!/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()

使用例:

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

これにより、現在のディレクトリに0.diff 1.diffなどと呼ばれるファイルが追加されます。

手順2:各パッチを適用し、既に適用されているパッチを破棄します。

このためにこのスクリプトを使用しました。

#!/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

使用例:

$ cd directory_containing_code
$ apply_patches.bash directory_containing_patch/foo

これにより、以前に生成されたパッチのうち、きれいに適用されるもの、またはすでに適用されているものがすべて削除されます。残ってfooいるパッチはすべて拒否され、手動で調査してマージする必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.