tag remove practices crear best git version-control

remove - git tag best practices



Git: ¿Hay alguna manera de averiguar de dónde fue elegido un compromiso? (3)

No hay información sobre la confirmación original insertada en la confirmación recién creada, por lo que no hay forma directa de decirlo. Lo que sugieres (buscar el mensaje de confirmación) es probablemente la mejor manera: sin duda es mucho más fácil que buscar una confirmación con la misma diferencia:

git log --grep="<commit subject>" --all

A menos que, por supuesto, la confirmación ya no sea accesible desde una sucursal ... probablemente querría ver la salida de git fsck .

Si selecciono cuidadosamente desde múltiples ramas, ¿hay una forma simple de descubrir de dónde proviene el compromiso (por ejemplo, el sha de la confirmación original)?

Ejemplo:
- en la sucursal maestra
- cherry pick commit A de una rama dev
- A se convierte en D en la rama principal

Antes de:

* B (master) Feature Y | * C (dev) Feature Z | * A Feature X |/ * 3 * 2 * 1

Después:

* D (master) Feature X * B Feature Y | * C (dev) Feature Z | * A Feature X |/ * 3 * 2 * 1

¿Es posible descubrir que D fue escogido a mano por A (aparte de buscar el mensaje de confirmación)?

Editar:
Aunque iré con correcciones daggy (vea la respuesta de VonC), acepté la respuesta de Chris Johnsens porque está más cerca de la pregunta real. Gracias chicos.


Por defecto, la información sobre la confirmación original "cereza" no se registra como parte de la nueva confirmación.

Registre el Compromiso de origen en el mensaje de compromiso

Si puede forzar el uso de flujos de trabajo / opciones particulares, git cherry-pick tiene la opción -x :

Al grabar la confirmación, anexe al mensaje de confirmación original una nota que indique de qué compromiso se seleccionó este cambio.

Esto es obviamente inútil si no puede confiar en los recolectores de cerezas que usan la opción. Además, dado que la información grabada es solo texto, no una referencia real en lo que respecta a Git, incluso si usa -x , aún debe tomar medidas para asegurarse de que la confirmación original se mantenga viva (por ejemplo, si es parte del DAG de una etiqueta o una rama no rebobinadora).

git cherry y git patch-id

Si puede restringir su búsqueda a dos ramas particulares de la historia DAG, entonces git cherry puede encontrar cerezas "sin pintar" y "recogidas".

Nota : Este comando (y el id. De parche de git relacionado) solo pueden identificar cerezas libres de conflicto que se seleccionaron individualmente sin cambios adicionales. Si hubo un conflicto al elegir la cereza (por ejemplo, tuvo que modificarlo ligeramente para que se aplique), o utilizó -n / --no-commit para realizar cambios adicionales (por ejemplo, múltiples cerezas en una sola confirmación), o el contenido de la confirmación se reescribió después de la selección, luego tendrá que confiar en la comparación de mensajes de confirmación (o la información -x si fue registrada).

git cherry en realidad no está diseñado para identificar el origen de las cerezas recogidas, pero podemos abusar un poco para identificar pares de cerezas individuales.

Dada la siguiente historia DAG (como en el ejemplo del cartel original):

1---2---3---B---D master / A---C dev # D is a cherry-picked version of C

Verás algo como esto:

% git cherry master dev + A - C % git cherry dev master + B - D

(A, B, C y D son hashes SHA-1 completos en la salida real)

Como vemos una cereza (las líneas) en cada lista, deben formar un par de cerezas. D fue una cereza recogido de C (o viceversa, no se puede decir solo por el DAG, aunque las fechas de confirmación podrían ayudar).

Si está tratando con más de una cereza potencial, tendrá que "rodar su propio" programa para hacer la asignación. El código debería ser fácil en cualquier idioma con matrices asociativas, hashes, diccionarios o equivalentes. En awk , podría verse así:

match_cherries() { a="$(git rev-parse --verify "$1")" && b="$(git rev-parse --verify "$2")" && git rev-list "$a...$b" | xargs git show | git patch-id | awk '' { p[$1] = p[$1] " " $2 } END { for (i in p) { l=length(p[i]) if (l>41) print substr(p[i],2,l-1) } }'' } match_cherries master dev

Con un ejemplo extendido que tiene dos cerezas recogidas:

1---2---3---B---D---E master / A---C dev # D is a cherry-picked version of C # E is a cherry-picked version of A

