Los files cambiaron entre confirmaciones pero con la limitación de la list de files a la confirmación más antigua

Situación: Tengo un compromiso antiguo que necesito fusionar selectivamente con el último compromiso. Algunos files no tienen cambios y otros tienen cambios importantes que debo revisar y fusionar selectivamente.

Digamos que el antiguo commit 1 tenía files A , B , C

El último compromiso 5 ha implicado el cambio de los files B y C desde el compromiso 1 y también ha agregado los files D , E y F

Entonces, entre los commits 1 y 5 files B y C han cambiado, es decir, ejecutando diff en 1:B y 5:B ; y en 1:C y 5:C mostraría diferencias.

Necesito get los nombres B y C solamente .

Es decir, todos los files que no pertenecen a 1 pero que se cambiaron o agregaron hasta que 5 inclusive, NO deberían aparecer.

Puede intentar

 git diff --diff-filter=M 1 5 

Los filters disponibles son

  • A : agregado
  • C : copydo
  • D : eliminado
  • M : modificado
  • R : Renombrado
  • T : tipo cambiado (enlace simbólico, file regular, etc.)
  • U : Sin fusionar
  • X : Desconocido
  • B : emparejamiento roto

Consulte la página del manual de git-diff(1) para conocer todos los detalles.

Editar :

Si está interesado en qué cambió cómo entre dos confirmaciones, también puede usar la opción --name-status , que para cada file que cambió produce uno de los códigos anteriores. Esta opción también se puede usar con git-log indicándole qué tipo de cambio se hizo a qué files para cada una de las confirmaciones.

Para considerar solo los files que están presentes en la confirmación 1 , ejecute

 $ git ls-tree --name-only commit1 | xargs git diff commit1 commit5 -- 

Tenga en count que esto includeá los files que estuvieron presentes en la confirmación 1, pero que se eliminaron en la confirmación 5 (que aparecerá como files eliminados en la diferencia). Si desea evitar eso, busque el subset común de files:

 $ git ls-tree --name-only commit1 > all-files-in-commit1 $ git ls-tree --name-only commit5 > all-files-in-commit5 $ comm -1 -2 all-files-in-commit1 all-files-in-commit5 > common-files $ xargs git diff commit1 commit5 -- < common-files 

Suponiendo que, con su "último compromiso" 5 se refiera a HEAD , también podría usar esta estrategia diferente para su tarea. Descubrí que es la más viable hasta ahora:

  1. Aplique los cambios del compromiso anterior a su área de ensayo sin compromiso ( -n = --no-commit ):

     git cherry-pick -n <commit> 
  2. Anula todos los cambios que acabas de hacer:

     git reset 
  3. Compare cuáles son estos cambios, en relación con su último compromiso:

     git diff HEAD 
  4. Agregue selectivamente los cambios que desee:

     git add -p 
  5. Y finalmente haz el nuevo compromiso:

     git commit -m "commit message" 

Fuente: Adaptado de esta respuesta .

Pruebe (utilizando los SHA 1 y 5 como en su ejemplo):

 git diff 1 5 $(git diff --raw --no-commit-id --name-only -r 1~1 1) 

O más cómodamente, por lo que solo debe escribir cada SHA una vez:

 c1="1"; c2="5" git diff $c1 $c2 $(git diff --raw --no-commit-id --name-only -r $c1~1 $c1) 

Cómo debe funcionar: El primer git diff compara los dos commits. El segundo genera una list de routes para limitar la comparación a. Esta list se genera al comparar qué files cambiaron entre su commit $c1 y su $c1~1 padre. (Esto también funciona cuando se especifica algo así como el décimo-último commit utilizando c1="HEAD~10" , ya que HEAD~10~1 es un tree-ish válido en git, equivalente a HEAD~11 ).

La subshell usa git diff --raw para funcionar como para las git diff --raw de fusión. De lo contrario, podríamos usar git diff-tree --no-commit-id --name-only -r $c1 , que automáticamente compara una confirmación con su padre.

TODO: Todavía no completamente funcional. A veces funciona, a veces me sale "fatal: ambiguous argument '<filename>': revisión desconocida o ruta no en el tree de trabajo."