Git (I)

Lectura de ~10 minutos

Seguimos con la serie de repositorios. Anteriormente expliqué que son los sistemas de trabajo colaborativo. En el artículo de hoy explicaré una extendida herramienta que se usa para llevar a cabo un control del trabajo que se está realizando. La herramienta es ni más ni menos que Git. Lo que voy a explicar no es más pero sí un poco menos lo que aparece en el libro Pro Git. Empezemos.

Fundamentos.

Vamos a ver como trabaja git.

Cada vez que se confirma un cambio, Git no realiza una copia diferencial de los archivos modificados, realiza copias de los archivos modificados y guarda una referencia a esa copia. De forma que la vida del proyecto es una sucesión de copias.

Una gran ventaja de Git es que la grandísima mayoría de las operaciones se realizan de forma local. De modo que si por alguna razón te quedas sin conexión puedes seguir trabajando en tu proyecto.

Si tienes miedo de que al usar Git se pierda la integridad de tus ficheros, quitate esa idea de la cabeza. Git guarda un hash en formato SHA-1 para cada cambio que se realiza. De este modo al transferir ficheros no hay forma de que se corrompa un fichero sin que Git lo detecte.

En Git existen tres tipos de estados para un fichero.

  1. Modificado: el fichero se ha modificado y está pendiente de confirmar.
  2. Preparado: el fichero está preparado para la siguiente confirmación.
  3. Confirmado: el fichero ya está en la copia de Git. Un fichero que se encuentre en copia es muy difícil de perder.

La forma de trabajo es justamente el descrito, primero se modifica el fichero, se prepara y finalmente se confirma.

Forma de uso.

Todo esto está muy bien, pero… ¿Cómo se usa? Git es una aplicación de línea de comandos. También hay aplicaciones con interfaz gráfica, pero en la línea de comandos es el lugar dónde se pueden ejecutar todos los comandos.

Si quieres instalarlo puedes encontrar la forma de instalarlo aquí.

Una vez instalado se debería configurar al menos dos parámetros. Una vez configurados nos podemos casi olvidar de ellos.

Antes de configurar debemos saber como funciona la configuración de Git. Hay tres niveles de configuración:

  1. Configuración a nivel de sistema.
  2. Configuración a nivel de usuario.
  3. Confguración a nivel de proyecto.

De forma que la útlima configuración es la que se tiene en cuenta, es decir, si tenemos alguna configuración a nivel de usuario y otra a nivel de sistema, Git tendrá en cuenta la configuración de nivel de usuario.

Los dos parámetros que se deben configurar para poder usar Git son el nombre de usuario y el correo electrónico. Esta configuración se suele hacer a nivel de usuario. La forma de hacerlo es la siguiente:

Nombre de usuario

$ git config --global user.name "Pepe Olivares"

Correo electrónico

$ git config --global user.mail pepeolivares@dominio.com

También es importante configurar el editor de texto que usas. Git lo usará para pedirte que introduzcas mensajes.

git config --global core.editor emacs

Si quieres ver tu configuración no tienes más que ejecutar el siguiente comando:

$ git config --list

Si tienes dudas sobre algún comando puedes consultarlo en la línea de comandos:

$ git help <comando>
$ git <comando> --help
$ man git-<comando>

Primeros comandos (empezando a gatear)

Existen dos modos de obtener un repositorio Git, importar desde un directorio existente o clonarlo desde un servidor.

  1. Para importarlo no hay más que ejecutar el siguiente comando en el directorio del proyecto:
    $ git init
    

    Este comando crea el directorio .git y ya tenemos el repositorio listo para usar en forma local.

  2. Si de otro modo lo que queremos hacer es clonarlo desde un servidor debemos ejecutar el siguiente comando:
    $ git clone <url>
    

    Este comando crea un directorio con el nombre del proyecto creando también el directorio .git.

Ahora ya estamos listos para trabajar en el proyecto pero ¿cómo se hace?

Hemos explicado anteriormente los estados en los que pueden estar los ficheros según Git. Para verlos tenemos que ejecutar el siguiente comando:

$ git status

Si ejecutamos este comando justo después de importar o clonar la salida será como la siguiente:

$ git status
On branch master
nothing to commit, working directory clean

En cambio, si por ejemplo, creamos el fichero hola.txt y volvemos a ejecutar el comanto anterior, obtendremos la siguiente salida:

$git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

  hola.txt.

nothing added to commit but intracked files present (use "git add" to track)

Como se puede observar, nos indica que el fichero hola.txt está sin modificado pero no preparado para confirmación. Para prepararlo para la confirmación tenemos que ejecutar el siguiente comando:

$ git add hola.txt

Y si volvemos a ejecutar el comando para comprobar el estado:

$git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  new file: hola.txt

Si confirmamos los cambios en este punto, Git guardará el estado del proyecto en el momento que se ejecutó el comando git add.

Si modificamos el archivo hola.txt después de confirmar los cambios y volvemos a comprobar el estado, aparecerá lo siguiente:

$git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

  modified: hola.txt

En este caso Git nos indica que el fichero hola.txt ha sido modificado desde la última confirmación pero que no se ha preparado para la confirmación.

Para preparar de nuevo el fichero hola.txt debemos ejecutar de nuevo el comando git add. El comando git add sirve tanto para añadir nuevos ficheros que no están siendo rastreados como para añadir los cambios de un fichero.

Por defecto, Git nos indica los cambios de todos y absolutamente todos los ficheros que cambiamos. Este comportamiento lo podemos variar si no queremos que tenga en cuenta algún fichero o incluso algún directorio. Suele ser el caso de los ficheros auto-generados por compiladores. Estos ficheros y directorios se deben especificar en el fichero .gitignore que se encuentra en el directorio raíz del proyecto. Los ficheros se especifican de forma similar a las expresiones regulares, de modo que si añadimos *.obj, Git ignorará todos los ficheros que acaben en .obj. Si indicamos por ejemplo build/, se ignorarán todos los ficheros del directorio build.

Con git status podemos ver los ficheros que han cambiado, pero si quieres ver los cambios realizados en el fichero tienes que ejecutar el comando git diff:

$ git diff
diff --git a/hola.txt
b/hola.txt
index eujj3s1..583hf934 12091
--- a/hola.txt
+++ b/hola.txt
@@ +Hola Git.

Si deseas ver la diferencia de lo que hay preparado y lo que hay incluido en la próxima confirmación se utiliza el comando git diff --staged

Para confirmar los cambios que ya tenemos preparados se utiliza el comando siguiente:

$ git commit

Al ejecutarlo se abrirá el editor que se haya configurado tal y como se ha mencionado anteriormente para introducir el mensaje de confirmación. Si queremos hacerlo directamente en el comando sin tener que abrir un editor, se puede hacer con el siguiente comando:

$ git commit -m "Añadir hola.txt"
[master fe943d0] Añadir hola.txt
1 file changed, 1 insertion(+)
create mode 124568 hola.txt

Si quieres saltarte el área de preparación solo tienes que añadir el parámetro -a cuando haces commit, ej:

$ git commit -a -m "Corrección hola.txt"
[master fj490fj] Corrección hola.txt
1 file changed, 1 insertion(+), 1 deletion(-)

Cuidado con este comando, añade automáticamente todos los ficheros modificados al estado preparado para luego confirmarlos. Debemos estar totalmente seguros que queremos confirmar todos los ficheros.

Si no vamos a necesitar un archivo y lo vamos a eliminar hay dos formas de hacerlo:

  1. Eliminar el archivo del área de preparación y luego confirmar el cambio.
  2. Utilizar el comando git rm, que ademas elimina el archivo del disco:
$ git rm hola.txt
rm 'hola.txt'
$ git status
On branch masterChanges to be committed:
  (use "git reset HEAD <file>..." to unstage)

  deleted: hola.txt

Si confirmamos en este punto, el archivo habrá sido eliminado y Git no volverá a mostrarlo.

Si olvidaste añadir el fichero en .gitignore y lo has confirmado por accidente, puedes eliminarlo sólamente del área de preparación con el siguiente comando:

$ git rm --cached hola.txt

Si lo que quieres es cambiar el nombre a un fichero, se puede hacer con el siguiente comando:

$ git mv hola.txt modificado.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  renamed: hola.txt -> modificado.txt

Para ver el historial de confirmaciones de un proyecto tenemos que ejecutar el comando siguiente:

$ git log
commit
5jf94j59rjgfo9rk409rkg0fj404itrjf04kr0fg
Author: Pepe Olivares <pepe@olivares.com>
Date: Mon Mar 17 21.52.11 2008 -0700

  Corrección hola.txt

