![Para quais arquivos `patch -p1` aplica o patch neste exemplo?](https://rvso.com/image/109227/Para%20quais%20arquivos%20%60patch%20-p1%60%20aplica%20o%20patch%20neste%20exemplo%3F.png)
Para reverter as alterações em um arquivo em um commit, dehttps://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
A quais arquivos patch -p1
o arquivo de patch se aplica (ou seja, a saída de git diff $sha1..$sha1^ -- $file
)?
Isso se aplica a todos os arquivos no diretório de trabalho?
Mas o diretório de trabalho pode não ser igual ao commit $sha1
. Então, faz sentido aplicar a diferença entre $sha1^
e $sha1
ao diretório de trabalho, que pode ou não ser igual a $sha1
?
Obrigado.
Responder1
git diff $sha1..$sha1^
produz um patch que reverte o $sha1
commit (ele lista as diferenças entre esse commit e seu pai). Se $file
for especificado, limita esse patch às alterações feitas $file
no commit fornecido.
Esse patch é então enviado para patch -p1
, o que removerá os nomes de diretório falsos usados por git
( a/
e b/
) e tentará aplicar o patch a quaisquer arquivos listados no patch (ou seja, $file
se foi nomeado e alterado no commit determinado, ou todos os arquivos alterados no commit determinado, incluindo arquivos em subdiretórios). Se os arquivos presentes no diretório atual e seus subdiretórios forem substancialmente diferentes (ou, por extensão, ausentes), patch
não será possível aplicar o patch.
Isso é possível pelo fato de que os patches em formato unificado, produzidos por git diff
(e diff -u
), incluem os nomes dos arquivos que estão sendo corrigidos e o contexto do patch. Aqui está um exemplo (não de git
, mas mostra a ideia):
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
Este patch diz que está modificando o arquivo nomeado cli-common-0.9+nmu1.orig/policy-remove
para produzir o arquivo chamado cli-common-0.9+nmu1/policy-remove
. A mudança em si começa na linha 11 e cobre 4 linhas, incluindo contexto (esse é o @@ -11,4
); no alvo, as linhas alteradas ficam na mesma posição ( +11,4 @@
). Existem três linhas de contexto acima da alteração, depois a alteração em si, excluindo uma linha começando com rm
e adicionando uma linha começando com rm -f
. Quando patch
isso for aplicado, ele procurará o arquivo com nome apropriado (após remover os componentes do caminho, se instruído com uma -p
opção) e comparará o contexto no arquivo com o patch; somente se o contexto corresponder (dentro de algumas linhas, dependendo das opções de fuzz) a alteração será aplicada.
O objetivo deste script é tentar reverter as alterações feitas em um único arquivo no commit fornecido (daí seu nome). Se isso é possível ou não, depende das alterações feitas no arquivo desde o commit; mas muitas vezes é bastante útil na prática. (Para reverter um commit completo, você usaria git revert
.)