Tutorial sobre Git

Advertencia previa.

Estas notas son mis apuntes personales sobre uso de Git y tienen como finalidad primordial servirme de recordatorio de métodos que me han funcionado. Si te resultan de alguna utilidad, estupendo. Pero, como todas las cosas que encontramos en Internet, es necesario usarlas con prudencia y buen juicio. Soy un usuario, no un experto en Git. Los programas cambian, los enlaces se rompen y el comando que hace un tiempo era inocuo hoy puede sembrar el caos. Ten cuidado y en caso de duda pregunta a alguien de confianza.

Instalación bajo Windows (Mac y Linux son similares)

  1. Descargar el instalador desde http://git-scm.com/.
  2. Arrancar la instalación.
  3. Se pueden ir aceptando todas las opciones por defecto, pero:
    • en la pantalla Select Components, bajo el epígrafe Windows Explorer Integration yo prefiero elegir Simple Context Menu, para no sobrecargar mis sufridos menús contextuales de Windows.
    • en la pantalla Adjusting your PATH environment yo prefiero dejarlo en Use Git from Git Bash only, par ano sobrecargar mi sufrido PATH de Windows.
      El resto lo dejo como aparece en las opciones por defecto. Una descripción reciente (hoy es 2014-12-08) del proceso aparece en https://confluence.atlassian.com/display/BITBUCKET/Set+up+Git.

Establecer la configuración global de usuario.

Esta es la información de usuario que usarán por defecto tus repositorios.

git config --global user.name nombreUsuario
git config --global user.email correo.usuario@whatever.com

En la Sección Crear un repositorio directamente en local se muestra la forma de modificar esta información para un repositorio concreto.

Ver la configuración global.

Para comprobar esa configuración global podemos usar:

git config --global

En Mac y Linux esta configuración se guarda en el fichero (oculto) .git de nuestra carpeta de usuario.

Crear alias para comandos útiles (opcional).

git config --global alias.s "status -s"
git config --global alias.lg "log --oneline --all --graph  --decorate"

Una vez creados estos alias, los comandos se pueden invocar simplemente haciendo:

git s

o

git lg

respectivamente.

Ajustar el salto de línea.

Es muy importante hacer esto para colaborar con gente que usa un sistema operativo diferente del nuestro.

En Windows:

 git config --global core.autocrlf true

En Linux o Mac:

 git config --global core.autocrlf input

Clonar uno de tus repositorios desde Github.

  1. Abrir un terminal en el directorio local elegido para el repo.

  2. Comprobar que git está en el Path.

  3. Ejecutar

     git clone direccion_http_repositorio  

    Esa dirección se obtiene de Github. Pedirá usuario y password y se sincroniza.

  4. Con esto tenemos una copia local de nuestro repositorio. Como el repositorio es nuestro podemos hacer cambios en él y sincronizarlos con GitHub. Ver las instrucciones en el apartado Hacer cambios y sincronizarlos.

Hacer un fork de un repositorio de GitHub, creado por otro usuario.

  1. Entrar en tu cuenta de GitHub.
  2. Buscar el repositorio que vamos a bifurcar (fork), creado por otro usuario.
  3. Pulsa en el botón fork de ese repositorio: Botón fork Con esto crearás un fork de ese repositorio en tu cuenta de GitHub.
  4. Ahora puedes clonar tu repositorio bifurcado para empezar a trabajar en él. Como es tuyo, puedes sincronizarlo con GitHub. El repositorio original (de otro usuario), naturalmente, no se ve afectado.
  5. Ahora puedes hacer cambios y luego sincronizarlos.

Crear un repositorio directamente en local y sincronizarlo con GitHub.

  1. Cambiar al directorio del repositorio.

  2. Abrir un terminal Git BASH:

  3. Ejecutar

     git init  
  4. Se puede usar este comando para chequear:

     git status   
  5. Añadir algún archivo. Por ejemplo un README.md se puede crear con

     touch README.md  
  6. Ejecutar

     git add .  

    o aún mejor

     git add README.md
  7. Si no se quiere usar la información global de usuario, configurar el correo de este repo con:

     git config user.email "correo.usuario@whatever.com"
  8. Y el nombre de usuario (del repo) con:

      git config user.name "nombreUsuario"   

    Tienen que coincidir con los de GitHub si se va a sincronizar. Y se puede usar la opción –global para hacerlos globales para todos los repos (cuidado si tienes varias cuentas en GitHub).

  9. Ejecutar

     git commit -a -m "Initial commit"

    o el mensaje inicial que se desee.
    Actualización: algunos autores opinan que git commit -a (o git add .) es una mala idea, porque de esa forma se incluyen en el commit (staged for commit) los cambios ocurridos en todos los ficheros que Git sigue (tracked files). Y es posible que algunos de esos cambios no reflejen la modificación planificada en el proyecto que debe representar un commit. Así que es preferible hacer un git add previo seleccionando explícitamente los ficheros que queremos incluir en el commit.

  10. Ahora:

     git remote add origin https://github.com/nombreUsuario/nombreRepo.git
  11. Crear en GitHub un directorio con el mismo nombre. Y no crear nada en él, ni un readme.

  12. Ejecutar:

     git push origin master  

    Pedirá usuario y clave y se sincronizará.