Si no se le pasa ningún parámetro a git log, por defecto mostrará los cambios más recientes a los más antiguos. Si queremos ver las diferencias introducidas en cada confirmación, se pueden ver con el parámetro -p. Si no queremos ver todas las entradas del log, y solo las dos últimas por ejemplo se haría con el parámetro -2. Por otro lado si queremos ver los cambios que se han introducido para una función en específico, podemos hacerlos con el comando siguiente:

$git log -Snombre_funcion

Si has olvidado agregar algún archivo en la preparación o te has equivocado el en mensaje de última confirmación y has confirmado los cambios, puedes corregirlo con el siguiente comando:

git commit --amend

Si has preparado un archivo por error y quieres quitarlo del área de preparación puedes hacerlo con el siguiente comando:

$ git reset HEAD hola.txt
Unstaged changes after reset:
M     hola.txt

Si no quieres mantener los cambios de un fichero y quieres volver a la versión anterior de confirmación lo puedes hacer con el siguiente comando:

$ git checkout -- hola.txt

Git además de permitirte gestionar un proyecto de forma local te permite gestionar proyectos remotos. Primero debemos saber que proyectos remotos tenemos configurados, para ello debemos ejecutar el siguiente comando:

$ git remote
origin

Git utiliza el nombre origin por defecto para el proyecto remoto. Si quieres ver las URL asociadas al nombre debes ejecutar el siguiente comando:

$ git remote -v
origin https://github.com/repositorio
(fetch)
origin https://github.com/repositorio
(push)

Si hay más de un servidor se listarán con su nombre y su URL. Un mismo proyecto puede traer cambios de cada uno de los distintos servidores listados en el comando anterior. Pero para poder enviar datos puede que necesitemos de algún permiso adicional.

Si quieres añadir un repositorio remoto y aplicarle un nombre lo puedes hacer con el siguiente comando:

$ git remote add rem https://github.com/otrorepositorio

De forma que se puede usar este repositorio remoto además de los que hubieran en el proyecto para traer cambios. Para traer cambios se puede hacer con el comando siguiente:

$ git fetch rem

Este comando trae los cambios del servidor remoto pero no los aplica en tu trabajo ni lo combina, para ello debes ejecutar el comando siguiente:

$ git pull rem

Si lo que quieres es enviar tus cambios al servidor tienes que ejecutar el comando:

$ git push rem

Este comando envía todas las confirmaciones que no se encuentren en el servidor.

Si quieres ver a que URL apuntan tus remotos puedes hacerlo con el comando:

$ git remote show

Cuando ya no necesites rastrear más un remoto lo puedes eliminar con el comando:

$ git remote rm <nombre-remoto>

O si en su lugar quieres renombrar el remoto lo puedes hacer con el comando:

$ git remote rename <nombre-origen> <nombre-destino>

Es posible que quieras marcar un momento especifico de tu repositorio, sobretodo para marcar una versión que se va a publicar. Hay dos tipos de etiquetas en Git

  1. Etiqueta ligera: es como una rama pero que nunca cambia. Básicamente un puntero a un commit en espécifico. Para crear una etiqueta de este tipo ejecuta el comando:
    $ git tag <nombre-etiqueta>
    
  2. Etiqueta anotada: Git guarda el objeto entero. Para crear una etiqueta de este tipo ejecuta el comando:
    $ git tag -a <nombre-etiqueta> -m '<mensaje de la etiqueta>'
    

Si quieres ver las etiquetas creadas ejecuta el comando:

$ git tag
v0.1
v0.2

Si ha pasado tiempo desde el commit que quieres etiquetar lo puedes hacer especificando el checsum del commit específico:

$ git tag -a v1.2 48rhf94

Por defecto Git no comparte las etiquetas al hacer push. Si quieres compartir una etiqueta en servidor remoto lo puedes hacer con el comando:

$ git push origin v1.5

O si quieres compartir todas las etiquetas lo puedes hacer con el comando:

$ git push origin --tags

Si quieres ir a una etiqueta en específico, se debe hacer creando una rama para ir al commit en questión:

$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'

Ya estás listo para usar Git a nivel básico con estos comandos.

Nos vemos en las próximas líneas.

Escrito el 26/05/2017