git: aplica los cambios introducidos por la confirmación en un repositorio a otro repositorio


115

Tengo un repo1y repo2en una máquina local. Son muy similares, pero esta última es algún tipo de otra rama ( repo1ya no se mantiene).

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

¿Cómo aplicar los cambios realizados por commit <some_sha>in repo1a repo2?

¿Necesito preparar algún parche o es posible hacerlo cherry-pickentre los repositorios?

¿Qué tal hacer lo mismo pero para un rango de confirmaciones?


2
¿No puedes simplemente pasar de repo1 a repo2?
zwol

para el caso un poco más específico en el que está buscando aplicar cambios a un archivo o archivos que se movieron en uno de los repositorios, mire aquí: stackoverflow.com/questions/3491270/…
Braham Snyder

Respuestas:


31

Como truco, puede intentar modificar la receta para comparar confirmaciones en dos repositorios diferentes en la página de GitTips , es decir:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

donde ../repoes la ruta al otro repositorio.

Con Git moderno, puede usar múltiples revisiones y rangos de revisión con selección de cerebros .

El $(git --git-dir=../repo/.git rev-parse --verify <commit>) está aquí para traducir <commit>(por ejemplo HEAD, o v0.2, o master~2, que son valores en el segundo depósito de la copia se realiza) en SHA-1 identificador de comprometerse. Si conoce SHA-1 de un cambio que desea elegir, no es necesario.

TENGA EN CUENTA, sin embargo, que Git puede omitir la copia de objetos del repositorio de origen, ya que no sabe que el repositorio de objetos alternativo es solo temporal, para una operación. Es posible que deba copiar objetos del segundo repositorio con:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

Esto coloca esos objetos prestados del segundo repositorio en el almacenamiento del repositorio original

No probado.


Una solución no tan hacky es seguir la respuesta de knittl :

  • Vaya al segundo repositorio desde el que desea copiar las confirmaciones y genere parches a partir de las confirmaciones que desee con git format-patch
  • Opcionalmente, copie los parches (0001- * etc.) a su repositorio
  • Úselo git am --3waypara aplicar parches

1
Funciona bien. Si tiene problemas con la confirmación, haga 'git reset HEAD; git add. '.
gumik

5
esto es increíble, ¿cómo harías una serie de confirmaciones? solo sha1 ... sha2?
hvgotcodes

También obtengo, fatal: unable to read tree ...pero después de que git reset HEAD^todo funciona bien
jmarceli

@hvgotcodes funcionó para mí simplemente pasando el rango como, <commit>pero al rev-parse --verifycomando no le gusta, ya que solo acepta valores de confirmación únicos. Pero como cherry-pickacepta valores de compromiso únicos y de rango, pregunto: ¿por qué se rev-parsenecesita?
Chuim

1
@Chuim: git rev-parsees necesario si se desea hacer referencia a un compromiso por su nombre a base de referencia en otro depósito, por ejemplo master, HEAD^^o algo por el estilo; rev-parse lo convierte en un identificador universal SHA-1.
Jakub Narębski

207

Probablemente desee utilizar git format-patchy luego git amaplicar ese parche a su repositorio.

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

O, en una línea:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3

9
Esta solución resultó ser más simple y segura que la respuesta aceptada del uso directo de selección selectiva GIT_ALTERNATE_OBJECT_DIRECTORIES(que corrompería mi repositorio).
Chuim

2
Cuando hay conflictos, no funcionará porque no encuentra las confirmaciones en la otra rama.
Roger Far

2
Agregar --ignore-whitespaceal git amcomando puede resolver cualquier conflicto y evitar la necesidad de realizar una combinación de 3 vías
Hugheth

97

Puede hacerlo cherry-picksi agrega el segundo repositorio como remoto al primero (y luego fetch).


11
En realidad, esa es la forma correcta de hacerlo.
Wilbert

5
Este también me parece el camino correcto. Y simplemente lo usé y funcionó bien para mí.
Ricky Nelson

11
Prefiero decir: hazlo git fetch [remote-name]en el segundo repositorio y luego git cherry-pick [sha1].

5
Este enfoque funcionó muy bien para mí, gracias. Dado que el segundo repositorio también era local, solo tenía que usar un URI de archivo al agregarlo como remoto.
palimpsesto

2
En mi caso, tengo dos clones de un gigantesco repositorio remoto de git (para permitir el trabajo en paralelo), lo que significa que todo su historial ya está descargado y almacenado dos veces en mi HD. Si también tuviera que agregar cada uno como un control remoto del otro, eso crearía dos copias adicionales del mismo historial y potencialmente requeriría sincronizaciones entre ellas antes de poder hacerlo cherry-pick. Entonces, aunque pueda parecer la forma "correcta", no siempre es la más práctica.
Chuim

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.