tag practices delete create crear best git cherry-pick git-cherry-pick

practices - git tag push



Número principal de línea principal cuando se confecciona la combinación de selección de cereza (2)

Supongamos que esta es mi historia git

Z / A -- C -- D / / B

Mi CABEZA está actualmente en Z Quiero elegir B y C Si mi entendimiento es correcto, debería hacer esto:

git cherry-pick B git cherry-pick C -m 1 git commit --allow-empty

Funcionó en mi caso porque C es un no-op (por lo tanto, la confirmación vacía después, necesitaba la confirmación por otras razones), pero me pregunto qué hará el parámetro después de -m . Aquí está lo que leí de los documentos :

-m número de padre

--número de padre en línea

Por lo general, no puede elegir una combinación porque no sabe qué lado de la combinación debe considerarse la línea principal. Esta opción especifica el número principal (a partir de 1) de la línea principal y permite a cherry-pick reproducir el cambio en relación con el principal especificado.

En mi caso, C tiene dos padres, pero ¿cómo puedo saber cuál es el 1 y el 2 y, lo que es más importante, cuándo importa cuando selecciono 1 o 2?


He subestimado la respuesta de Scott Weldon , que es correcta, pero solo quiero agregar un intento de arte ASCII que incluya la numeración de los padres. Dado un gráfico que se parece a esto:

B / / ...--A D--... / / C

podemos decir que el nodo D es una confirmación de fusión, pero no podemos saber si B o C es el primer padre de D Uno de los dos es necesariamente el primer padre, y el otro es el segundo. Entonces, si necesitamos saberlo, debemos etiquetar el dibujo, lo que requiere más espacio. Aquí hay uno de esos intentos.

B / /² ...--A D--... / /¹ C

Ahora vemos que, por alguna razón, 1 dibujé el gráfico "al revés": que cometer C es de hecho el primer padre de D , mientras que cometer B es el segundo padre.

Es posible crear combinaciones arbitrarias utilizando comandos de nivel inferior ("plomería"). En particular, git commit-tree solo toma todos los argumentos -p que quieras dar, en el orden en que los das, y realiza un nuevo commit con los commit dados como sus padres. Dale uno -p y hace un compromiso ordinario con un padre. No le dé argumentos -p y hace un root confirmado. Dale 155 argumentos distintos -p (todos deben resolverse, por supuesto, a las ID de confirmación válidas) y crea una confirmación de fusión masiva de pulpo.

El comando git merge , sin embargo, siempre realiza su nueva confirmación con el primer padre como el HEAD actual (de ahí la rama actual, si está en una rama). El segundo padre, para una combinación estándar de dos padres, proviene de .git/MERGE_HEAD , en el que git merge escribe el otro ID de confirmación. Si la combinación está en conflicto, o la confirmación final de la combinación se retrasa con --no-commit , este archivo MERGE_HEAD es, de hecho, el único lugar donde está disponible la ID de confirmación.

(Cuando git merge hace que un pulpo se fusione, usando la estrategia -s octopus (esta estrategia es forzada para tales combinaciones) y varios padres adicionales, se interrumpe y no deja rastro alguno si hay conflictos de fusión, por lo que el caso de conflicto nunca ocurre . No he intentado combinar --no-commit con una fusión de pulpo, pero eso, lógicamente, dejaría a los padres del segundo al noveno en MERGE_HEAD , si Git lo permite.

1 Obstinación.


Mi entendimiento, basado en esta respuesta, es que el padre 1 es la rama a la que se está fusionando y el padre 2 es la rama de la que se está fusionando. Entonces, en su caso, el padre 1 es A , y el padre 2 es B Ya que un cherry-pick realmente está aplicando el diff entre dos confirmaciones, usas -m 1 para aplicar solo los cambios de B (porque el diff entre A y C contiene los cambios de B ). En su caso, probablemente no importa, ya que no tiene confirmaciones entre A y C

Así que sí, -m 1 es lo que quieres, y eso es cierto incluso si hubiera confirmaciones adicionales entre A y C

Si quieres que la nueva historia se parezca un poco más a la historia original, hay otra forma de hacerlo:

git cherry-pick B git checkout Z git merge --no-ff --no-commit B git commit --author="Some Dev <[email protected]>" --date="<commit C author date>"

(Si es necesario, puede crear una nueva rama para B antes de elegir).

Esto conservará la información del autor, debe darle una historia que se parece a esto:

B'' / / Z -- C'' / A -- C -- D / / B