es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Git: crea un repositorio espejo/fork con historial reducido.

Supongamos que hay un gran repositorio de Git llamado “Orig” en pleno desarrollo y con una larga historia. Ese repositorio también tiene algunos archivos grandes, pero no utiliza git-lfs. No tengo control sobre ese repositorio, en particular no puedo migrarlo a git-lfs.

Me gustaría crear un repositorio derivado (“Fork”) con las siguientes propiedades:

  1. Puedo fusionar fácilmente los cambios del desarrollo de “Orig” en las ramas correspondientes de “Fork” y en mis ramas personalizadas basadas en esas ramas (cherry-pick de cada cambio no cuenta como “fácil”).
  2. Puedo crear fácilmente solicitudes de extracción al repositorio “Orig” con algunos de mis cambios en “Fork” (menos importante que #1, pero sería bueno tenerlo).
  3. Quiero reducir significativamente la historia de “Fork” en cuanto a su profundidad (clon más pequeño).
  4. Quiero reducir significativamente la historia de “Fork” en cuanto a los archivos grandes, porque quiero alojar mi “Fork” en GitHub. Esto es un problema porque “git-lfs migrate” reescribe la historia.

Solucionar accidentalmente solo el punto #3 probablemente arreglará el punto #4, ya que solo hay algunos archivos realmente grandes que requerirían git-lfs y no están en la parte de la historia que realmente quiero mantener en mi “Fork”.

Lograr solo el punto #4 sin el punto #3 (pero aún obteniendo los puntos #1 y #2) es aceptable porque el punto #4 es realmente un obstáculo mientras que el punto #3 es solo algo deseable.

Cosas que realmente no necesito:
– No necesito mantener todas las ramas históricas de “Orig” en mi “Fork”. Realmente necesito la rama principal (“master”) y algunas ramas de características recientes también serían realmente buenas.
– Es aceptable que la configuración inicial sea complicada y lleve tiempo, siempre y cuando el flujo principal posterior funcione sin problemas.

Algunas cosas obvias que creo que no funcionan:

  • Realizar “git-lfs migrate” para solucionar el punto #4 y enviarlo a GitHub. Esto parece romper los puntos #1 y #2, ya que crea una historia totalmente nueva sin conexión con la original, por lo que no puedo fusionar fácilmente nuevos cambios de “Orig” a “Fork”.
  • Crear una copia superficial y enviarla como un nuevo repositorio a GitHub. Esto soluciona el punto #4 y probablemente el punto #3, pero nuevamente rompe los puntos #1 y #2.

Sospecho que no hay una solución buena para este problema con respecto a cómo funcionan los hashes de git. Al menos, los enlaces https://stackoverflow.com/questions/51597812/partial-repository-mirror-of-git-repositories y https://stackoverflow.com/questions/50740609/git-mirror-of-non-lfs-repo-to-lfs-repo no parecen realmente prometedores. Pero aún tengo la esperanza de que se pueda hacer con algo de magia de git (o que de alguna manera las cosas hayan cambiado en los últimos años).

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Una posible solución para lograr #1, #2 y #4 sin sacrificar completamente #3 es utilizar submódulos de Git. Aquí están los pasos para configurarlo:

    1. Crea un repositorio vacío en GitHub y clónalo en tu máquina local (Fork).
    2. Clona también el repositorio Orig en tu máquina local.
    3. En el repositorio Orig, crea una nueva rama que solo contenga los commits que deseas incluir en tu Fork (es decir, la rama master y algunas ramas de características recientes).
    4. En el directorio raíz de tu repositorio Fork, agrega el repositorio Orig como un submódulo utilizando el comando git submodule add <url> (sustituye <url> por la URL del repositorio Orig). Esto creará un nuevo directorio en tu repositorio Fork que contiene un clon del repositorio Orig.
    5. En el directorio del submódulo Orig en tu repositorio Fork, cambia a la rama que creaste en el paso 3 (git checkout <branch>).
    6. Elimina los archivos grandes en el directorio del submódulo Orig que no necesitas (pero asegúrate de que no sean necesarios para los commits que deseas conservar). Puedes utilizar herramientas como git filter-branch o git subtree para eliminar estos archivos.
    7. Haz commit de los cambios en el directorio del submódulo Orig y súbelos al repositorio Fork.
    8. En el directorio raíz de tu repositorio Fork, haz commit de los cambios para agregar el submódulo (git commit -am "Agregar submódulo Orig").
    9. Súbelos cambios al repositorio Fork (git push).

    Ahora, cada vez que desees fusionar cambios desde el repositorio Orig a tu Fork, simplemente actualiza el submódulo (git submodule update) y luego fusiona los cambios en tus ramas Fork. De manera similar, si deseas crear una solicitud de extracción al repositorio Orig con algunos cambios de tu Fork, puedes crear una rama en el directorio del submódulo Orig, agregar tus cambios allí y crear la solicitud de extracción desde esa rama.

    Esta solución también debería abordar el punto #4, porque solo estás conservando los commits y archivos que necesitas en el directorio del submódulo Orig, y los archivos grandes que no son necesarios deben eliminarse durante el paso 6. Sin embargo, aún puedes encontrarte con el límite de tamaño de archivo de GitHub si los archivos restantes siguen siendo demasiado grandes, en cuyo caso es posible que debas utilizar git-lfs después de todo (y sacrificar #3).

Comments are closed.