¿Cómo copio una versión de un solo archivo de una rama de git a otra?

944

Tengo dos ramas que están completamente fusionadas.

Sin embargo, después de que se realiza la fusión, me doy cuenta de que un archivo ha sido desordenado por la fusión (alguien más hizo un formateo automático, gah), y sería más fácil cambiar a la nueva versión en la otra rama, y luego vuelva a insertar mi cambio de una línea después de traerlo a mi rama.

Entonces, ¿cuál es la forma más fácil en git para hacer esto?

madlep
fuente
3
Tenga en cuenta que en la respuesta aceptada, la primera solución organiza los cambios, y la segunda solución no. stackoverflow.com/a/56045704/151841
user151841

Respuestas:

1675

Ejecute esto desde la rama donde desea que termine el archivo:

git checkout otherbranch myfile.txt

Fórmulas generales:

git checkout <commit_hash> <relative_path_to_file_or_dir>
git checkout <remote_name>/<branch_name> <file_or_dir>

Algunas notas (de comentarios):

  • Usando el hash de confirmación, puede extraer archivos de cualquier confirmación
  • Esto funciona para archivos y directorios.
  • sobrescribe el archivo myfile.txtymydir
  • Los comodines no funcionan, pero las rutas relativas sí
  • Se pueden especificar múltiples rutas

una alternativa:

git show commit_id:path/to/file > path/to/file
madlep
fuente
13
Sí lo haría. Pero esa era la intención de la pregunta.
Ikke
37
Probablemente obvio, pero necesita usar el nombre de archivo completo ... ¡Los comodines no funcionan!
Chris Hart
66
aunque ... también es una buena manera: git show commit_id: ruta / a / archivo> ruta / a / archivo
milushov
14
remoto: git checkout origin / otherbranch myfile.txt
Roman Rhrn Nesterov
66
El uso de comodines funciona, solo necesita envolverlos ''para que el shell no los interprete.
Wiktor Czajkowski
82

Terminé en esta pregunta en una búsqueda similar. En mi caso, estaba buscando extraer un archivo de otra rama en el directorio de trabajo actual que era diferente de la ubicación original del archivo. Respuesta :

git show TREEISH:path/to/file >path/to/local/file
lkraav
fuente
18
La intención de 'git show' es enviar datos al terminal en formato legible, lo que no garantiza que coincida exactamente con el contenido del archivo. Igual que es mejor copiar un documento de Word como un todo, y no intentar copiar y pegar su contenido en otro documento.
Gonen
Solo quería verlo para poder comparar el contenido con la rama actual (verifique algún fragmento de código). Sin embargo, me gustaría usar vim con esto ... para resaltar la sintaxis, etc.
isaaclw
3
Para comparar contenidos antes de realizar el pago, git diff <other branch> <path to file>funciona bien.
Randall
2
@Gonen: A partir de la versión 2.21.0 de git, la página del manual "git show" dice "Para los blobs simples, muestra el contenido simple". No estoy seguro de si esto significa que siempre somos buenos. Estoy un poco cuidadoso en busca de una imagen de esa manera ...
hibbelig
52

¿Qué pasa con el uso del comando de pago:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"
RzR
fuente
8
note merge (2nd command) no puede funcionar si el archivo no existe en ambas ramas
simpleuser
Hm. No tengo diffstat. ¿Es esa una versión específica de una herramienta diff, porque nunca he oído hablar de ella (y debería cambiarla?): D
dudewad
git diffadmite un --statargumento que básicamente hace lo mismo que diffstat.
hlovdal 01 de
Tuve que hacer que ambas sucursales fueran revisadas localmente para que esto funcionara.
UnitasBrooks
18

1) Asegúrese de estar en la sucursal donde necesita una copia del archivo. por ejemplo: quiero un archivo de sucursal secundaria en maestro, por lo que debe pagar o debe estar en maestrogit checkout master

2) Ahora compruebe solo el archivo específico que desee de la subrama en maestro,

