Cree un parche git a partir de los cambios en el directorio de trabajo actual

880

Digamos que tengo cambios no confirmados en mi directorio de trabajo. ¿Cómo puedo hacer un parche de esos sin tener que crear una confirmación?

vrish88
fuente
29
La respuesta aceptada probablemente debería cambiarse, dado que la segunda respuesta es casi cuatro veces más popular.
Tim Ogilvy
55
@TimOgilvy estuvo de acuerdo. OP debería hacerlo. La segunda respuesta es mucho más popular y brinda más información
John Demetriou
1
Creo que vale la pena mencionar que necesitas un parche de cambios no confirmados en el título.
2i3r

Respuestas:

401

git diffpara cambios no organizados. git diff --cachedpara cambios por etapas.

sigjuice
fuente
12
sí, git diff es el inverso de git apply
Spike Gronim
33
git format-patchTambién incluye diferencias binarias y alguna metainformación. En realidad, esa sería la mejor apuesta para crear un parche, pero afaik esto solo funciona para fuentes / cambios verificados, ¿verdad?
Eric
20
A veces puede ser útil crear un parche relativo al directorio actual. Para lograr esto, usegit diff --relative
ejboy
30
git diff> a.patch para escribirlo en un archivo
qasimzee
139
En pocas palabras, sarcástico, la respuesta a continuación es más útil.
Aire
1865

Si aún no ha confirmado los cambios, entonces:

git diff > mypatch.patch

Pero a veces sucede que parte de las cosas que está haciendo son archivos nuevos que no se rastrean y no estarán en su git diffsalida. Entonces, una forma de hacer un parche es organizar todo para una nueva confirmación ( git addcada archivo, o simplemente git add .) pero no hacer la confirmación, y luego:

git diff --cached > mypatch.patch

Agregue la opción 'binario' si desea agregar archivos binarios al parche (por ejemplo, archivos mp3):

git diff --cached --binary > mypatch.patch

Luego puede aplicar el parche:

git apply mypatch.patch

Nota: También puede usar --stagedcomo sinónimo de --cached.

jcarballo
fuente
128
Muchas gracias por el ejemplo. A diferencia de la respuesta aceptada, muestra a los comandos cómo hacerlo y no solo habla. Muy útil y funcionó a la perfección para mí :)
nuala
44
Hice exactamente eso y obtuve "fatal: entrada no reconocida" al ejecutar git apply. ¿Alguna idea de qué puede causar esto y cómo solucionarlo?
Vitaly
66
@Vitaly: ¿tu parche es legible si lo abres con un editor de texto? debe estar limpio sin caracteres extraños, por ejemplo, si la configuración de color.diff está configurada, su parche tendrá algunos 'caracteres de color' que pueden hacer que 'git apply' falle, en ese caso, intente git diff --no-color. De lo contrario, parece un problema de codificación.
jcarballo
3
Relacionado con "nuevos archivos sin seguimiento": "git diff" y "git diff --cached" solo funcionan si se ha llamado primero a "git add <file>". (Soy nuevo en Git y me pregunto por qué siempre tengo un parche vacío)
Anónimo
55
Esto me sacó de un extraño infierno de fusión / rebase bastante fácilmente, gracias :)
John Hunt
86

git diffy git applyfuncionará para archivos de texto, pero no funcionará para archivos binarios.

Puede crear fácilmente un parche binario completo, pero tendrá que crear una confirmación temporal. Una vez que haya realizado sus confirmaciones temporales, puede crear el parche con:

git format-patch <options...>

Después de haber realizado el parche, ejecute este comando:

git reset --mixed <SHA of commit *before* your working-changes commit(s)>

Esto revertirá su (s) confirmación (es) temporal (es). El resultado final deja su copia de trabajo (intencionalmente) sucia con los mismos cambios que tuvo originalmente.

