Cómo seleccionar solo los cambios para un solo archivo, no para toda la confirmación

108

Necesito aplicar los cambios introducidos en una rama a otra rama. Puedo usar una selección de cerezas para hacer eso. Sin embargo, en mi caso, quiero aplicar cambios que son relevantes solo para un archivo, no necesito seleccionar la confirmación completa. ¿Como hacer eso?

como él
fuente

Respuestas:

137

Tienes diferentes opciones en función de lo que quieras conseguir:

Si desea que el contenido del archivo sea el mismo que en la rama de destino, puede usar git checkout <branch> -- <filename>. Sin embargo, esto no "seleccionará" los cambios que ocurrieron en una única confirmación, sino que simplemente tomará el estado resultante de dicho archivo. Entonces, si agregó una línea en una confirmación, pero las confirmaciones anteriores cambiaron más, y solo desea agregar esa línea sin esos otros cambios, entonces una verificación no es lo que desea.

De lo contrario, si desea aplicar el parche introducido en una confirmación a un solo archivo, tiene varias opciones. Puede ejecutar git cherry-pick -n, es decir, sin comprometerlo, editar el compromiso (por ejemplo, restablecer todos los archivos usando git reset -- .y solo agregar el archivo que realmente desea cambiar usando git add <filename>). O puede crear la diferencia para el archivo y aplicar la diferencia luego:

git diff <branch>^..<branch> -- <filename> | git apply
dar un toque
fuente
22

Crea un patch filey aplícalo.

git diff branchname -- filename > patchfile
git apply patchfile

EDITAR:

Como necesita tomar los cambios de una confirmación, cree el parche de esta manera:

git show sha1 -- filename > patchfile
Sailesh
fuente
1
git diff sha1(o git diff branch- es lo mismo si la rama apunta al mismo hash) solo producirá una diferencia del directorio de trabajo actual en relación con ese hash, pero no los cambios introducidos por una confirmación por sí sola.
empujar
Correcto. Editó la respuesta. Gracias.
Sailesh
1
-1 git checkoutcon un nombre de archivo es el martillo adecuado para este clavo. Ambas opciones son innecesariamente complejas.
Rein Henrichs
7
Para este caso en particular, sí. Pero en general, si desea seleccionar cambios de una confirmación realizada en un archivo en particular, entonces checkoutno funcionará, ya que puede involucrar otros cambios anteriores no deseados y puede que no contenga cambios realizados en la rama actual.
Sailesh
11

Otra cosa útil que puede hacer es obtener el parche localmente y luego usar:

git checkout {<name_of_branch>, commit's SHA} <path to the file> 

Sin embargo, eso no es una selección de cerezas.

0x90
fuente
2
Advertencia: como dice @poke en su respuesta, esto no copia los cambios; copia todo el estado del archivo. Entonces, si desea agregar los cambios de una confirmación al archivo, al verificar de esta manera, terminará sobrescribiendo los cambios más nuevos, lo cual no es bueno.
Alexander Bird
7

Git tiene todo listo :)

Solo usa git checkout <sha> <path-to-file>

Raghotham S
fuente
4
Eso no es una elección selectiva, eso verifica el archivo en su totalidad. El objetivo es realizar un cambio particular a partir de una confirmación. A menudo, esos son lo mismo, pero a veces no lo son.
AndrewF
6
git checkout the_branch_with_the_change the/path/to/the/file/you/want.extension

esto funciona si desea que un solo archivo de otra rama se copie a la rama de trabajo actual

Ismail Iqbal
fuente
1
Tenga cuidado, los cambios realizados en el archivo que no estén en la versión de la otra rama se perderán.
Patrick Schlüter
De acuerdo con eso. esto es útil si solo necesita una copia del archivo y desea modificarlo en la rama actual
Ismail Iqbal
1
Se pueden usar globs (ruta / *) y especificar más de una ruta / archivo
Todd
1

Esto es lo que buscas:

git checkout target-branch sha1 path/to/file

sha1 es opcional

Ruslan Osipov
fuente
11
no, "seleccionar cambios en la confirmación" no es "seleccionar el archivo completo"
Abyx
1

Lo que suelo hacer es usar git ls-tree

solo haz:

git ls-tree -r <commit-id> |grep 'your filename'
# there will be output that shows a SHA1 of your file
git show ${SHA1 of your file} > 'your filename'

Esto imprimirá todos los nombres de archivo que coincidan con su grep y le dará claves SHA1 de los archivos en la confirmación.

Git show también se puede usar en archivos fuera de su rama. usar >desde su shell para canalizar la salida a un archivo le da el resultado que está buscando.

Alex
fuente
0

Puedes intentar hacer esto:

git show COMMIT_ID -- path/to/specific-file | git apply

Por ejemplo:

git show 3feaf20 -- app/views/home/index.html | git apply
arashb31
fuente
-9
git reset HEAD~1

mueve los archivos a la etapa de confirmación previa

git stash

quita de la memoria

Ahora su rama está bastante limpia (volvió a la confirmación anterior)

Venkata
fuente