Ver el remote de un repositorio local.

git remote -v

Ver información más completa de un repositorio local.

git config --list

Eliminar un remote

git remote -v
git remote rm nombreDelRemote

donde nombre del remote es a menudo origin

Hacer cambios en el directorio local y sincronizarlos con nuestra copia en Github.

  1. Tras cambiar algo en un fichero, hacemos:

     git status  
     git add .  
  2. Ahora el comit. Ejecutar:

     git commit -a -m "Added some code file..."   
  3. Y el push:

     git push origin master  

    Pedirá usuario y clave y se sincronizará.

Para sincronizar la copia local con un directorio clonado desde Github.

  1. Ejecutar

     git pull

Para sincronizar la copia local con el repositorio primario de Github del que hemos hecho un fork.

Ejecutamos uno tras otro estos comandos. Atención, no se usa nuestro repo sino el primario del que hicimos el fork:

git remote add upstream https://github.com/nombreUsuarioPrimario/nombreRepoPrimario.git

git fetch upstream

git checkout master

git merge upstream/master

Usando ficheros gitignore.

Los ficheros (ocultos) .gitignore son ficheros de texto que se utilizan para decirle a Git cuáles son los ficheros que no queremos que incluya en el repositorio. A menudo el desarrollo del código produce ficheros auxiliares o demasiado voluminosos, etc., que preferimos mantener fuera del control de versiones de Git.

La documentación oficial sobre este tipo de ficheros está aquí.

La librería gitignore de R ayuda a construir este tipo de ficheros para diferentes tipos de proyectos.

Crear una rama gh-pages en GitHub:

La utilidad de esto es para crear páginas web de nuestro repositorio directamente en GitHub, usándolo como un servicio de hosting web básico para el proyecto.

  1. Primero vamos a GitHub y crearemos un repositorio llamado nombreusuario.gitub.io, que nos puede servir para luego, colgando de él, albergar todos los repositorios tipo gh-pages de este usuario (hay otras formas de trabajar, pero a mi esta me resulta la más sencilla por el momento). Creo que no es necesario mantener copia local de este repo.

  2. Ahora vamos a trabajar en un proyecto concreto. Creamos, en la carpeta que queramos, un repositorio local en el que vamos a albergar las páginas asociadas. Voy a llamarlo RepoPages como referencia. Usamos para esto y para sincronizarlo con GitHub las instrucciones que aparecen más arriba en “Crear un repositorio directamente en local y sincronizarlo con GitHub.”

  3. Una vez creado y sincronizado, ejecutamos:

     git branch gh-pages  

    para crear la rama gh-pages del repositorio y después

     git checkout gh-pages  

    para cambiar el repo local a esa rama.

  4. Para sincronizar, hacemos:

     git push origin gh-pages
  5. En GitHub vamos a usar el menú desplegable branch para cambiar a esa rama gh-pages.

  6. Ya está listo para trabajar. Cada vez que creamos o modificamos ficheros en el repositorio local y queremos sincronizar hacemos el ciclo de comandos:

     git add .  
     git commit -a -m "A nice message here..."
     git push origin gh-pages  
  7. Si tenemos un fichero html, por ejemplo index.html en nuestro repositorio, para verlo en la web escribimos la dirección nombreUsuario.github.io/RepoPages/index.html y lo visualizaremos como html.

Deshacer un git add antes de ejecutar commit.

Para esto basta con hacer:

git reset

Autenticando en GitHub con ssh.

2015-11-11: Lo que sigue es una adaptación de la información que aparece en:
Referencia: Multiple SSH Keys settings for different github account.

Vamos a ver como utilizar ssh para autenticar nuestras cuentas en GitHub, con la ventaja de no tener que teclear la clave de cada cuenta cada vez que hacemos un cambio. Todos los comandos que aparecen aquí se ejecutan en un terminal (bash), salvo las modificaciones de ficheros, que se hacen en un editor de texto.

