¿Cómo generar un parche git para una confirmación específica?

1233

Necesito escribir un script que cree parches para una lista de números de confirmación SHA1.

Intenté usar git format-patch <the SHA1>, pero eso generó un parche para cada confirmación desde ese SHA1. Después de generar unos cientos de parches, tuve que matar el proceso.

¿Hay alguna manera de generar un parche solo para el SHA1 específico?

elle
fuente

Respuestas:

1991

Tratar:

git format-patch -1 <sha>

o

git format-patch -1 HEAD

De acuerdo con el enlace de documentación anterior, la -1bandera le dice a git cuántas confirmaciones deben incluirse en el parche;

- <n>

     Prepare parches a partir de los commits superiores.


Aplica el parche con el comando:

git am < file.patch
manojlds
fuente
211
Aplicando el parche: git apply --stat file.patch# mostrar estadísticas. git apply --check file.patch# verifique el error antes de aplicar. git am < file.patch# aplicar el parche finalmente.
Adrian
3
No parece funcionar si la última confirmación es una fusión de otra rama.
Lex Li
2
Para aplicar el parche en archivos usando terminaciones de línea CRLF:git am --keep-cr < mypatch.patch
Michael Schmeißer
40
Use git am -3 < file.patchpara aplicar usando una combinación de tres vías que le permitirá resolver conflictos usando git mergetooldespués (o editando manualmente) que se encuentran aquí .
Matt
66
Este comando también funciona solo para un archivo (s) específico del commit: git format-patch -1 <sha> path/to/file.jsEsto creará un parche que solo contenga los diffs para el archivo .js
Kristóf Dombi
281

Para generar los parches desde los commits superiores desde un hash sha1 específico:

git format-patch -<n> <SHA1>

Los últimos 10 parches de la cabeza en un solo archivo de parche:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch
Sriram Murali
fuente
2
¿puede ser tan amable de proporcionar un ejemplo para el primer comando
Kasun Siyambalapitiya
1
git format-patch -1 HEADgenerará parche para la confirmación más reciente
Sriram Murali
1
discúlpeme por preguntar esto, así que cuando -2genera parches para los 2 commits más recientes es, y una cosa más para aclarar es que el comando got format-patch -2 HEADes el mismo que la líneagit format-patch HEAD~2
Kasun Siyambalapitiya
85

Digamos que tiene commit id 2 después de commit 1 que podría ejecutar:

git diff 2 1 > mypatch.diff

donde 2 y 1 son hash SHA.

Brandon
fuente
Gracias dookehster por la respuesta. Eso significa que necesito el script para encontrar los commits que precedieron a los que me interesan. Esperaba poder evitar eso.
elle
11
@elle, no, no lo haces - git diff hash^ hash. el "hash ^" da el commit precedido. (pero, por supuesto, la respuesta de manojlds es mejor)
J-16 SDiZ
2
git show HEAD > mypatch.diffmientras estás en el commit debería hacer lo mismo.
andho
1
@dookehester es correcto o es al revés,git diff 1 2
Kasun Siyambalapitiya
1
Esto no podrá incluir ningún archivo binario en el diff.
stuckj
55

Este comando (como ya sugirió @ Naftuli Tzvi Kay ):

git format-patch -1 HEAD

Reemplace HEADcon hash o rango específico.

generará el archivo de parche para la última confirmación formateada para parecerse al formato de buzón UNIX.

-<n> - Prepare parches a partir de los commits superiores.

Luego, puede volver a aplicar el archivo de parche en un formato de buzón:

git am -3k 001*.patch

Ver: man git-format-patch.

kenorb
fuente
¡Gracias! Creo que vale la pena señalar que la aplicación del parche creará una confirmación con un mensaje de confirmación con el prefijo [PATCH]. Sin embargo
Mike S
2
Fenomenal. OP, no has aceptado esto, porque ...? @MikeS No, no lo hace, más que cualquier otro gitparche con formato, al menos si el usuario lo aplica de la manera correcta.
underscore_d
2
@MikeS Realmente no investigé por qué, pero omitiendo la -kbandera ( git am -3) me arregló este formulario (sin PATCH[0/10]mensajes de confirmación). Git versión 2.20.1.windows.1
Jannis
31
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

Solución rápida y simple.

zdrsoft
fuente
55
Además, no olvide llamar git apply --check patch-file-nameantes de aplicar un parche. Esto ayudará a evitar problemas.
iamantony
16

Si desea asegurarse de que el parche (confirmación única) se aplicará sobre una confirmación específica, puede usar la nueva opción git 2.9 (junio de 2016) git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

Ver commit bb52995 , commit 3de6651 , commit fa2ab86 , commit ded2c09 (26 de abril de 2016) por Xiaolong Ye (``) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 72ce3ff , 23 de mayo de 2016)