git checkout sub_branch file_path/my_file.ext

aquí sub_branchsignifica dónde tiene ese archivo seguido del nombre de archivo que necesita copiar.

Mohideen bin Mohammed
fuente
Muy práctico y bien explicado.
Abk
15

Siguiendo la respuesta de madlep, también puede copiar un directorio de otra rama con el blob de directorio.

git checkout other-branch app/**

En cuanto a la pregunta del operador si solo ha cambiado un archivo allí, funcionará bien ^ _ ^

6 pies Dan
fuente
1
Tenga en cuenta que ambas ramas deben extraerse correctamente, primero, o usarse origin/other-branchpara referirse a la rama de repositorio. Lo básico, pero me mordió. (la respuesta es excelente, no requiere edición)
akauppi
8

Yo usaría git restore(disponible desde git 2.23)

git restore --source otherbranch path/to/myfile.txt


¿Por qué es mejor que otras opciones?

git checkout otherbranch -- path/to/myfile.txt- Copia el archivo en el directorio de trabajo pero también en el área de ensayo (efecto similar al de copiar este archivo manualmente y ejecutarlo git adden él). git restoreno toca el área de preparación (a menos que se lo indique por --stagedopción).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtusa redirección de shell estándar. Si usa Powershell, entonces podría haber un problema con la búsqueda de texto o podría obtener un archivo roto si es binario . Con el git restorecambio de archivos se hace todo porgit ejecutable.

Otra ventaja es que puede restaurar la carpeta completa con:

git restore --source otherbranch path/to

o con git restore --overlay --source otherbranch path/tosi desea evitar eliminar archivos. Por ejemplo, si hay menos archivos en el otherbranchdirectorio de trabajo actual (y estos archivos se rastrean ) sin --overlayopción git restore, los eliminará. Pero este es un buen comportamiento predeterminado, lo más probable es que desee que el estado del directorio sea el mismo otherbranch, no "el mismo pero con archivos adicionales en mi rama actual"

Mariusz Pawelski
fuente
Buena respuesta. ¿Hay alguna git restoremanera de copiar un archivo de la rama de origen a un nuevo archivo en la rama de destino? Con git show puedo hacer esto con la redirección de shell ( git show otherbranch:path/to/file1.txt > path/to/file2.txt), pero quiero evitar la redirección de shell por las razones que mencionaste.
AdmiralAdama
1
@AdmiralAdama no realmente. Y creo que no hay grandes posibilidades de obtenerlo git restore(pero quién sabe;)). Estos problemas de redirección son básicamente un problema de Powershell, no estoy seguro si hay algún otro shell que tenga problemas con él. Por lo general, vuelvo a "git bash" o incluso "cmd" donde necesito usar git showcomandos " con redirección". O use la GUI como GitExtensions donde puede explorar el árbol de archivos de commit y hacer clic en "Guardar como" en cualquier archivo.
Mariusz Pawelski
Ah, ya veo. No uso Powershell, así que quizás la redirección de shell sea np para mí. Gracias por la info.
AdmiralAdama
3

Tenga en cuenta que en la respuesta aceptada, la primera opción muestra todo el archivo desde la otra rama (comogit add ... se había realizado), y que la segunda opción tiene en cuanto a copiar el archivo, pero no organizar los cambios (como si tuviera solo edité el archivo manualmente y tenía diferencias notables).

Git copia el archivo de otra rama sin organizarlo

Cambios organizados (por ejemplo git add filename):

$ git checkout directory/somefile.php feature-B

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   directory/somefile.php

Cambios pendientes (no escenificados o comprometidos):

$ git show feature-B:directory/somefile.php > directory/somefile.php

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   directory/somefile.php

no changes added to commit (use "git add" and/or "git commit -a")
usuario151841
fuente
Obtengo "feature-B no es un archivo", el nombre de la rama es lo primero, sobre esto -> "> directorio / somefile.php" ¿esto puede cambiar la codificación del archivo?
Tiago Oliveira de Freitas