git filter-branch condujo a un historial desconectado: ¿cómo deshacerse de los viejos commits?

El escenario es el siguiente:

Tengo un gran repository CVS que quiero convertir a 14 repositorys git distintos. La parte cvs2git del process está bien y lleva a un gran repository repo.git.

Para cada uno de los 14 git repo, clono el repository principal y ejecuto el siguiente command:

 git filter-branch -d /tmp/rep --tag-name-filter cat --prune-empty --subdirectory-filter "sub/directory" -- --all 

Sin embargo, antes de este command, tengo que realizar otro command git filter-branch para algunos repositorys git porque tengo que reescribir los commits para mover un file de un directory a otro. El --tree-filter es la opción que uso. Aquí hay un ejemplo de la línea de command ejecutada:

 script_tree_filter="if test -f rep/to/my/file && test -d another/rep ; then echo Moving my file ; mv rep/to/my/file another/rep; fi" git filter-branch -d /tmp/rep --tag-name-filter cat --prune-empty --tree-filter '$script_tree_filter' -- --all 

Al final del process (14500 confirmaciones: ¡demora alnetworkingedor de 1 hora!) Limpio los refs y uso git gc :

 git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d git reflog expire --expire=now --all git gc --prune=now 

Al final, obtengo un repository con un tamaño de 1.2Go (que obviamente sigue siendo demasiado grande), y al observar los commits, puedo ver que muchos de los antiguos aún están presentes. Se refieren a files y directorys que ya no deberían estar aquí después del --subdirectory-filter .

En la historia de los commits, hay una discontinuidad entre los commits no deseados y los buenos como se ve en gitk --all :

discontinuidad vista en gitk

Estoy bastante seguro de que esos commits todavía están presentes debido a las tags en algunos de ellos. Si este es el caso, ¿es posible eliminar esas tags sin eliminar la de las confirmaciones correctas?

Si las tags no son la razón, ¿alguna idea?

Para get más información, el contenido del directory refs (en el repository git obtenido por el subdirectory-filter) está vacío:

 $ ls -R refs/ refs/: heads original tags refs/heads: refs/original: refs refs/original/refs: heads tags refs/original/refs/heads: refs/original/refs/tags: refs/tags: 

Descubrí que las twigs y las tags se enumeran en el file packed-refs en el repository de git:

 d0c675d8f198ce08bb68f368b6ca83b5fea70a2b refs/tags/v03-rev-04 95c3f91a4e92e9bd11573ff4bb8ed4b61448d8f7 refs/tags/v03-rev-05 

Hay 817 tags y 219 twigs enumeradas en el file.

Pude resolver mi problema cambiando la forma en que usé cvs2git : en vez de convertir toda la base de CVS y luego usar el command subdirectory-filter , convertí cada uno de los submodules que quería. En mi caso, esto llevó a lanzar 18 commands cvs2git diferentes:

antes de

 cvs2git --blobfile=blob --dump=dump /path/to/cvs/base # Module 1 git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter "path/to/module1" -- --all # Module 2 git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter "path/to/module2" -- --all 

Ahora

 # Module 1 cvs2git --blobfile=blob_module1 --dump=dump_module1 /path/to/cvs/base/path/to/module1 # Module 2 cvs2git --blobfile=blob_module2 --dump=dump_module2 /path/to/cvs/base/path/to/module2 

Cada repository tiene ahora una historia perfecta.

¿Por qué el método anterior no funcionó? Supongo que cvs2git se confundió con todos los submodules (algunos de ellos cambiaron su nombre de directory durante su historial).

@Michael @CharlesB Gracias por tomarse su time para responder y ayudarme.

Apuesto a que te están golpeando con esto:

  • Diferencias entre CVS y los models de git branch / tag: CVS permite crear una twig o label a partir de combinaciones arbitrarias de revisiones de fonts de múltiples twigs de origen. Incluso permite que las revisiones de files que nunca fueron contemporáneas se agreguen a una sola twig / label. Git, por otro lado, solo permite que el tree fuente completo, tal como existió en algún momento de la historia, se ramifique o marque como una unidad. Además, la ascendencia de una revisión de git tiene implicaciones sobre el contenido de esa revisión. Esta diferencia significa que es fundamentalmente imposible representar un historial de CVS arbitrario en un repository de git 100% fielmente. cvs2git utiliza las siguientes soluciones alternativas:

    • cvs2git intenta crear una twig a partir de una única fuente, pero si no puede averiguar cómo hacerlo, crea la twig utilizando una "fusión" desde múltiples twigs de origen. En situaciones patológicas, el número de fonts de fusión para una sucursal puede ser arbitrariamente grande. El historial resultante implica que cada vez que se agregaba un file a una twig, toda la twig fuente se fusionaba en la twig de destino, lo que es claramente incorrecto. (La alternativa, omitir la fusión, descartaría la información de que parte del contenido se movió de una twig a otra).

    • Si cvs2git no puede determinar que una label CVS puede crearse a partir de una única revisión, entonces crea una twig de corrección de label llamada TAG.FIXUP, luego label esta twig. (Esta es una solución necesaria para el hecho de que git solo permite labelr las revisiones existentes). La twig TAG.FIXUP se crea como una combinación entre todas las twigs que contienen revisiones de files incluidas en la label, lo que implica la misma compensación descrita arriba para las twigs. La twig TAG.FIXUP se borra al final de la conversión, pero (debido a una limitación técnica del formatting de file de import rápida de git) no se elimina. Hay algunas situaciones en las que se puede crear una label a partir de una única revisión, pero cvs2git no se da count y crea una twig de corrección de label superflua. Es posible eliminar twigs de corrección de label superfluas después de la conversión ejecutando el script contrib / git-move-refs.py dentro del repository de git resultante.

  • No hay comprobaciones de que los nombres de twig y label de CVS sean nombres legales de git. Probablemente haya otras restricciones de git que también deberían verificarse. ver cvs2git

¿Está mostrando el directory refs de los nuevos directorys o del repo grande después de la conversión? Puede eliminar las tags en su repository grande de export antes de filtrar y dividir el repository grande.

Puede eliminar tags en el repository grande simplemente borrando el file en el directory; es solo una reference a un SHA.

    Intereting Posts