El resultado puede verse así:

match_cherries master dev D C E A

(A, C, D y E son hashes SHA-1 completos en la salida real)

Esto nos dice que C y D representan el mismo cambio y que E y A representan el mismo cambio. Al igual que antes, no hay forma de saber cuál de cada par era "el primero", a menos que también considere (por ejemplo) las fechas de confirmación de cada confirmación.

Commitar la comparación de mensajes

Si tus cerezas no fueron recogidas con -x , o si están "sucias" (tuvieron conflictos u otros cambios agregados a ellas (es decir, con --no-commit más cambios adicionales de puesta en escena, o con git commit --amend u otra "historia") reescribiendo "mecanismo"), entonces puede que tenga que recurrir a la menos confiable técnica de comparación de mensajes de compromiso.

Esta técnica funciona mejor si puede encontrar algo del mensaje de confirmación que probablemente sea exclusivo de la confirmación y no sea probable que haya cambiado en la confirmación que resultó de la selección. El bit que funcionaría mejor dependería del estilo de los mensajes de confirmación utilizados en su proyecto.

Una vez que haya seleccionado una "parte de identificación" del mensaje, puede usar git log para encontrar compromisos (también se demuestra en la respuesta de Jefromi).

git log --grep=''unique part of the commit message'' dev...master

El argumento para --grep es en realidad una expresión regular, por lo que es posible que tenga que escapar de los metacaracteres regexp ( []*?./ ).

Si no está seguro de qué ramas pueden contener el compromiso original y el nuevo compromiso, puede usar --todo lo mostró Jefromi.


Si sigo su diagrama, desea saber si puede determinar que D (no B) es el resultado de una selección de cerezas A.

En teoría, como se ilustra en " ¿Cómo listar las ramas de git que contienen una confirmación dada? ", Puede buscar una confirmación, si D es realmente la misma confirmación (SHA1) que A:

git branch --contains <commit>

Pero como comenta Jefromi , D no puede tener el mismo SHA1 en este caso.
Eso deja la búsqueda de un mensaje de compromiso común: ver la respuesta de Jefromi .

Como menciona Ken Bloom en los comentarios de la pregunta, para una selección tan local, una técnica de daggy-fix (como en monotone.ca/wiki/DaggyFixes o mercurial ) es más apropiada, ya que dejará un rastro claro de la fusión.

Las correcciones de Daggy significan usar en lugar de perder el verdadero origen y la relación entre errores y soluciones en el gráfico de ascendencia.

Dado que [Git] ofrece la posibilidad de realizar una confirmación sobre cualquier revisión, generando así una pequeña rama anónima, una alternativa viable a la selección de cerezas es la siguiente:

  • use bisect para identificar la revisión donde surgió un error;
  • mira esa revisión;
  • arreglar el error;
  • y cometer la corrección como hijo de la revisión que introdujo el error.

Este nuevo cambio se puede fusionar fácilmente en cualquier sucursal que tenga el error original, sin que se requiera ningún tipo de travesura.
Utiliza una herramienta normal de control de revisiones y una máquina de resolución de conflictos, por lo que es mucho más confiable que la selección (la implementación de la cual es casi siempre una serie de ataques grotescos).

(aquí un diagrama de Mercurial, pero se aplica fácilmente a Git)

Hacer correcciones daggy todo el tiempo no es para todos.
No siempre es tan fácil desarrollar una solución directamente contra la revisión donde se introdujo el error.

  • Tal vez el error no se descubrió hasta que otro código más reciente lo usó de manera que expuso el error; sería difícil depurar y encontrar la solución sin este otro código.
  • O tal vez la importancia o alcance de la solución simplemente no se había realizado en ese momento.

Consulte también este artículo para obtener más información sobre daggy-fix :

Esta técnica de retroceder en la historia para corregir un error, y luego fusionar la solución en las ramas modernas, recibió el nombre de "correcciones daggy" por los autores de Monotone , un influyente sistema distribuido de control de revisiones.
Las soluciones se llaman daggy porque aprovechan el historial de un proyecto que está estructurado como un gráfico acíclico dirigido o dag .
Si bien este enfoque se puede utilizar con Subversion, sus ramas son pesadas en comparación con las herramientas distribuidas, por lo que el método daggy-fix es menos práctico. Esto subraya la idea de que las fortalezas de una herramienta informarán las técnicas que utilizan sus usuarios.