format-patch: agregar ' --base' opción para registrar la información del árbol base

Los encargados del mantenimiento o los evaluadores externos pueden querer saber el árbol base exacto al que se aplica la serie de parches. Enseñe a git format-patch una --baseopción ' ' para registrar la información del árbol base y agregarla al final del primer mensaje (ya sea la carta de presentación o el primer parche de la serie).

La información del árbol base consiste en el "compromiso base", que es un compromiso conocido que forma parte de la parte estable del historial del proyecto en el que todos los demás trabajan, y cero o más "parches de requisitos previos", que son conocidos parches en vuelo que aún no forman parte del "compromiso base" que deben aplicarse sobre el "compromiso base" en orden topológico antes de que los parches puedan aplicarse.

El "compromiso base" se muestra como " base-commit:" seguido del 40 hex del nombre del objeto de compromiso.
Un "parche de prerrequisito" se muestra como " prerequisite-patch-id:" seguido por el "id de parche" de 40 hex, que se puede obtener pasando el parche a través del git patch-id --stablecomando " ".


Git 2.23 (Q3 2019) mejorará eso, porque la " --base" opción de " format-patch" calculó los patch-idsparches de requisitos previos de una manera inestable, que se ha actualizado para calcular de una manera que sea compatible con " git patch-id --stable".

Ver commit a8f6855 , commit 6f93d26 (26 abr 2019) por Stephen Boyd ( akshayka) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 8202d12 , 13 jun 2019)

format-patch: hacer --base patch-idestable la salida

No estábamos limpiando el contexto cada vez que procesábamos un fragmento en el patch-idcódigo de generación diff.c, pero lo estábamos haciendo cuando generamos ID de parche "estables" con la patch-idherramienta ' '.

Transmitamos esa lógica similar de patch-id.cadentro a adentro diff.cpara que podamos obtener el mismo hash cuando generamos ID de parche para ' format-patch --base=' tipos de invocaciones de comandos.


Antes de Git 2.24 (Q4 2019), " git format-patch -o <outdir>" hizo un equivalente de " mkdir <outdir>" no " mkdir -p <outdir>", que se está corrigiendo.

Ver commit edefc31 (11 oct 2019) por Bert Wesarg ( bertwesarg) .
(Fusionada por Junio ​​C Hamano - gitster- en commit f1afbb0 , 18 oct 2019)

format-patch: crea componentes principales del directorio de salida

Firmado por: Bert Wesarg

'git format-patch -o' hizo un equivalente de 'mkdir' no 'mkdir -p', que se está corrigiendo.

Evite el uso de ' adjust_shared_perm' en los directorios principales que pueden tener implicaciones de seguridad. Logrado al desactivar temporalmente config.sharedRepository"me gusta" git init.


Con Git 2.25 (Q1 2020), " git rebase" no funcionó bien cuando se format.useAutoBaseconfiguró la variable de configuración, que se ha corregido.

Ver commit cae0bc0 , commit 945dc55 , commit 700e006 , commit a749d01 , commit 0c47e06 (04 dic 2019) por Denton Liu ( Denton-L) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 71a7de7 , 16 dic 2019)

rebase: arreglar format.useAutoBaserotura

Reportado por: Christian Biesinger
Firmado por: Denton Liu

Con la format.useAutoBase = trueejecución de rebase se produjo un error:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

Solucione esto pasando siempre --no-basea format-patch desde rebase para que se niegue el efecto de format.useAutoBase.

VonC
fuente
8

Para generar la ruta desde una confirmación específica (no la última confirmación):

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE
Makah
fuente
5

si solo desea diff el archivo especificado, puede:

git diff master 766eceb - conexiones /> 000-mysql-connector.patch

jiahut
fuente
0

Con mi fondo mercurial iba a usar:

git log --patch -1 $ID > $file

Pero estoy considerando usar git format-patch -1 $IDahora.

alls0rts
fuente
-5

¿Cuál es la forma de generar un parche solo para el SHA1 específico?

Es bastante simple:

Opción 1. git show commitID > myFile.patch

Opcion 2. git commitID~1..commitID > myFile.patch

Nota: Reemplace commitIDcon la identificación de confirmación real (código de confirmación SHA1).

Ankush
fuente
3
La opción 1 es francamente incorrecta y no está relacionada con la pregunta.
Anshuman Manral
3
La opción 2 también es un comando no válido. Se obtendrá como: git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 ~ 1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git: 'a5f4bcaeb7fa7defcfcfcfcfcfcfcfcfgfcfcfcfcfcfcfcfcfcfcpx Ver 'git --help'. Por favor, compruebe antes de publicar respuestas
Anshuman Manral