![Auf welche Dateien wendet `patch -p1` in diesem Beispiel den Patch an?](https://rvso.com/image/109227/Auf%20welche%20Dateien%20wendet%20%60patch%20-p1%60%20in%20diesem%20Beispiel%20den%20Patch%20an%3F.png)
Um die Änderungen an einer Datei in einem Commit rückgängig zu machen,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
Auf welche Dateien wird patch -p1
die Patchdatei angewendet (also die Ausgabe von git diff $sha1..$sha1^ -- $file
)?
Gilt es für alle Dateien im Arbeitsverzeichnis?
Das Arbeitsverzeichnis muss jedoch nicht mit dem Commit identisch sein $sha1
. Ist es also sinnvoll, den Unterschied zwischen $sha1^
und $sha1
auf das Arbeitsverzeichnis anzuwenden, das mit identisch sein kann oder nicht $sha1
?
Danke.
Antwort1
git diff $sha1..$sha1^
Erstellt einen Patch, der das $sha1
Commit rückgängig macht (er listet die Unterschiede zwischen diesem Commit und seinem übergeordneten Commit auf). Wenn angegeben ist, beschränkt es den Patch auf die im angegebenen Commit $file
vorgenommenen Änderungen .$file
Dieser Patch wird dann an weitergeleitet . Das Programm entfernt die von ( und ) patch -p1
verwendeten falschen Verzeichnisnamen und versucht, den Patch auf die im Patch aufgeführten Dateien anzuwenden (git
a/
b/
dh, $file
wenn es im angegebenen Commit benannt und geändert wurde, oder alle im angegebenen Commit geänderten Dateien, einschließlich der Dateien in den Unterverzeichnissen). Wenn die im aktuellen Verzeichnis und seinen Unterverzeichnissen vorhandenen Dateien wesentlich unterschiedlich sind (oder fehlen), patch
schlägt die Anwendung des Patches fehl.
Dies wird dadurch ermöglicht, dass Patches im einheitlichen Format, wie sie von git diff
(und diff -u
) erstellt werden, die Namen der gepatchten Dateien und den Kontext für den Patch enthalten. Hier ist ein Beispiel (nicht von git
, aber es zeigt die Idee):
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
Dieser Patch besagt, dass er die Datei mit dem Namen ändert, cli-common-0.9+nmu1.orig/policy-remove
um die Datei mit dem Namen zu erstellen cli-common-0.9+nmu1/policy-remove
. Die Änderung selbst beginnt in Zeile 11 und umfasst 4 Zeilen, einschließlich Kontext (das ist das @@ -11,4
); im Ziel befinden sich die geänderten Zeilen an derselben Position ( +11,4 @@
). Über der Änderung befinden sich drei Kontextzeilen, dann die Änderung selbst, wobei eine Zeile gelöscht wird, die mit beginnt, rm
und eine Zeile hinzugefügt wird, die mit beginnt rm -f
. Wenn patch
dies angewendet wird, wird nach der entsprechend benannten Datei gesucht (nachdem Pfadkomponenten entfernt wurden, wenn dies mit einer -p
Option angewiesen wurde) und der Kontext in der Datei mit dem Patch verglichen; nur wenn der Kontext übereinstimmt (innerhalb weniger Zeilen, abhängig von den Fuzz-Optionen), wird die Änderung angewendet.
Der Sinn dieses Skripts besteht darin, die an einer einzelnen Datei im angegebenen Commit vorgenommenen Änderungen rückgängig zu machen (daher der Name). Ob das möglich ist oder nicht, hängt von den Änderungen ab, die seit diesem Commit an der Datei vorgenommen wurden; in der Praxis ist es jedoch oft recht nützlich. (Um ein vollständiges Commit rückgängig zu machen, verwenden Sie git revert
stattdessen.)