Compartir a través de


Obtenga información sobre cómo quitar un binario grande del historial de Git para administrar el tamaño de los repositorios clonados.

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2019

Git ha ganado mucha popularidad en los últimos años como repositorio de código fuente distribuido que permite a los usuarios trabajar con el repositorio completo mientras están en un estado desconectado. Las ventajas de Git están bien documentadas, pero ¿qué ocurre si necesita "revertir el reloj" en el repositorio principal? Esto no es tan intuitivo y requiere permisos elevados, como podría esperar para algo que afecte a cada usuario del repositorio.

¿Cómo puede revertir el repositorio central de forma segura?

Escenario del problema

Imagine que confirma un archivo grande, como un vídeo, en el servidor git. En un sistema de código fuente tradicional, es conveniente almacenar todo en un solo lugar y, a continuación, extraer lo que necesita. Sin embargo, con Git, todo el repositorio se clona en el equipo local de cada usuario. Con un archivo grande, todos los usuarios del proyecto también tendrán que descargar los archivos grandes. Con cada archivo grande posterior que confirma en el servidor, el problema crecerá, hasta que el repositorio sea demasiado grande para que sus usuarios lo usen de forma eficaz. Para empeorar las cosas, incluso si quita el archivo en cuestión del repositorio local y vuelve a enviar la confirmación, el archivo seguirá existiendo en el historial del repositorio, lo que significa que se seguirá descargando en el equipo local de todos los usuarios como parte del historial.

Cuadro de diálogo Cambios de Team Explorer que muestra un vídeo grande en los cambios incluidos

Adición de un archivo grande al repositorio local

Servidor y repositorio local, ambos con una copia de los archivos de vídeo grandes

Después de confirmar desde el repositorio local, el servidor también tendrá el archivo grande

Congelar el repositorio

Importante

Los siguientes pasos eliminarán el video de la historia de la rama, pero el archivo permanecerá en la historia del repositorio al clonar tu repositorio desde Azure Repos. Quitar los archivos del historial de ramas impide que los archivos se actualicen, lo que creará otra versión del archivo grande en el repositorio. Obtenga más información sobre cómo administrar archivos grandes en Git y consulte esta entrada de blog para obtener una explicación detallada y una solución alternativa para este comportamiento al usar repositorios git de Azure Repos.

Para corregirlo, debe iniciarse en el origen, que, en este caso, es el repositorio del servidor. Pida al equipo que deje de enviar cambios al repositorio, pero si se producen envíos de cambios adicionales durante este proceso, también tendrá que tenerlos en cuenta, para que no pierda ningún dato.

Fusión mediante cambio de base y forzar el envío de cambios

Si nadie más del equipo ha realizado ningún cambio en el repositorio (normalmente a través de un push), puede tomar la ruta sencilla, en la que básicamente hace que el repositorio local tenga la apariencia que desea (es decir, sin el archivo grande), y luego fuerza sus cambios al servidor.

Nota: Es posible que tenga que clonar o corregir el repositorio local antes de comenzar este trabajo. Esto podría dar lugar a cambios o trabajos perdidos, por lo que debe continuar con precaución.

De forma predeterminada, es probable que solo tenga la capacidad de cambiar sus archivos y repositorios locales del proyecto y de insertar los cambios en el servidor, por lo que no tiene la capacidad de realizar otros cambios, como eliminaciones o rebasado, a nivel de servidor. Por lo tanto, deberá adquirir permisos para Forzar el envío de cambios (preferible) o de administrador del proyecto o buscar a alguien que los tenga y esté dispuesto a ayudar. Para más información sobre los permisos de Git, vaya aquí.

Símbolo del sistema: git push --force permissions.

A continuación, debe hacer rebase del repositorio.

  1. Pero en primer lugar, use git log para buscar los valores hash sha de las confirmaciones más recientes: necesitará esta información en un momento. Esto se debe a que necesitamos conocer la confirmación correcta más reciente. Para obtener esa información, abra un símbolo del sistema de Git y escriba:

git log

Como alternativa, puede obtener el hash SHA al ver el historial de ramas en Visual Studio Team Explorer.

Ver historial de la rama principal

  1. Ahora, abra un símbolo del sistema de Git.

Cuadro de diálogo de sincronización: acción de apertura del símbolo del sistema

  1. Busque el número de hash SHA de interés.

Símbolo del sistema: selección de la confirmación del vídeo

  1. Necesitará el SHA que comienza con «25b4»

Recuerde que Git usa punteros para determinar dónde se encuentra en el repositorio el encabezado o la rama actual. Por este motivo, el estado del repositorio que le interesa estará en algún momento del pasado. Para volver al tiempo y hacer que el estado deseado anterior sea el nuevo estado actual, deberá usar el comando de rebase de Git:

git rebase -i <SHA hash of desired new current branch>

Rebase para quitar el archivo de vídeo

El -i interruptor proporciona un poco de seguridad adicional, ya que mostrará el historial en un editor (Mi implementación de Git en la línea de comandos de Windows abre el editor vi clásico, que puede recordar si ha trabajado con un sistema basado en Unix).

  1. En nuestro ejemplo, escribiría lo siguiente:

git rebase -i 25b4

  1. Una vez que aparezca el editor, quite todas las líneas "pick", excepto la rama que quiere conservar como la nueva principal. Cuando todo parezca como desee, en vi, escriba ":w<enter>" para guardar o "!q<enter>" para salir sin guardar.

Símbolo del sistema: fusión mediante cambio de base de Git con el comando pick -i 25b4

Vas a cambiar las líneas que ya no deseas.

Símbolo del sistema: fusión mediante cambio de base de Git con el comando drop -i 25b4

  1. Cambie "pick" a "drop", como se muestra, escriba ":w" (en vi) para guardar y ":q!" para iniciar la fusión mediante cambio de base

Ahora escriba git log de nuevo: la rama ofendida debe estar ausente del registro. Si es así, está listo para el paso final, que requiere permisos de administrador del proyecto.

git log

Repositorios locales y de servidor después del rebaseo

Observe que la confirmación del vídeo grande ha desaparecido del repositorio local

  1. Tipo: git push --force

Ventana de comandos - git push --force

Símbolo del sistema: git push --force result

Este comando obligará al repositorio a sobrescribir el repositorio en el servidor.

Use con precaución, ya que puede perder fácilmente datos en el servidor!!

Empuje forzado mostrando el contenido que se debe conservar, sin incluir el archivo de vídeo

Tenga en cuenta que debe autenticarse en el servidor para que funcione.

Si usa Azure Repos, es posible que tenga que configurar una credencial alternativa que no use caracteres especiales (como "@" en una dirección de correo electrónico). Para ello, siga las instrucciones que se indican aquí.

Ahora, la rama desaparecerá permanentemente del servidor, y los miembros del equipo del proyecto no descargarán los archivos grandes que intentabas quitar en los nuevos clones y sincronizaciones. Los usuarios tendrán que incorporar los cambios del servidor para asegurarse de que están sincronizados con el nuevo estado del repositorio de servidor.

Si los usuarios tienen confirmaciones más recientes

Si otros usuarios ya han realizado confirmaciones en el repositorio del servidor, también tendrá que tenerlo en cuenta. Quiere quitar la rama que contiene los archivos grandes, pero no desea perder los cambios realizados por el equipo. Para solucionar este problema, al abrir el editor como parte de la fusión mediante cambio de base, examine detenidamente las confirmaciones. Asegúrese de que las confirmaciones que quiere conservar se muestran en las líneas "pick"; elimine las que quiere quitar, como en la que agregó un archivo grande.

