2009-04-07 8 views
158

He estado usando Git durante aproximadamente un año y creo que es fantástico, pero acabo de comenzar una segunda versión del proyecto y comencé una nueva rama para él. Estoy luchando un poco con la mejor manera de manejar las cosas en el futuro.git - omitiendo confirmaciones específicas al fusionar

Tengo dos ramas llamadas say master10 (para v1) y master20 (para v2). He estado haciendo correcciones de errores en v1 en branch master10, y desarrollando nuevas cosas de master20. Cada vez que hago una corrección de errores la fusiono en v2 revisando master20 y haciendo git merge master10. Hasta aquí todo bien.

Ahora, sin embargo, he realizado un cambio en v1 que no quiero en v2, pero quiero continuar fusionando otras correcciones de errores. ¿Cómo le digo a Git que omita esa confirmación en particular (o un rango de confirmaciones), pero que en el futuro sigo queriendo combinar otras correcciones de errores?

Pensé que git rebase podría ser lo que necesito, pero lea el documento y mi cabeza casi explotó.

Creo que lo que quiero es algo así como un comando "git sync" que le dice a git que dos ramas están ahora sincronizadas y en el futuro solo fusionará las confirmaciones de este punto de sincronización.

Cualquier ayuda apreciada.

Respuesta

234

Si desea fusionar la mayoría pero no todas las confirmaciones en la rama "maint" a "master", por ejemplo, puede hacerlo. Requiere algo de trabajo ---- como se mencionó anteriormente, el caso de uso habitual es fusionar todo de una rama --- pero a veces sucede que usted hizo un cambio a una versión de lanzamiento que no debería ser integrada de nuevo (tal vez ese código sido reemplazado en el maestro ya), entonces, ¿cómo lo representas? Aquí va ...

Supongamos que se han aplicado 5 cambios a maint, y uno de ellos (maint ~ 3) no debe fusionarse nuevamente en el máster, aunque todos los demás deberían estarlo. Usted hace esto en tres etapas: en realidad fusionar todo antes de eso, decirle a git que marque maint ~ 3 como fusionado incluso cuando no lo esté, y luego fusionar el resto. La magia es:

bash <master>$ git merge maint~4 
bash <master>$ git merge -s ours maint~3 
bash <master>$ git merge maint 

El primer comando fusiona todo antes de su maint problemático cometen en maestro. El mensaje de registro de fusión predeterminado explicará que está fusionando "rama 'maint' (parte inicial)".

El segundo comando combina el molesto comando ~ 3 commit, pero la opción "-s ours" le dice a git que use una "estrategia de fusión" especial que, de hecho, funciona simplemente manteniendo el árbol en el que se está fusionando e ignorando los compromisos que está fusionando por completo. Pero todavía hace una nueva fusión se compromete con HEAD y maint ~ 3 como los padres, por lo que el gráfico de revisión ahora dice que maint ~ 3 se fusionó. Así que, de hecho, probablemente también quieras usar la opción -m para 'git merge', para explicar que ese commit ~ 3 de maint está siendo ignorado.

El comando final simplemente combina el resto de maint (maint ~ 2..maint) en el maestro para que todos estén sincronizados de nuevo.

+0

Me pregunto, sin embargo, si eso no es un poco peligroso: ¿qué es el mástil ~ 3 no debe ser ignorado sino simplemente pospuesto? Con su solución, cualquier subsiguiente combinación de git no fusionaría el mástil ~ 3. – VonC

+1

Para el compromiso pospuesto, crearía una "sub-bifurcación", haré exactamente lo que describes (incluyendo git merge -s our maint ~ 3), luego fusionaré todo de la sub-bifurcación a la maestra. Creo que un futuro "git merge maint" combinaría esta vez "mast ~ 3" – VonC

+2

Creo que si necesita posponer la fusión de esa confirmación, no tiene más remedio que omitirla (combinar la suya) y luego aplicarla usando el comando cherry-pick. Una vez que el compromiso es alcanzable desde el maestro, no se puede fusionar de nuevo, evitar fusionar el mismo cambio dos veces es uno de los principales objetivos de git. – araqnid

0

Cree una tercera rama para los cambios que desee en master10 pero no en master20. Siempre considere master10 como su "maestro", la rama más estable de todas. La rama con la que todas las otras ramas quieren estar sincronizadas en todo momento.

+0

Supongo que podría funcionar, pero ya me he metido en este estado, y una tercera rama probablemente me confundiría aún más. :) –

15

Compromisos incluyen ascendencia. No puede fusionar una confirmación sin fusionar compromisos previos.

Puedes elegirlas, por supuesto. Ese es un flujo fino cuando tienes una rama que está en modo de mantenimiento.

+1

Gracias, cherry pick hará el trabajo. No es tan bueno como lo que esperaba pero servirá. –

26

En mi humilde opinión, lo más lógico que hacer, es a fusionar todo, y luego usar git revert (commit_you_dont_want) para eliminarlo.

Ejemplo:

git merge master 
git revert 12345678 

Si tiene varios "de ignorar" se compromete, o si desea editar Mensaje de Reversión:

git merge master 
git revert -n 123456 
git revert -n abcdef 
git commit -m "... Except commits 123456 and abcdef" 

Luego, su historia puede verse como:

| ... Except 123456 and abcdef 
|\ Merge branch 'master' into 'your_branch' 

Si tiene conflictos que sólo afecten a estos "de ignorar" commits, se pueden utilizar:

git merge master -X ours 

De modo que su versión persistirá sobre la otra. Incluso sin mensajes de error, aún puede "revertir" esos commits no deseados, ya que pueden tener otros cambios que no entraron en conflicto, y aún así no los quiere.

Si tiene conflictos envolving no sólo el "a-ignore" se compromete, se debe resolver de forma manual, y es probable que tenga que resolver de nuevo durante la reversión.

+1

Si luego desea fusionar esas confirmaciones revertidas en la rama en cuestión, ¿las ignorará Git? –

+0

@ AnriëtteMyburgh Puede revertir los compromisos de reversión para luego fusionarlos en algo que realmente no puede hacer tan fácilmente con la estrategia "fusionar-la nuestra". – ikdc

2

Una especie de un anuncio a mi project que básicamente envuelve el proceso descrito por @araqnid.

Es una especie de ayudante que introduce siguiente flujo GIT:

  • hay una notificación diaria/semanal en espera de fusiones de las ramas de mantenimiento en dev/rama principal
  • cheques mantenedor rama para el estado y lo decide/ella misma si se requieren todas las confirmaciones y si las bloquea o si le pide a los desarrolladores que se bloqueen. En la rama de mantenimiento final se fusiona en el upsteam.

Una cita de la página del proyecto:

Dependiendo del flujo de trabajo es posible tener mantenimiento o ramas específicas del cliente junto con la rama principal. Estas ramas también se llaman ramas LTS.

A menudo las correcciones caliente se instalan en las ramas donde el error se informó y luego la confirmación se fusionó de nuevo en la rama principal.

la práctica general es tener todas las ramas perfectamente sincronizados con el maestro, es decir, que desea ver un delta clara entre un rama principal y en particular de entender si el maestro contiene todas las características y correcciones de errores .

Sin embargo, a veces no desea confirmaciones particulares porque son específicas del cliente y no serán visibles para otros usuarios. O su rama principal divergieron de que mucho de lo que se requiere completamente diferente enfoque para solucionar el problema, o mejor aún, el problema no es más presentes allí.

También en el caso de la recogida selectiva desde el maestro en la rama de mantenimiento , la confirmación resultante se bloqueará en el maestro.

Cuestiones relacionadas