git diff excepto con cierta label

Necesito get una list de cambios de files entre 2 confirmaciones, pero excluyendo confirmaciones con una label determinada.

Actualmente estoy usando esta línea

git diff --oneline --diff-filter=AM FIRST_TAG HEAD -- SpecificFolder 

como solo necesito los nombres de los files agregados o modificados (dentro del directory SpecificFolder) entre FIRST_TAG y ahora

ahora, debo excluir commits labeldos como EXCLUDE_TAG / * en esta comparación. ¿Esto es compatible con git diff? o debería hacer varios pasos como

  1. Obtener identificadores de commit entre ambas tags
  2. para cada identificación de confirmación, obtenga los nombres de file dentro de SpecificFolder, si la confirmación no está labelda como EXCLUDE_TAG / *
  3. Agregue la list acumulada en el paso 2

Necesitarás tu process de varios pasos, o algo similar.

Descripción larga (no dudes en TL; DR)

"Excluir ciertos commits" es una frase que, en Git, especialmente en lo que se refiere a diffs, tiene poco sentido. Es como decir "Me gustaría estar allí, pero excluyendo mi arm izquierdo". 🙂

Fundamentalmente, el problema aquí es que:

  • una confirmación es una instantánea de algún tree fuente, y
  • git diff compara dos de esas instantáneas
    • o una instantánea y el tree de trabajo
    • o una instantánea y el índice
    • o el índice y el tree de trabajo

(con "el índice" y "el tree de trabajo" básicamente actuando como instantáneas temporales, frente a las confirmaciones, que son instantáneas permanentes e invariables).

Una vez que tenga el resultado de la comparación, puede networkingucirlo de varias maneras, como limitarlo con --diff-filter , imprimir solo los nombres de los files con --name-only (supongo que quería decir eso en lugar de --oneline aquí ), y / o solo mirando los cambios en SpecificFolder , pero siempre comenzamos con las dos instantáneas específicas.

Mientras tanto, un nombre de label simplemente especifica algún compromiso en una larga cadena de confirmaciones, por ejemplo:

  tag:v1.0 | v ...--o--o--o <-- master \ o--o--o <-- develop ^ | tag:v1.1-rc1 

Aquí, cada ronda o nodo representa una confirmación. La confirmación que es la confirmación más reciente, o sugerencia , en el master es la confirmación que se copy para la ejecución cuando se ejecuta el git checkout master . Esa misma confirmación (la misma instantánea) recibe el nombre de la label v1.0 , pero una vez que realiza una nueva confirmación en el master , la label permanece donde está, y el nombre de la twig avanza para acomodar la nueva confirmación:

  tag:v1.0 | v ...--o--o--o--o <-- master \ o--o--o <-- develop ^ | tag:v1.1-rc1 

Del mismo modo, la label v1.1-rc1 identifica un compromiso específico, actualmente uno se compromete "detrás" de la punta del develop .

Puede ejecutar git diff v1.0 v1.1-rc1 para comparar las dos confirmaciones labeldas específicas. Esto ignora completamente cualquier otro compromiso : simplemente extrae las dos instantáneas y las compara.

Dado que, en este caso, solo busca files agregados o modificados, tiene sentido ejecutar un compromiso a la vez:

  tag:EXCLUDE_TAG/2 | v o--o <-- feature / ...--o--A--*--o <-- master \ \ *--* \ / \ *--* *--*--* <-- develop (HEAD) \ / *--* ^ | tag:EXCLUDE_TAG/1 

Ahora puede ejecutar git rev-list --ancestry-path A..HEAD , donde A es un identificador que localiza el commit A , y el commit actual es el commit tip de branch develop , que es el branch actual. Esto imprimirá la identificación hash de cada confirmación con estrella (tenga en count que la propia identificación de A no se imprimirá).

Desde esta list, puede quitar el ID hash de exactamente una confirmación con estrella, ya que tiene un nombre EXCLUDE_TAG/1 . Puede usar git for-each-ref 'refs/tags/EXCLUDE_TAG/*' para localizarlos. (Pruébalo sin opciones, luego agrega directivas de --format para limitar su salida a lo que realmente quieres. Si tienes una combinación de tags anotadas y livianas, restring que es posible que tengas que "pelar" algunas de ellas para encontrar su objective commits. %(*objectname) hará eso para las tags anotadas, pero no produce salida para las tags livianas.) Tenga en count que algunas -como EXCLUDE_TAG/2 en este ejemplo-pueden no estar en la list original de hashes de confirmación.

Ahora tiene una list de todos los hashes de confirmación no excluidos. Por lo tanto, puede comparar cualquier compromiso con cualquier otro, como comparar cada compromiso con su padre inmediato, para ver qué cambió en ese compromiso. Pero hay una falla en esta estrategia: ¿qué vas a hacer con los commit de fusión ? En el diagtwig de arriba, hay una combinación de fusión, tres pasos detrás de la punta de develop . Puede diferir de uno o ambos de sus compromisos primarios; de hecho, si se trata de una fusión maligna , contendrá cambios que no están en ninguno de los padres (esta es la definición de una fusión maligna : ¿ve el mal se funde en git? ). Debe decidir por sí mismo qué hacer para dichos casos.