Tenga en cuenta que, después de la fusión mediante cambio de base, los demás usuarios del equipo también tendrán que realizar una fusión mediante cambio de base para que todos tengan una copia coherente del repositorio del servidor. Esto es un dolor para todos y normalmente debe evitarse. Por lo tanto, si necesita quitar un envío de cambios como se indica aquí, es importante coordinarse con el equipo. Para obtener detalles completos sobre la fusión mediante cambio de base, eche un vistazo a la documentación oficial de fusión mediante cambio de base aquí.

La clave es asegurarse de que sabe qué confirmaciones quiere conservar y cuáles no. Estudie el registro de Git o el historial en su IDE (como Visual Studio) y tome una nota meticulosa de los hashes SHA que debe conservar y aquellos que debe descartar.

En escenarios en los que el archivo grande lleva ya un tiempo en el repositorio y ha habido ramas y combinaciones posteriores, es posible que pueda quitar el archivo con el modificador git filter-branch. Si quiere probar esto, siga las instrucciones que se indican aquí.

Consideraciones de procedimientos recomendados

Ahorra mucho trabajo asegurarse de que los archivos de gran tamaño permanezcan fuera del repositorio principal desde el principio. Teniendo esto en cuenta, estos son algunos procedimientos recomendados de sentido común para que el equipo tenga en cuenta:

Qué hacer

  • Confirme los cambios con frecuencia. Siempre puede corregirlos más adelante con una fusión mediante combinación con "squash" o una fusión mediante cambio de base.
  • Asegúrate de usar ramas para aislar tus cambios. Las ramas son baratas y privadas, y la fusión es sencilla. También puede realizar una copia de seguridad de los cambios en una rama insertandolos en el servidor.
  • Use una convención de nomenclatura al publicar ramas de temas. Asigne a la rama el nombre "users/<alias>/<branchname>". Esto ayudará a agrupar las ramas y facilitar a los demás identificar el "propietario".
  • Recuerde insertar los cambios. Commit != Checkin. (Commit + Push) == Checkin.
  • Considere la posibilidad de usar .gitignore para archivos binarios grandes para que no se agreguen al repositorio en primer lugar: más información aquí.
  • Considere la posibilidad de usar el control de versiones de NuGet o TFS para almacenar los archivos binarios grandes.

Cosas que no debes hacer

  • No fusione mediante cambio de base después de enviar cambios. La fusión mediante cambio de base de confirmaciones insertadas en Git puede ser incorrecta porque obliga a todos los demás miembros del repositorio a realizar una fusión mediante cambio de base de sus cambios locales, y no les gustará tener que hacer esto. La fusión mediante cambio de base de confirmaciones insertadas en su propia rama personal, incluso si se han insertado, no es un gran problema a menos que otras personas incorporen los cambios de esas confirmaciones.
  • No suba archivos binarios a su repositorio. Git no comprime los archivos binarios del mismo modo que lo hace TFVC y, dado que todos los repositorios tienen todo el historial, cometer archivos binarios significa un incremento de tamaño permanente.

Resumen

A veces, los elementos no deseados, como los archivos grandes, se agregan a un repositorio y deben quitarse para mantener el repositorio limpio y ligero. Para ello, obtenga el repositorio local en orden mediante el git rebase comando y, a continuación, use el git push --force comando para sobrescribir el repositorio del servidor con el repositorio local.

Autores: Edward Fry y Jesse Houwing | Conexión con los autores y ALM | DevOps Rangers aquí

(c) 2015 Microsoft Corporation. Todos los derechos reservados.øEste documento se proporciona "as-is." La información y las vistas expresadas en este documento, incluidas las direcciones URL y otras referencias a sitios web de Internet, pueden cambiar sin previo aviso. Usted asume el riesgo de utilizarla.

Este documento no le proporciona ningún derecho legal a ninguna propiedad intelectual en ningún producto de Microsoft. Puede copiar y usar este documento con fines internos de referencia.