Git básico (en desarrollo)

Introducción

Git es un sistema de control de versiones distribuido con el que podemos guardar el histórico de cambios realizados en nuestro código o ficheros en general.

Se puede entender Git como un árbol en el que cada nodo guarda el estado de nuestro repositorio en un momento dado. Cada nodo del árbol corresponde a cada commit realizado en el repositorio.

Los commit se identifican mediante un id de la forma 071befca5eef8b8703ad259a409774b5cedb1e20. Para referirnos a un commit concreto normalmente sólo será necesario los primeros caracteres de su id, por ejemplo, 071befc.

En el árbol pueden haber distintas ramas, es decir, a partir de un commit podemos avanzar en el árbol por varios caminos diferentes. Cada rama tiene un nombre, y a la rama principal se le suele llamar master. El último commit de cada rama tiene una etiqueta con el nombre de la rama, por tanto, podemos utilizar el nombre de la rama (en lugar del id del commit) para recuperar el estado del último commit de una rama concreta.

Existe una etiqueta especial llamada HEAD, la cual hace referencia al último commit de la rama actual. Además, a cada commit se le puede asignar una etiqueta particular, por ejemplo para identificar en qué commit se cierra una versión concreta de nuestro código.

  • Imagen árbol con ramas

Creación de un repositorio

En Git existen dos tipo de repositorios: repositorios de trabajo y repositorios bare. El primero es el repositorio local donde tenemos nuestra copia de trabajo y el segundo es el repositorio central que se utiliza exclusivamente para la sincronización entre los distintos colaboradores del proyecto. El repositorio central (bare) normalmente está ubicado en una máquina remota accesible por todos los colaboradores, por ejemplo podemos utilizar github o bitbucket para alojar estos repositorios. Además de punto de centralización del código, también hace la función de copia de respaldo.

  • Para crear un repositorio de trabajo:
$ git init <directory>
  • Para crear un repositorio bare:
$ git init --bare <directory>

Para los repositorios bare se suele utilizar la extensión .git en el nombre del repositorio para diferenciarlo de las copias de trabajo.

Ejemplo: Crear un repositorio bare, crear un repositorio de trabajo y asociarle como repositorio central el repositorio bare creado.

$ git init --bare myproject.git
$ git init myproject
$ cd myproject
$ git remote
add origin path/to/myproject.git

Al repositorio central se le suele dar el nombre origin. Una opción más sencilla para crear un repositorio a partir de uno ya existente es hacer un clone.

  • Para hacer un clone:
$ git clone <repo> <directory>

Ejemplo: Clonar el repositorio myproject.git creado previamente.

$ git clone path/to/myproject.git myproject

Al realizar el clone, el nuevo repositorio ya tendrá asociado como repositorio remoto origin el repositorio original que se ha clonado.

Configuración

Antes de hacer el primer commit es importante haber configurado git para que los cambios que hagamos queden registrados con nuestros datos. Todas las configuraciones de Git se pueden establecer a nivel de repositorio, de usuario o de sistema. Entre los datos que podemos configurar están el nombre de usuario, email, editor por defecto para los commits, etc.

Para cada uno de los niveles de configuración existe un fichero particular:

  • .git/config : para la configuración en un repositorio concreto.
  • ~/.gitconfig : para la configuración a nivel de usuario.
  • $(prefix)/etc/gitconfig: para la configuración a nivel de sistema.

Estos ficheros se pueden editar para modificar los parámetros de configuración, pero también podemos utilizar directamente el comando config.

  • Para establecer el nombre de usuario:
$ git config user.name <name>
  • Para establecer el email:
$ git config user.email <email>
  • Para establecer el editor predeterminado:
$ git config core.editor <editor>
  • Para crear un alias de un comando git:
$ git config alias.<alias-name> <git-command>

Ejemplo: Establecer el nombre del usuario, email, vim como editor y el alias co para el comando checkout.

$ git config user.name "José Iván López"
$ git config user
.email "joseivanlopez@gmail.com"
$ git config core
.editor "vim"
$ git config
alias.co checkout

Para establecer la configuración a nivel de usuario se utiliza el flag –global, y para hacerlo a nivel de sistema el flag –system.

Ejemplo: Configurar el nombre de usuario y email a nivel de usuario para no tener que configurarlo en cada uno de nuestros repositorios.

$ git config --global user.name "José Iván López"
$ git config
--global user.email "joseivanlopez@gmail.com"

También se puede utilizar el comando config para editar manualmente el fichero de configuración con el editor predeterminado. Para ello se utiliza el flag –edit.

Ejemplo: Editar el fichero de configuración a nivel de sistema.

$ git config --system --edit

Registrar cambios

Para registrar el estado actual de un repositorio, y por tanto, todos los nuevos cambios realizados desde la última versión registrada, se utilizan los comandos add y commit.

El comando add se emplea para indicar qué cambios de todos los existentes queremos registrar, y el comando commit es quien registra todos esos cambios indicados. Para los ficheros nuevos es necesario realizar un add para añadirlo al repositorio.

  • Para indicar cambios a registrar:
# Para añadir un fichero o todos los cambios en un fichero.
$ git
add <file>
# Para añadir todos los cambios en un directorio.
$ git
add <directory>
# Para añadir cambios en modo interactivo.
$ git
add -p
  • Para crear un commit con la instantánea actual:
$ git commit
$ git commit
-m "<message>"
# Para crear commit con todos los cambios en ese momento.
$ git commit
-a

Para registrar un commit es conveniente revisar previamente qué cambios hemos realizado. Para ello se utiliza el comando status, el cual nos indica los ficheros modificados, los nuevos y los eliminados. Git utiliza un área especial llamada staging area donde va agrupando los cambios que hemos indicado con add que queremos registrar. El comando status informa también del contenido actual del staging area.

Ejemplo: Crear un fichero, ver el estado del repositorio, añadir el fichero a Git y hacer un commit.

$ echo "line 1" > file1.txt
$ git status
$ git
add file1.txt
$ git commit
-m "Added file1.txt"

Para que Git no tenga en cuenta determinados ficheros y por tanto no se muestren con el comando status, se puede crear un fichero .gitignore que contenga las rutas de los ficheros a ignorar.

Eliminar cambios

  • Eliminar un commit concreto (no pueden haber cambios pendientes en el directorio de trabajo):
$ git stash
$ git rebase
-i <commit>
# En el editor eliminar la línea correspondiente al commit.
$ git stash pop
  • Eliminar hasta un commit concreto (sin perder cambios pendientes en el directorio de trabajo ni cambios en commits eliminados):
$ git reset --soft <commit>
  • Eliminar hasta un commit concreto (se pierden cambios pendientes en el directorio de trabajo pero no los cambios de los commits eliminados):
$ git reset <commit>
  • Eliminar hasta un commit concreto (se pierden cambios pendientes en el directorio de trabajo y los cambios de los commits eliminados):
$ git reset --hard <commit>
  • Eliminar cambios del staging area (pero del directorio de trabajo):
$ git reset
# Para eliminar sólo los cambios de un fichero concreto.
$ git reset
<file>
  • Eliminar cambios en el directorio de trabajo:
$ git reset --hard
# Para eliminar sólo los cambios de un fichero concreto.
$ git reset
--hard <file>
  • Eliminar un fichero:
$ git rm <file>
# Para conservar el fichero en el directorio de trabajo.
$ git rm
--cached <file>

El fichero eliminado siempre se conserva en los commits anteriores al commit donde fue eliminado.