En el lado receptor, puede usar el mismo truco para aplicar los cambios a la copia de trabajo, sin tener el historial de confirmación. Simplemente aplique los parches y git reset --mixed <SHA of commit *before* the patches>.

Tenga en cuenta que es posible que tenga que estar bien sincronizado para que esta opción funcione. He visto algunos errores al aplicar parches cuando la persona que los hizo no había realizado tantos cambios como yo. Probablemente hay maneras de hacer que funcione, pero no lo he investigado demasiado.


Aquí se explica cómo crear los mismos parches en Tortoise Git (no es que recomiendo usar esa herramienta):

  1. Compromete tus cambios de trabajo
  2. Haga clic derecho en el directorio raíz de la rama y haga clic en Tortoise Git->Create Patch Serial
    1. Elija el rango que tenga sentido ( Since: FETCH_HEADfuncionará si está bien sincronizado)
    2. Crea el parche
  3. Haga clic derecho en el directorio raíz de la rama y haga clic en Tortise Git->Show Log
  4. Haga clic derecho en la confirmación antes de su (s) confirmación (es) temporal (es) y haga clic enreset "<branch>" to this...
  5. Seleccione la Mixedopcion

Y cómo aplicarlos:

  1. Haga clic derecho en el directorio raíz de la rama y haga clic en Tortoise Git->Apply Patch Serial
  2. Seleccione los parches correctos y aplíquelos
  3. Haga clic derecho en el directorio raíz de la rama y haga clic en Tortise Git->Show Log
  4. Haga clic derecho en el commit antes del commit (s) del parche y haga clic enreset "<branch>" to this...
  5. Seleccione la Mixedopcion
Merlyn Morgan-Graham
fuente
55
Técnicamente, esto requiere crear una confirmación que OP pidió evitar, pero es temporal y la respuesta es útil independientemente.
davenpcj
33

Para crear un parche con archivos modificados y nuevos (por etapas), puede ejecutar:

git diff HEAD > file_name.patch
Ionel Sirbu
fuente
Gracias, en mi caso, esta respuesta funciona, pero git diff --cached > mypatch.patchno funciona.
minería
Tengo una pregunta: ¿puede file_name.patchser utilizada por el patchcomando? ¿Son compatibles entre sí?
Rakshith Ravi
git diff + git diff --cached / staged == git diff HEAD (muestra todos los cambios desde la última confirmación)
K. Símbolo
20

Me gusta:

git format-patch HEAD~<N>

donde <N>es el número de últimas confirmaciones para guardar como parches.

Los detalles sobre cómo usar el comando están en el DOC

UPD
Aquí puede encontrar cómo aplicarlos luego.

UPD Para aquellos que no tuvieron la idea de format-patch
Agregar alias:

git config --global alias.make-patch '!bash -c "cd ${GIT_PREFIX};git add .;git commit -m ''uncommited''; git format-patch HEAD~1; git reset HEAD~1"'

Luego, en cualquier directorio de su repositorio de proyectos, ejecute:

git make-patch

Este comando creará 0001-uncommited.patchen su directorio actual. El parche contendrá todos los cambios y archivos no rastreados que son visibles para el siguiente comando:

git status .
Eugen Konkov
fuente
@jcarballo: He actualizado la respuesta. No dude en enviarme cualquier aviso que tenga.
Eugen Konkov
2
Hay una manera más simple que crear un commit y unmitmiting. git diff --cached --binary
Gaurav Agarwal
9

Si quieres hacer binarios, da una --binaryopción cuando corras git diff.

gitter
fuente
0

También podríamos especificar los archivos, para incluir solo los archivos con cambios relativos, particularmente cuando abarcan múltiples directorios ex

git diff ~/path1/file1.ext ~/path2/file2.ext...fileN.ext > ~/whatever_path/whatever_name.patch

Descubrí que esto no se especifica en las respuestas o comentarios, que son todos relevantes y correctos, así que decidí agregarlo. ¡Explícito es mejor que implícito!

Anshu Kumar
fuente