К каким файлам `patch -p1` применяет патч в этом примере?

К каким файлам `patch -p1` применяет патч в этом примере?

Для отмены изменений в файле в коммите, изhttps://stackoverflow.com/a/2620822/156458

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

К каким файлам patch -p1применяется файл исправления (т.е. вывод git diff $sha1..$sha1^ -- $file)?

Применимо ли это ко всем файлам в рабочем каталоге?

Но рабочий каталог может не совпадать с коммитом $sha1. Так имеет ли смысл применять разницу между $sha1^и $sha1к рабочему каталогу, который может совпадать или не совпадать с $sha1?

Спасибо.

решение1

git diff $sha1..$sha1^создает патч, который отменяет $sha1коммит (он перечисляет различия между этим коммитом и его родителем). Если $fileуказано, он ограничивает этот патч изменениями, внесенными $fileв указанный коммит.

Затем этот патч передается в patch -p1, который удаляет поддельные имена каталогов, используемые git( a/и b/), и пытается применить патч к любым файлам, перечисленным в патче (то есть, $fileесли он был назван и изменен в данном коммите, или все файлы, измененные в данном коммите, включая файлы в подкаталогах). Если файлы, присутствующие в текущем каталоге и его подкаталогах, существенно отличаются (или, соответственно, отсутствуют), то patchприменить патч не удастся.

Это стало возможным благодаря тому, что патчи в унифицированном формате, как это сделано git diffdiff -u), включают имена файлов, которые подвергаются исправлению, и контекст для исправления. Вот пример (не из git, но он показывает идею):

diff -ur cli-common-0.9+nmu1.orig/policy-remove cli-common-0.9+nmu1/policy-remove
--- cli-common-0.9+nmu1.orig/policy-remove  2015-02-25 21:34:08.000000000 +0100
+++ cli-common-0.9+nmu1/policy-remove   2017-04-08 20:47:09.029065259 +0200
@@ -11,4 +11,4 @@

 #echo "Removing GAC policy file ($POLICY) from available GACs"
 /usr/share/cli-common/gac-package-remove $POLICY > /dev/null
-rm /usr/share/cli-common/packages.d/$POLICY.installcligac
+rm -f /usr/share/cli-common/packages.d/$POLICY.installcligac

Этот патч говорит, что он изменяет файл с именем cli-common-0.9+nmu1.orig/policy-removeдля создания файла с именем cli-common-0.9+nmu1/policy-remove. Само изменение начинается со строки 11 и охватывает 4 строки, включая контекст (это @@ -11,4); в цели измененные строки находятся в том же положении ( +11,4 @@). Над изменением идут три строки контекста, затем само изменение, удаление строки, начинающейся с , rmи добавление строки, начинающейся с rm -f. При patchприменении этого он будет искать файл с соответствующим именем (после удаления компонентов пути, если указано с помощью -pпараметра), и сравнивать контекст в файле с патчем; только если контекст совпадает (в пределах нескольких строк, в зависимости от параметров fuzz), изменение будет применено.

Весь смысл этого скрипта в том, чтобы попытаться отменить изменения, внесенные в один файл в данном коммите (отсюда и его название). Возможно это или нет, зависит от изменений, внесенных в файл после этого коммита; но на практике это часто бывает весьма полезно. (Чтобы отменить полный коммит, вы бы использовали git revertвместо этого.)

Связанный контент