Voy a explicar los pasos necesarios para trabajar con dos cuentas. Es fácil adaptar estas instrucciones, ya sea simplifcandolas para trabajar con una sola cuenta o extendiéndolas para trabajar con más de dos.

Además, al final veremos cómo configurar el acceso desde varios equipos, usando las mismas claves en, por ejemplo, el ordenador de casa y el del trabajo.

  1. Preparación: Se supone que hemos creado dos cuentas en GitHub, con nombres de usuario usuario1 y usuario2 respectivamente. En lo que sigue voy a suponer que los correos de ambos usuarios son correo.usuario1@whatever.com y correo.usuario2@whatever.com.
    Además, para cada una de ellas hemos creado un repositorio (repo1 y repo2) siguiendo los pasos del 1 al 6 y el paso 8 del procedimiento que se describen en este mismo documento en el apartado Crear un repositorio directamente en local y sincronizarlo con GitHub. ¡Pero todavía no haremos ni el paso 7 de configuración git remote ni el paso 9 de sincronización, que allí se hacía a través de http! En el paso 8 de ese procedimiento es esencial introducir correctamente la información de cada uno de los usuarios.

  2. Una vez hecho esto vamos a crear las claves ssh de cada una de las cuentas. Para ello usaremos el programa ssh-keygen que debe estar disponible en nuestro terminal. Como preparación puedes leer la ayuda oficial de GitHub sobre claves ssh. Pero ten en cuenta que para usar varios usuarios vamos a hacer algunos cambios con respecto a ese documento.
    El programa ssk-keygen crea dos ficheros relacionados con la clave ssh del ususario1. Uno (sin extensión) es la clave privada que bajo ningún concepto debemos hacer pública o compartir con nadie y otro es la clave pública, que compartiremos con sitios como GitHub (más abajo vermeos cómo) para identificarnos. Por esa razón, lo primero que necesitamos es crear un directorio en el que almacenar esa clave. El siguiente comando crea un directorio .ssh (los directorios ocultos en sistemas Unix, como los Mac o Linux, tienen nombres que empiezan por punto) en la carpeta del usuario1. Ese es el nombre estándar del directorio de almacenamiento de claves:

    cd
    mkdir ".ssh"

    El primer comando cd nos sitúa en nuestro directorio personal. Como hemos dicho es necesario que la carpeta sea privada.
    Para crear la clave ssh del primer usuario hacemos esto:

    ssh-keygen -t rsa -b 4096 -C "correo.usuario1@whatever.com"

    Al ejecutarlo el resultado será parecido al que se muestra a continuación. Es importante leer las observaciones que aparecen más abajo antes de ejecutar el comando:

    $ ssh-keygen -t rsa -b 4096 -C "usuario1@whatever.com"
    Generating public/private rsa key pair.
    Enter file in which to save the key (/c/Users/usuario1/.ssh/id_rsa): .ssh/usuario1
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in .ssh/usuario1.
    Your public key has been saved in .ssh/usuario1.pub.
    The key fingerprint is:
    SHA256:8kPryi4lCDihAK2Y/mD5KCu5xIwg3AP1p58MPqOFLIo usuario1@whatever.com
    The key's randomart image is:
    +---[RSA 4096]----+
    |o. .             |
    |o o .            |
    |==   . .         |
    |X o   o          |
    |++.+ o. S        |
    |*=o = =+..       |
    |o*=o B ++        |
    |B..o+.o. .       |
    |Eo . o+..        |
    +----[SHA256]-----+

    Comentarios:

  • Lo primero que ssh-keygen nos pedirá es el nombre que vamos a usar para el fichero de clave, incluyendo en el nombre la carpeta donde se va a guardar. El nombre es arbitrario, pero debemos tomar nota porque ese nombre nos va a servir para identificar después a cada uno de los usuarios. Como puedes ver (en la tercera línea) yo he usado usuario1 para ese fichero y la he situado en el directorio .ssh que hemos creado antes.

  • A continuación keygen-ssh nos pide una contraseña para asociarla con esa clave ssh. Es muy conveniente incluir una contraseña fuerte para proteger el uso de esa clave. Más adelante veremos como conseguir que el uso de la clave no nos obligue a teclear cada vez esta contraseña. Naturalmente, debes guardar esta contraseña de forma segura, con las mismas precauciones que usarías, por ejemplo, para tu cuenta de correo personal.

  • ssh-keygen nos proporciona dos formas de identificar la clave fácilmente. Una cadena de caracteres, llamada fingerprint, que en el ejemplo anterior es:

    SHA256:8kPryi4lCDihAK2Y/mD5KCu5xIwg3AP1p58MPqOFLIo usuario1@whatever.com

    y una “imagen”, llamada randomart image. Es buena práctica copiar y guardar como referencia tanto el fingerprint como la randomart image en algún lugar en el que puedas localizarlos fácilmente. Como veremos más adelante, GitHub usa el fingerprint para ayudarnos a identificar cada clave ssh de forma sencilla. Antes de continuar, haz lo mismo con el otro usuario:

    ssh-keygen -t rsa -b 4096 -C "correo.usuario2@whatever.com"

    para generar en la carpeta .ssh los dos ficheros usuario2 y usuario2.pub que contienen las claves privada y pública respectivamente de este segundo usuario. Acuérdate de elegir y anotar un password fuerte y de anotar también el fingerprint y la randomart image para esta clave ssh.

  1. Como hemos dicho, queremos evitar tener que teclear contraseñas cada vez. Así que vamos a usar otro programa llamado ssh-add para autorizar de forma permanente. En Windows este paso resulta más complicado y más abajo detallaré las instrucciones necesarias en ese sistema operativo. En sistemas Unix (o en Windows tras esos preparativos) hay que empezar por establecer correctamente los permisos del directorio .config, ejecutando en el terminal:

    chmod 600 ~/.ssh/config

    (Ver este enlace como referencia), Una vez hecho esto basta con ejecutar:

    ssh-add.exe ~/.ssh/usuario1

    y cuando el programa nos lo pida introducir la contraseña que elegimos al crear esa clave ssh. Al hacer esto, un programa llamado ssh-agent, que en sistemas Unix arranca automáticamente al inicio de sesión, se encargará en adelante de gestionar por nosotros esa clave ssh. Por cierto, gracias al ssh-agent ahora podemos recuperar fácilmente el fingerprint de las claves ssh que hemos registrado con ssh-add. Basta con usar:

    ssh-add -l

    Si la clave no está registrada, mira este enlace.
    Para el segundo usuario habrá que ejecutar, de forma análoga:

    ssh-add.exe ~/.ssh/usuario2

    Preliminares en Windows:

    En el terminal bash de Windows el programa ssh-agent no arranca automáticamente. Para conseguir que lo haga debemos hacer modificaciones en un fichero de configuración de ese terminal situado en nuestra carpeta de ususario y llamado .profile. Así que los pasos son estos (a) cerrar el terminal (b) si aún no existe, es necesario crear ese fichero .profile en la carpeta de usuario (c) abrimos el fichero en un editor de texto y añadimos estas líneas (tomadas del sitio web de GitHub):

    # Note: ~/.ssh/environment should not be used, as it
    #       already has a different purpose in SSH.
    
    env=~/.ssh/agent.env
    
    # Note: Don't bother checking SSH_AGENT_PID. It's not used
    #       by SSH itself, and it might even be incorrect
    #       (for example, when using agent-forwarding over SSH).
    
    agent_is_running() {
        if [ "$SSH_AUTH_SOCK" ]; then
            # ssh-add returns:
            #   0 = agent running, has keys
            #   1 = agent running, no keys
            #   2 = agent not running
            ssh-add -l >/dev/null 2>&1 || [ $? -eq 1 ]
        else
            false
        fi
    }
    
    agent_has_keys() {
        ssh-add -l >/dev/null 2>&1
    }
    
    agent_load_env() {
        . "$env" >/dev/null
    }
    
    agent_start() {
        (umask 077; ssh-agent >"$env")
        . "$env" >/dev/null
    }
    
    if ! agent_is_running; then
        agent_load_env
    fi
    
    # if your keys are not stored in ~/.ssh/id_rsa or ~/.ssh/id_dsa, you'll need
    # to paste the proper path after ssh-add
    if ! agent_is_running; then
        agent_start
        ssh-add
    elif ! agent_has_keys; then
        ssh-add
    fi
    
    unset env

    Una vez hecho esto, volvemos a abrir el terminal (la primera vez es posible que aparezca un mensaje de error que debería desaparecer en usos posteriores) y procedemos como en el caso Unix (explicado más arriba).

  2. Cuando Git utilice ssh para autenticarnos en GitHub tiene que saber cuál de esas claves ssh elegir, dependiendo del usuario asociado al repositorio en cuestión. Podemos proporcionarle esa información a Git en un fichero llamado config situado en el directorio oculto .ssh que hemos visto en el paso 2. Si ese fichero no existe debemos crearlo y añadir estas líneas:

    host cuenta1
      Hostname github.com
      User git
        IdentityFile ~/.ssh/usuario1
        IdentitiesOnly yes

    Hay que hacer lo mismo con el otro usuario, así que antes de cerrar el fichero config añade un segundo bloque de líneas:

    host cuenta2
      Hostname github.com
      User git
      IdentityFile ~/.ssh/usuario2
     IdentitiesOnly yes

    Para cada usuario añadiremos un nuevo bloque con los cambios pertinentes. Guarda el fichero config al acabar.

  3. Con los pasos previos hemos completado la “parte ssh” de este método. En este y los siguientes pasos vamos a trabajar la parte que tiene que ver directamente con Git y GitHub. Para empezar vamos a nuestra cuenta de GitHub (asegúrate de que entras como usuario1) y hacemos click en el menú de usuario (esquina de arriba a la derecha), el triángulo situado junto al icono del usuario abre ese menú desplegable de usuario. Seleccionamos settings y en la nueva ventana elegimos, en la columna de la izquierda, SSH keys. El botón add SSH keys nos abrirá una interfaz en la que en el cuadro Title podemos elegir un nombre cualquiera para la clave (el nombre debería ser informativo, pero es arbitrario). Después, en el cuadro de texto key debemos copiar todo el contenido del fichero de clave pública usuario1.pub que hemos creado en el paso 2. CUIDADO: debemos copiar el contenido completo del fichero de extensión pub, nunca el del fichero sin extensión usuario1 de la misma carpeta, que contiene la clave ssh privada de ese usuario. De esta forma GitHub dispondrá de la información necesaria sobre la clave ssh de ese usuario. Naturalmente, deberemos repetir estos mismos pasos para el segundo usuario.

  4. Ya casi hemos acabado. Recuerda que en el paso 1 hemos creado un repositorio local repo1 y hemos preparado para sincronizar un repositorio del mismo nombre en Github, que de momento está vacío. Ahora tenemos que configurar ese repositorio de GitHub como remoto para nuestro repositorio local. Y tenemos que hacerlo de forma que Git sepa cuál es la clave de ese usuario. Para eso se va a usar la información que hemos añadido al fichero config dentro de la carpeta .ssh del paso 2. Ejecutamos:

    git remote add origin git@usuario1:usuario1/repo1.git

    En este comando el primer usuario1 sirve para identificar la clave ssh del fichero config, mientras que el bloque usuario1/repo1.git sirve para que GitHub sepa con cuál de los repositorios que alberga queremos conectar. Así que para adpatarlo a tus propios usuarios y repositorios tienes que modificar esta línea.
    Finalmente, podremos sincronizar con:

    git push origin master

    Hacemos lo mismo para el otro usuario, cambiando primero a la carpeta local que contiene el repositorio repo2:

    git remote add origin git@usuario2:usuario2/repo1.git
    git push origin master

    A partir de ahí la sincronización debería ocurrir siempre automáticamente sin necesidad de introducir ningún password adicional.

