Hay algunos problema con Git que barrí bajo la alfombra. Algunos pueden ser manejados con facilidad utilizando scripts y hooks, otros requieren reorganizar or redefinir el proyecto, y por las molestias que quedan, uno simplemente va a tener que esperar. ¡O mejor aún, unirse y ayudar!
A medida que pasa el tiempo, los criptógrafos descubren más y más debilidades de SHA1. Al día de hoy, encontrar colisiones en los hashes es feasible para organizaciones con buenos fondos. En unos años, quizás incluso una PC típica tendrá suficiente poder de cómputo para corromper un repositorio de Git de manera silenciosa.
Esperemos que Git migre a una función de hash mejor antes de que nuevas investigaciones destruyan el SHA1.
Git en Microsoft Windows puede ser engorroso:
- Cygwin, un ambiente similar a Linux para Windows, contiene una versión de Git para Windows.
- Git para Windows es una alternativa que requiere un soporte mínimo para la ejecución, aunque algunos de los comandos necesitan cierto trabajo.
Si tu proyecto es muy grande y contiene muchos archivos no relacionados que están siendo cambiados de manera constante, Git puede estar en desventaja ante otros sistemas, porque no se monitorean archivos simples. Git maneja proyectos enteros, lo cual suele ser beneficioso.
Una solución es partir tu proyecto en pedazos, cada uno consistiendo de archivos relacionados. Usa git submodule si quieres mantener todo en un único repositorio.
Algunos sistemas de control de versiones te fuerzan a marcar un archivo de manera explícita antes de editarlo. Si bien esto es especialmente molesto cuando esto involucra comunicarse con un servidor central, también tiene dos beneficios:
- Los diffs son rápidos porque solo se precisa examinar los archivos marcados.
- Uno puede descubrir quién más está trabajando en el archivo preguntándole al servidor central quien lo marcó para edición.
Con scripts apropiados, se puede alcanzar lo mismo con Git. Esto requiere cooperación del programador, quien debería ejecutar ciertos scripts cuando edita un archivo.
Como Git guarda cambios por proyecto, reconstruir la historia de un archivo dado requiere más trabajo que en sistemas de control de versiones que administran archivos individuales.
El problema suele ser leve, y vale tenerlo dado que otras
operaciones son increíblemente eficientes. Por ejemplo,
git checkout
es más rápido que
cp -a
, y los deltas de un
proyecto completo comprimen mejor que colecciones de deltas
por archivo.
Cuando hay una historia larga, crear un clon es más costoso que hacer checkout de código en otros sistemas de control de versiones.
El costo inicial lo vale a la larga, dado que la mayoría
de las operaciones futuras van a ser rápidas y desconectado.
De todos modos, en algunas situaciones, seria preferible
crear un clon sin profundidad usando la opción --depth
. Esto es mucho más rápido, pero el
clon resultante tiene su funcionalidad reducida.
Git fue escrito para ser rápido respecto al tamaño de los cambios. Los humanos hacen pequeñas ediciones de versión a versión. Un bugfix de una línea acá, una nueva funcionalidad allá, comentarios retocados, y así en adelante. Pero si tus archivos son radicalmente diferentes en revisiones sucesivas, entonces en cada commit, tu historia crece necesariamente igual que tu proyecto entero.
No hay nada que ningún sistema de control de versiones pueda hacer sobre esto, pero los usuarios standard de Git van a sufrir más, dado que las historias son clonadas.
La razón por la que los cambios son tan grandes deberían ser examinadas. Tal vez los formatos de los archivos deberían ser cambiados, ediciones pequeñas deberían causar cambios menores en a lo sumo unos pocos archivos.
O tal vez una base de datos o una solución de backup/archivado es lo que realmente se necesita, no un sistema de control de versiones. Por ejemplo, un el control de versiones es poco adecuado para administrar fotos tomadas periódicamente con una webcam.
Si los archivos deben cambiar constantemente, y realmente se necesita que estén versionados, una posibilidad es usar Git de una forma centralizada. Uno puede crear clones sin profundidad, lo cual acarrea poco y nada de la historia del proyecto. Por supuesto, muchas herramientas de git no van a estar disponibles, y los arreglos deben ser enviados como patches. Esto probablement no sea problema, dado que no está claro por qué alguien quisiera un historial de archivos salvajemente inestables.
Otro ejemplo es un proyecto que depende de firmware, que toma la forma de un archivo binario enorme. La historia de este firmware no es de interés para los usuarios, y las actualizaciones comprimen de forma insatisfactoria, por lo que las revisiones de firmware aumentarían el tamaño del repositorio de manera innecesaria.
En este caso, el código fuente debe ser guardado en un repositorio de Git, y el archivo binario debe ser mantenido de forma separada. Para hacer la vida más fácil, uno puede distribuír un script que usa Git para clonar el código y rsync o un clon sin profundidad de Git para el firmware.
Algunos sistemas de control de versiones centralizados, mantienen un entero positivo que aumenta cuando un nuevo commit es aceptado. Git se refiere a los cambios por su hash, lo que es mejor en muchas circunstancias.
Pero a algunas personas les gusta tener este entero a mano. Por suerte es fácil escribir scripts de forma que con cada update, el repositorio central de git incrementa un entero, tal vez en un tag, y lo asocia con el hash del último commit.
Cada clon podría mantener esete contador, pero esto sería probablemente inútil, dado que solo el repositorio central y su contador son los que importan.
Los subdirectorios vacíos no pueden ser administrados. Crea archivos dummy para evitar este problema.
La implementación actual de Git, y no su diseño, es quien tiene la culpa de este problema. Con suerte, una vez que Git gane más tracción, más usuarios van a clamar por esta funcionalidad y va a ser implementada.
El estereotipo de un informático teórico cuenta desde 0, en lugar de desde 1. Lamentablemente, con respecto a los commit, Git no mantiene esta convención. Muchos comandos son poco amigables antes del commit inicial. Adicionalmente algunos casos borde deben ser manejados de forma especial, como hacer rebase de una rama con un commit inicial distinto.
Git se beneficiaría al definir el commit cero: tan pronto como se construye un repositorio, HEAD debería ser un string conteniendo 20 bytes de 0. Este commit especial representa un árbol vacío, sin padre, que en algún momento es parte de todos los repositorios de Git.
Entonces el correr git log, por ejemplo, informaría al usuario que no se han hecho commits aún, en lugar de salir con un error fatal. Algo similar pasaría con otras herramientas.
Cada commit inicial es de forma implícita un descendiente de este commit cero.
Lamentablemente igual hay algunos casos que presentan problemas. Si varias ramas con commits iniciales diferentes se mergean juntas, entonces un rebase del resultado requiere una buena cantidad de intervención manual.