Que es Git ?
Git es un sitema de control de revisiones distribuido, o software de administracion de proyectos de codigo fuente con un enfasis en ser rapido. Git fue inicialmente creado por Linus Torvalds para el desarrollo del kernel Linux
Git se diferencia de CVS en que cada directorio de trabajo contiene un repositorio con una copia completa de la historia del proyecto, y ningun repositorio es inherentemente mas importante que los demas. Esta es la naturaleza distribuida de Git, el cual no depende de acceso a red o un servidor central. Sin embargo, se puede emular el modelo CVS designando un repositorio compartido, contra el cual los desarrolladores pueden sincronizar. Mas adelante se explica como configurarlo de esta forma
Referencias
sitios con documentacion:
- Sitio Git Community book donde se puede descargar gratuitamente el libro Git Community Book, en formato pdf
- Git Tutorial
- Git Glossary
- Screencast 1 – Obteniendo un repositorio Git setup, init and commit
- CVS Git migration
screenshot herramienta grafica gitk, usada para visualizar historiales
Algunos proyectos usando Git
- Git
- Linux Kernel
- Perl
- Ruby on Rails
- Android
- WINE
- Fedora
- X.org
- VLC
- Prototype
Comentaré brevemente los puntos sobresalientes que he encontrado en este sistema de versionado. No voy a escribir aqui un tutorial completo, puesto que los existentes son muy buenos. Simplemente desarrollare los primeros capitulos del libro Git community Book, remarcando las diferencias entre este sistema de versionado con los sistemas actuales mas utilizados, como por ejemplo Subversion. Por lo tanto asumiré que el lector tiene un background en sistemas de versionado, y sobre todo en el uso diario de Subversion (svn).
Conceptos Git
Algunos conceptos interesante y novedosos en los que se basa Git:
- La base de datos de objetos es un sistema elegante usado para almacenar la historia de los proyectos — archivos, directorios y commits.
- El archivo index es una especie de cache del estado de un arbol de directorio, usado para crear un commit, hacer check out de directorios de trabajo, y mantener varios arboles involucrados en un merge.
Git soporta varios protocolos para acceso remoto **ssh:// http(s) git:// rsync **
Representacion interna
- Todos los nombres de archivos en Git tiene 40 digitos (el object name) , los cuales representan un codigo SHA1 y son unicos dentro de cada proyecto.
- Cada archivo puede contener alguno de los 4 tipos de objetos (blob, tree, commit o tag) con los cuales se representan todas las cosas.
Ventajas:
- Es muy facil verificar diferencias, simplemente comprando los nombre de archivos
- Facil detectar errores, comprando el SHA1 del archivo con su contenido.
Estructura de un Git Object
Object =
- size
- content
- type
- blob : simplemente un stream de datos
- tree : es como un directorio, a su vez puede referenciar trees y blobs
- commit : snapshot + meta informacion
- tag : marca un commit especifico
El comando git show puede ser usado entre otras cosas para ver la estructura interna de los objetos:
$ git log --stat commit e94bbd6e0b71efc4e6f6ec8d2d59b9fcf4964f08 Merge: b93c84f... 9edade8... Author: Sebastian Emilio Narvaez <sebastian@miemail.com.ar> Date: Sun Jan 18 19:29:54 2009 -0200 [...] $ git show e94bbd6e0b71efc4e6f6ec8d2d59b9fcf4964f08 --pretty=raw commit e94bbd6e0b71efc4e6f6ec8d2d59b9fcf4964f08 tree aa16d4c0828ce61ea72f4e1e13b02033354b6736 parent b93c84f0a30f030ab68c7b991cb12a510544603e parent 9edade8e672770a470b2a028f9a593dc05663623 author Sebastian Emilio Narvaez <sebastian@gcoop.com.ar> 1232314194 -0200 committer Sebastian Emilio Narvaez <sebastian@gcoop.com.ar> 1232314194 -0200 [...]
Directorio Git
Git guarda toda la informacion de versionado dentro del directorio .git, en el directorio principal de nuestro proyecto.
$ ls -AF .git/ branches/ config gitk.cache hooks/ info/ objects/ refs/ COMMIT_EDITMSG description HEAD index logs/ ORIG_HEAD
En el archivo config, se guarda la configuracion del repositorio: nombre de usuario, URL o direccion remota del repositorio, etc
Se puede usar el comando git config para setear valores en este archivo, sin tener que modificarlo manualmente
$ git config --global user.name "Sebastian E. Narvaez" $ git config --global user.email "seba@email.com"
El archivo index es especial. Es una especie de staging o archivo temporal, donde se guardan los cambios antes de hacer un commit.
Obteniendo un repositorio Git
Git soporta varios protocolos para acceso remoto **ssh:// http(s) git:// rsync **
$ git clone git://git.kernel.org/pub/scm/git/git/git.git $ git clone http://www.kernel.org/pub/scm/git/git.git
Usar:
- Protocolo git: es mas rapido y eficiente
- Protocolo http: Cuando estemos detras de un firewall corporativo
Inicializando un nuevo repositorio
$ tar xzf project.tar.gz $ cd project $ git init
git init crea el directorio .git dentro del directorio principal del proyecto, junto con toda la metadata con informacion de versionado.
Luego, usamos el comando git add para agregar los archivos al sistema de versionado.
NOTA: Hay una diferencia importante con el comando svn add de subversion. En subversion, svn add se utiliza unicamente la primera vez, o para agregar archivos nuevos, mientras que en Git, el comando add se utiliza tanto para agregar nuevos archivos, como para indicar cuales archivos han sido modificados. Es decir, en Git tenemos que usar git add cada vez que modificamos un archivo. Lo que hace el comando git add, es agregar los cambios al archivo index. Estos cambios en el archivo index son los que luego son commiteados al ejecutar git commit.
Para simplificar, existe la opcion -a: git commit -a, el cual tiene la funcion de realizar un add de todos los archivos modificados localmente, y luego realizar un commit normal
Siguiendo con el ejemplo, agregamos algunos archivos
$ git add file1 file2 file3
git diff nos mostrara los archivos modificados localmente, pero que todavia no han sido agregados con add ( o sea, todavia no se encuentran en el archivo index, por lo tanto no seran commiteados al ejecutar git commit.
git diff –cached, por otro lado nos mostrará los cambios contenidos en el archivo index, y que por lo tanto seran commiteados al ejecutar git commit
- git commit -a
- Automaticamente encuentra cualquier archivo modificado (pero no nuevo), los agrega al index, y commitea, todo en un solo paso
- git add
- Es usado para archivos nuevos, y para archivos modificados
- git branch experimental
- Crear una nueva rama, llamada experimental
- git branch
- Lista de branches
- git checkout experimental
- Cambiar el directorio de trabajo a la rama experimental
- git checkout master
- Devuelta en la rama principal
- git merge experimental
- Mezcla los cambios hechos en la rama experimenta, en la rama actual
- git diff
- Si hubo conflictos, los archivos se marcan con markers
- gitk
- Representacion grafica de la historia de un proyecto
- git branch -d experimental
- Borrar la rama experimental. Se asegura que los cambios de la rama experimental hayan sido mezclados en la rama principal
- git branch -D idea-loca
- Borra la rama experimental, sin revizar si los cambios fueron mergeados
Flujos de trabajo distribuidos
A continuacion, un ejemplo de trabajo distribuido (sin un servidor y repositorio central )
Bob se descarga el proyecto de Alice, colabora modificando algunos archivos, y luego realiza un commit con todos sus cambios:
bob$ git clone /home/alice/project myrepo bob$ ( edita archivos ) bob$ git commit -a
Alice mezcla los cambios de la rama principal de Bob en su rama actual:
alice$ cd /home/alice/project alice$ git pull /home/bob/myrepo master
Otra forma en que Alice puede mezclar (merge) los cambios, pero teniendo mas control es la siguiente:
alice$ git remote add bob /home/bob/myrepo # define un shortcut al repo de Bob alice$ git fetch bob # solo trae los datos, pero no hace merge # guarda los cambios en la rama de tracking remoto alice$ git log -p master..bob/master # revisa los cambios hechos por Bob. alice$ git merge bob/master # por ultimo, mezcla los cambios de Bob en su propio repo
Bob actualiza su repositorio con los cambios de Alice.
bob$ git pull
Ejemplo configuracion repositorio Git publico via http
Configurando un repositorio compartido
Asumiremos que ya tienes creado el repositorio git para tu proyecto, posiblemente creado desde cero o desde un tarball, o importado desde un repositorio CVS existente.
Suponiendo que el repositorio existente es ~/public_html/pruebagit/ , hay que crear un nuevo repositorio en modo “bare” (un repositorio sin directorio de trabajo) y hacer un fetch (traer) el proyecto en el nuevo directorio
Repositorio “bare”
Un repositorio “bare” es normalmente un directorio con un sufijo .git que no tiene una copia localmente descargada (cheked out) de ninguno de los archivos bajo control de revision. Esto es, todos los archivos git administrativos y archivos de control que estarian normalmente presentes en un subdirectorio oculto .git, estan directamente presentes en el directorio repositorio.git, y ningun otro archivo esta presente. Usualmente repositorios publicos son hechos repositorios “bare”
~/public_html$ mkdir bare-repo.git ~/public_html$ cd bare-repo.git/ ~/public_html/bare-repo.git$ git --bare init --shared Initialized empty shared Git repository in /home/seba/public_html/bare-repo.git/ ~/public_html/bare-repo.git$ ls branches config description HEAD hooks info objects refs ~/public_html/bare-repo.git$ git --bare fetch ~/public_html/pruebagit/ master:master remote: Counting objects: 21, done. remote: Compressing objects: 100% (11/11), done. remote: Total 21 (delta 2), reused 4 (delta 0) Unpacking objects: 100% (21/21), done. From /home/seba/public_html/pruebagit * [new branch] master -> master
Al intentar hacer un clone via http de nuestro nuevo repositorio “bare”, puede que nos encontremos con el siguiente problema:
~$ git clone http://localhost/bare-repo.git/ Initialized empty Git repository in /home/seba/bare-repo/.git/ warning: remote HEAD refers to nonexistent ref, unable to checkout.
Para resolver ese problema, ejecutamos el comando **git update-server-info **
~/public_html/bare-repo.git$ git update-server-info
Ahora probamos, y git clone funciona correctamente.
~$ git clone http://localhost/bare-repo.git master
Muchas opciones
A continuacion, algunos ejemplos que muestran la gran cantidad de opciones que soportan los comandos de git. La mayoria de las opciones pueden combinarse para formar consultas complejas, por ejemplo realizar busqudas de commits por determinadas fechas, que contengan ciertos strings, y en determinados directorios, etc.
Historial
El comando git log sirve para ver informacion historial del repositorio, y nos presenta con una gran cantidad de opciones
- git log
- Todos los commits visibles desde el commit padre
- git log v2.5..
- Todos los commits a partir de (pero no visibles desde ) la version V2.5
- git log test..master
- Commits visibles desde master, pero no desde test
- git log master..test
- Commits visibles desde test, pero no desde master
- git log master…test
- Commits visibles desde test o master, pero no desde ambos
- git log –since=”2 weeks ago”
- Los commits de las ultimas 2 semanas
- git log Makefile
- Todos los commits que modificaron el archivo Makefile
- git log fs/
- Commits que modificaron cualquier archivos bajo el directorio fs
- git log -S’foo()’
- Commits que agregaron o borraron datos conteniendo el string ‘foo()’
- git log -no-merges
- No mostrar commits de merges
- git log v2.5.. Makefile fs/
- Se pueden combinar consultas
- git log -p –since=”yesterday”
- la opcion -p Muestra patches (diffs)
- git log –stat
- Similar a svn log -v
- git log –pretty=online –date-order –graph –reverse
- Formato solo una linea, en modo grafico (ASCII representando branches) ordenado por fecha, y en forma descendente. Existen muchas opciones para –pretty, como raw y short
Diferencias – git diff
El comando git diff es muy util para ver cambios antes de commitear, o para ver diferencias entre distintas ramas o versiones.
- git diff
- Cambios en el directorio de trabajo actual, que todavia no han sido marcados para guardar en el siguiente commit
- git diff –cached
- ¿ Que archivos han sido marcados para guardar en el siguiente commit ?
- git diff master..test
- Diferenias entre dos ramas
- git diff master…test
- Diferencias desde su rama ancestro comun
- git diff HEAD
- ¿ que estaria commiteando si ejecutara git commit -a ?
- git diff test
- Diferencias entre el directorio de trabajo y la rama test
- git diff HEAD — ./lib
- Limitando la comparacion al subdirectorio lib
- git diff –stat
- Solo imprime archivos, resumido
Dejanos tus comentarios
Bueno, eso es todo por ahora. Por favor, si tienes alguna duda, o quieres sugerir algo, no dudes en dejar tu comentario. Muchas gracias.
este documento ha sido publicado bajo la siguiente licencia: “Verbatim copying and distribution of this entire article are permitted in any medium provided this notice is preserved.”