Trasladando la configuración de las claves ssh a otro equipo.

Si utilizas un segundo equipo para trabajar puedes seguir estos pasos para trasladar tu configuración a ese equipo:

  1. Comprueba si existe el directorio .ssh en tu carpeta de usuario. Si no existe créalo.

  2. Copia los ficheros de clave (públicas y privadas) a ese directorio.

  3. Ejecuta el paso 3 de la sección anterior en el nuevo equipo para registras las claves con ssh-agent. Si el nuevo equipo usa Windows presta especial atención al apartado Preliminares en Windows

  4. El fichero config del directorio ssh debe contener los bloques correspondientes a las claves ssh de cada usuario, tal como se ha descrito en el paso 4 de la anterior sección. Si el fichero config no existe hay que crearlo previamente, claro está.

  5. Podemos empezar a trabajar en este equipo. Para comprobar que todo funciona bien puedes ejecutar estos comandos:

    ssh -T git@usuario1
    ssh -T git@usuario2

    En ambos casos debes recibir un mensaje de confirmación de GitHub como este (para el usuario1):

    Hi usuario1! You've successfully authenticated, but
    GitHub does not provide shell access.

    Si quieres reanudar tu trabajo en este equipo puedes empezar clonando uno de tus repositorios desde GitHub. Por ejemplo, para clonar repo1 cambia a la carpeta en la que quieres situar la subcarpeta repo1 (no hace falta crear esa subcarpeta repo1, la clonación se encargará) y ejecuta:

    git clone git@usuario1:usuario1/repo1.git

    Cuando la clonación acabe te faltará aún un detalle: tienes que configurar el usuario y correo de este repositorio clonado, como se explica aquí en los puntos 7 y 8, para poder empezar a hacer commits desde este equipo.

Fernando San Segundo
Fernando San Segundo
Profesor Colaborador Asociado - Doctor

My research interests include Applied Mathematics, Data Analysis, Scientific Computation and Mathematical Modelling.