Introducción a GIT

GIT es un sistema distribuido de control de versiones, gratuito y que en los últimos años está incrementando su cuota de usuarios considerablemente. Para aquellos que hayan oído hablar alguna vez de este sistema y que estén considerando un posible cambio desde, presumiblemente, SVN, CVS o incluso Source Safe he escrito este pequeño artículo. Espero que lo encuentren útil.

GIT nace como una necesidad para el desarrollo del kernel de Linux, desarrollado inicialmente por el propio Linus Torvalds, que deseaba un sistema rápido, eficiente y distribuido. Así nace GIT como un conjunto de scripts escritos en perl y shell scripts, que posteriormente han ido siendo migrados a C.

GIT no es un sistema de control de versiones, sino algo más general: es más bien un sistema de ficheros. De hecho no constituye una única aplicación, sino un conjunto de herramientas (scripts).

Características internas del diseño de GIT

Quizá la característica más importante de GIT es que cuando se crea una nueva versión no se crean deltas de diferencias, sino un nuevo árbol. Cuando se diferencian dos versiones se traen ambos árboles y se comparan. Esto es eficiente porque solamente se almacenan los ficheros y directorios idénticos una sola vez, y se transfieren los contenidos de forma comprimida.

Favorece el uso de ramas y su posterior integración; es eficiente ya que la mayoría de las operaciones son locales (y casi instantáneas, por tanto), y los repositorios ocupan muy poco; además se transfiere solamente lo que ha cambiado: si dos ficheros tienen el mismo contenido, éste se transfiere una sola vez.

GIT consta de dos tipos de comandos: de porcelana, típicos de un usuario habitual, y de fontanería: comandos avanzados de bajo nivel. No vamos a entrar en la lista de comandos porque esto se puede encontrar muy bien explicado aquí, por ejemplo.

GIT maneja cuatro tipos de objetos fundamentales en la base de datos. Atención, chicos, que aquí viene el meollo de la cuestión; entender esto es prácticamente entender todo GIT, así que no se me distraigan:

BLOB: Contenidos de los ficheros. Solamente los contenidos, no los metadatos. Si hay dos ficheros con distinto nombre e igual contenido, solamente se almacena 1 blob.

TREE: Estructura de directorios. Contiene, para cada directorio, qué ficheros (blobs) y subtrees contiene. Es, por tanto, una estructura arbórea y recursiva.

COMMIT: Puntero a un árbol (del cual se hizo commit). Contiene autor, committer, message y parent commits que lo preceden, de manera que cada commit apunta al commit que lo precede.

TAG: Es algo así como el alias del commit, con información extra: objeto commit al que apunta, tipo, comentario… Este objeto es probablemente el de menor trascendencia de los cuatro explicados.

Podemos entender la estructura de un repositorio GIT como un grafo acíclico, en el cual un commit apunta a otros commits o trees y un tree apunta a otros trees o blobs. Y aquí viene un maravilloso boceto hecho con Paint que, aunque cutre a más no poder, aclarará la estructura:

Además de los objetos GIT, existe otro concepto que son las referencias GIT. Estos elementos (evitaré denominarlos objetos para con confundirlos con los primeros) no residen en la base de datos del repositorio y pueden cambiar, a diferencia de los objetos, que son inmutables. Esto significa que cada vez que se hace commit se crea un nuevo objeto commit que apunta a un nuevo tree, que apunta a los objetos blob apropiados.

Una rama en GIT es una referencia, un fichero en .git/refs/heads que apunta al último commit de dicha rama. El directorio .git está en la raíz del directorio de trabajo. Este directorio contiene subdirectorios muy interesantes:

  • Ramas: .git/refs/heads
  • Etiquetas: .git/refs/tags
  • Remotes: .git/refs/remotes
  • Objetos: .git/objects (blobs, trees y commits).
  • Configuración: .git/config
  • HEAD: .git/HEAD.
  • Eventos pre y post commit: .git/hooks

Los remotes son punteros a ramas de otros usuarios del mismo repositorio, posiblemente en otra máquina.

HEAD identifica la rama a la que se está apuntando en el instante actual.

La forma que tiene GIT de identificar objetos es mediante claves SHA-1. Puesto que estas claves constan de ristras de caracteres y números considerablemente largas, GIT permite referenciar dichas claves mediante prefijos, siempre y cuando dichos prefijos que identifican objetos sean identificados como únicos en la base de datos.

Vamos a dejarlo aquí, con la esperanza de que haya sido suficiente para que hayan entendido los fundamentos de GIT. Si tienen alguna consulta no duden en escribir. Podrán encontrar más información en la siguiente referencia:

GIT Internals, Source Code Control and beyond

Scott Chacon

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s