2009-05-19 20 views
80

Tengo las siguientes ramas:Tire todas las confirmaciones de una rama, empujar compromete especificados a otra

  • master
  • production

y las siguientes ramas remotas:

  • origin/master
  • origin/production

Tengo un script que recupera la rama origin/master y obtiene el diff de lo que ha cambiado desde mi último fetch (log -p master..origin/master). Luego me fusiono origin/master.

Las confirmaciones encontradas se envían a una herramienta de revisión de código.

Deseo enviar los commits exitosos - y solo ellos - a la rama de producción, y luego, por supuesto, al origin/production.

¿Cómo puedo hacer eso?

Además, tengo 2 scripts en ejecución: el que obtiene de origin/master, envía detalles a una base de datos y se fusiona, y el otro que estoy escribiendo que deberá enviar los commits correctos.

Me gustaría tener esos 2 scripts ejecutándose mientras se evitan las condiciones de carrera/conflicto de combinación. Como solo quiero trabajar con confirmaciones especificadas, ¿hay alguna manera de deshacerse de las confirmaciones que no quiero?

+0

¿Qué quiere decir con 'commits exitosos'? – bdonlan

+0

el que ha sido revisado y marcado como exitoso. realmente no importa aquí, lo importante es que hay compromisos que quiero mantener y enviar a otra rama, y ​​otros que quiero eliminar/ignorar. – Sylvain

Respuesta

259

El término que creo que está buscando es una "selección de cereza". Es decir, tomar una sola confirmación desde el medio de una de las ramas y agregarlo a otro:

A-----B------C 
\ 
    \ 
    D 

convierte

A-----B------C 
\ 
    \ 
    D-----C' 

Esto, por supuesto, se puede hacer con el comando git cherry-pick.

El problema con este cometa es que git considera compromete a incluir toda la historia delante de ellos - por lo tanto, si tiene tres confirmaciones de este modo:

A-----B-----C 

Y tratar de deshacerse de B, usted tiene que crear una confirmación completamente nueva como esta:

A-----------C' 

Donde C 'tiene una ID de SHA-1 diferente. Del mismo modo, seleccionar un compromiso de una rama a otra consiste básicamente en generar un parche y luego aplicarlo, perdiendo así también la historia.

Este cambio de identificaciones de compromiso rompe la funcionalidad de fusión de git entre otras cosas (aunque si se usa con moderación hay heurísticas que se imprimirán sobre esto). Sin embargo, lo más importante es que ignora las dependencias funcionales: si C realmente usó una función definida en B, nunca lo sabrá.

Quizás una mejor forma de manejar esto sería tener ramas de grano más fino.Es decir, en lugar de solo tener un 'maestro', tener 'featureA', 'bugfixB', etc. Realice una revisión de código en una rama completa a la vez, donde cada rama está muy enfocada en hacer una sola cosa, y luego fusione una rama cuando termines Este es el flujo de trabajo para el que está diseñado git, y en qué es bueno :)

Si insistes en tratar las cosas al nivel de los parches, es posible que desees ver los darcs: considera que un repositorio es un conjunto de parches, y por lo tanto, la selección de cereza se convierte en la operación fundamental. Sin embargo, esto tiene su propio conjunto de problemas, como ser muy lento :)

Editar: Además, no estoy seguro de entender su segunda pregunta, sobre los dos scripts. ¿Tal vez podrías describirlo con más detalle, posiblemente como una pregunta separada para evitar que las cosas se vuelvan confusas?

+0

Sobre mi segunda pregunta, solo quiero asegurarme de que los procesos de búsqueda de cambios (1er script) y empujar los commits acordados a otra ubicación (2º script) pueden funcionar sin tener condiciones de carrera/conflicto de fusión, mientras se trabaja con diferentes ramas. Pero al final supongo que no importa, ya que podría fusionar los 2 guiones en uno para que los 2 guiones no funcionen simultáneamente :) – Sylvain

+20

Buena descripción de las consecuencias de recoger cereza. +1 – VonC

+8

* "Este cambio de identificadores de commit rompe la funcionalidad de fusión de git entre otras cosas" * ** @ bdonlan explica por qué se frenó la funcionalidad de fusión. ¿Qué significa? ** – Narek

1

que dan cuenta de esto es una cuestión de edad, sino que se hace referencia aquí: How to merge a specific commit in Git

Por lo tanto, una respuesta más reciente: Use ramas de características y tire de solicitudes.

el aspecto que tiene, donde Fa es una confirmación con la característica A, y FB es una confirmación con la función B:

  fA fC (bad commit, don't merge) 
     /\/
master ----A----B----C 
       \/
       fB 

peticiones de tracción están asociados con la funcionalidad de GitHub, pero realmente todo lo que quiero decir es que alguien tiene la responsabilidad de fusionar las ramas de características en maestra.

Cuestiones relacionadas