6 motivos por los que git no es un sistema de backup

Esta es una frase que escucho muy a menudo:

 “Yo tengo backup de mi repositorio git en github”.

Siempre que la escucho acabo teniendo la misma conversación con la persona que la ha dicho. Intento hacerle ver porqué github, bitbucket o cualquier otro servicio de hosting de repositorios no son una copia de seguridad de tu repositorio y cómo en determinadas circunstancias (muy habituales cuando trabajas en equipo) puedes perder información por usarlos para lo que no son.

Esto desde el punto de vista práctico. Si escarbamos un poco, lo normal es que detrás de esta frase se esconda un uso no del todo correcto de git o un desconocimiento de ciertas funcionalidades de la herramienta que espero corregir con este artículo.

En adelante me referiré a tu cuenta de github, bitbucket o cualquier otro sistema de hosting de repositorios git como servidor git.

1- Git es algo más que hacer un commit al final de nuestra jornada

El flujo más básico de uso de git que me he encontrado es el siguiente:

  • Llego a trabajar por la mañana y trabajo
  • Antes de irme hago un commit
  • Después del commit hago un push

Así, tienes en tu servidor git la última versión del código fuente. Si respetas este flujo, efectivamente tienes una copia de la última versión de tu código fuente en tu servidor. Ahora bien, no tienes una copia de tu repositorio, porque el repositorio del servidor al que haces push y el de tu máquina local son diferentes. ¡Por eso haces push!

Este forma de trabajo viola varias de las buenas prácticas de git:

  • No estás haciendo commits atómicos, pequeños y muy a menudo. Lo que significa que no estás pensando en cómo gestionar tu código sino en guardar la última versión en un “cajón de sastre” que es tu servidor
  • No estás trabajando con ramas locales para desarrollar funcionalidad
  • Probablemente, no tienes definido ningún flujo de trabajo que te permita gestionar cambios de contexto a la hora de trabajar

2- No estás guardando una copia de tus ramas locales

Las ramas locales, son eso, ramas locales. Las usas para muchas cosas, entre ellas para hacer pruebas, hacer refactorings del código o desarrollar funcionalidades en paralelo. Al no hacer push, de estas ramas, no tienes copia de los commits en tu servidor git.

Sé lo que estás pensando, basta con hacer push de todas las ramas y ya está. Bien, eso es correcto si estás tu solo con tu repositorio. Ahora bien, si estás trabajando en equipo y todos vosotros compartís el mismo repositorio git, la cosa cambia ¿Te imaginas a 5 personas todas subiendo sus ramas de prueba al servidor git para tener copia de seguridad? El caos está garantizado si no se organiza todo muy, muy, muy bien.

3- No estás guardando una copia del reflog

El reflog es un fichero de log que está en la carpeta .git de tu repositorio local donde se guarda un log de todos los cambios de referencias que ocurren en tu repositorio. Cada vez que cambias de rama, haces un merge, un rebase, un pull o un cherry-pick (entre otros) se guarda en el reflog lo que ha pasado.

Este fichero es el que te permite dar marcha atrás cuando la lías parda. Échale un vistazo a este hangout para un ejemplo sobre cómo se usa.

Tu reflog no está en tu servidor git. El servidor git tiene su propio reflog que no tiene porqué coincidir con el tuyo. De nuevo, si estás tu solo y haces push de todas tus ramas, el reflog del servidor se parecerá mucho al tuyo. Eso sí, en caso de desastre, tendrás que entrar al servidor a verlo o copiartelo a tu máquina local… oh, vaya, espera, que estás trabajando con github / bitbucket y no te dejan entrar a sus servidores a descargarte el reflog, desde luego qué tíos perros ¿no?.

Si estás trabajando en equipo, el reflog del servidor tiene todas las modificaciones de referencias hechas por tí y el resto del equipo. ¡Intentar encontrar algo en ese reflog es garantía de diversión durante horas!

4- No tienes backup de los hooks de tu repositorio git

Dentro de la carpeta .git/hooks de tu repositorio puedes poner hooks. Estos hooks no son más que scripts que se ejecutan antes o después de los comandos git y que te permiten interceptar la ejecución para hacer “cosas”. Por ejemplo, el ‘pre-commit’ te permite manipular dinámicamente el mensaje del commit que se genera por defecto.

Cualquier hook que hayas puesto en tu máquina local en la carpeta .git/hooks, no tiene copia de seguridad en tu servidor git.

5- No tienes backup de tu configuración local

Dentro de tu repositorio tienes un fichero con la configuración local de tu repositorio: .git/config. En este fichero puedes guardar varias cosas, entre ellas el nombre y correo electrónico del autor de los commits, alisas de comandos de esos molones que te has bajado de internet y, en general, opciones de configuración específicas de ese repositorio en esa máquina.

Este fichero tampoco se sube a tu servidor git, así que en caso de desastre, lo pierdes y tienes que volver a generar la configuración del repositorio.

6- git permite sobreescribir la historia de tu repositorio

Si trabajas con más gente, en tu repositorio no vas a estar hurgando solo tú. Tendrás código de otras personas, harás merges o pull requests. Hay alguien que puede estar tocando el repositorio detrás de tí así que entre el momento que ocurre el desastre y “recuperas” el repositorio haciendo un clon, muchas cosas pueden haber cambiado.

Ponte en esta situación: te vas de vacaciones mientras tus compañeros trabajan en el repositorio. A la vuelta tu disco duro ha muerto, o durante el viaje te roban el portátil, así que clonas de nuevo el repositorio y te pones a trabajar… Lo que vas a clonar no es lo que tenías antes de irte, el repositorio contendrá todos los cambios que tus compañeros han hecho en tu ausencia.

Me dirás: “tío, no tienes ni idea. Una vez clonado hago un reset al commit de antes de irme de vacaciones y ya está”… Y yo te digo ¿Y no sabes que tus compañeros del alma pueden haberse cargado esos commits con un rebase, por ejemplo?. Recuerda: git, a diferencia de mercurial, permite sobreescribir la historia del repositorio así que ¡¡nada te garantiza que cuando vuelvas de tus vacaciones los commits sigan ahí!!

Conclusión

Según la wikipedia:

a backup, or the process of backing up, refers to the copying and archiving of 
computer data so it may be used to restore the original after a data loss event.

Si pierdes tu disco duro, y recuperas un repositorio haciendo un nuevo clon, no estás recuperando el repositorio como lo tenías antes del desastre así que según esta definición, no es una copia de seguridad. Además ¿Tú crees que Linus Torvalds hizo git para esto? ¿Para hacer backup? ¡eso ya lo tenía con los ficheros tar con los que empezó! Si solo lo usas para hacer copias de respaldo te estás perdiendo muchas cosas.

Git no es un sistema de copia de seguridad de nuestro código. Ahora bien, si se dan estas condiciones:

  1. Estás trabajando tú solo
  2. Haces push de todos los commits al repositorio remoto
  3. Todas las ramas que creas son remotas
  4. Tienes un repositorio que llamas scripts_y_configuracion en el que guardas los hooks, alias, pro-tips y configuraciones personalizadas de tus repositorios.

y eres consciente de lo que estás haciendo, puedes utilizar github como un backup (parcial) de tu código fuente, no de tu repositorio.

De igual manera, si trabajas en equipo y cada integrante tiene su propio repositorio, cada uno de vosotros podría usar git de esta manera. Aunque es un flujo muy básico que sirve para empezar a trabajar, no lo recomiendo en casi ningún caso: en seguida se te queda corto.

En mi caso particular, TimeMachine me ha salvado ya en varias ocasiones de problemas, ahorrándome mucho tiempo y trabajo. Aquí tienes mi consejo: usa una herramienta de backups para hacer backups y una herramienta de gestión de código para gestionar código.

7 pensamientos en “6 motivos por los que git no es un sistema de backup

  1. Roy

    Git nunca sera un sistema de backup para el codigo, ni se acerca a ello porque de hecho sus cientos de archivos contenidos dentro de .git suelen corromperse ocasionalmente cuando se trabaja con discos duros magneticos. Yo uso Genie Timelime Pro en windows, es el unico que me gusto para hacer una copia del codigo fuente en tiempo real, lo configuras con el directorio de tu proyecto en git y te olvidas que existe, cuando algo sale mal el buen amigo Genie salta al rescate.

    Tambien uso Macrium Reflect para obtener una copia diaria de toda la carpeta del proyecto. Por si al disco duro se le ocurre la idea de pactar con satanas y pasar a mejor vida.

    Por cierto, como se resuelve esto? uso git-flow para un proyecto,
    He creado un feature “ie7-css”
    He modificado index.php, config.php y estilos.css
    He hecho commit.
    La tarea no salio bien y deseo dejar revertir todos los cambios hechos en estilos.css, solamente este archivo, el resto de archivos si deseo juntarlo a la rama de desarrollo.
    Busque por internet y mi problema aparentemente simple se complico, a los 20 segundos me aburri, cambie de rama copy -> paste. Me quedo la duda de como se hace en git.

    Responder
    1. admin

      Hola Roy:

      La solución a tu problema la tienes en el comando git-revert:


      git-revert - Revert some existing commits

      Los pasos a dar serían:

      • Localizas el commit que tiene los cambios (por ejemplo 1234acb)
      • Ejecutas: git-revert -n 1234abc La opción -n hace que no se genere un commit al hacer revert.
      • Desechas las modificaciones de los cambios de los ficheros index.php y config.php
      • Haces el commit de estilos.css

      ¡y ya está!

      Responder
      1. Roy

        Complicadoooo! Deberia ser obligatorio el uso de git-flow, la comprension de las ramas y una estrategia de backup para trabajar con git. SourceTree trae por defecto git-flow pero es mas importante el concepto en si.

        Git es un cuento muy hermoso, te va contando que cambios hiciste en el codigo, es una mejor forma de trabajo en programación.

        Git tambien tiene sus cosas raras y cripticas, como mi problema simple pero estupidamente complicado con git. Yo encontre dos soluciones:
        – git checkout develop (abri el archivo estilos.css -> Ctrl+C )
        – git checkout feature/ie7-css(abri el archivo estilos.css -> Ctrl+V )
        Simple y sin misterio alguno. Ahora una solucion mas simple todavia
        – Guardo el codigo “master” en el servidor, pues solo me conecte por “FTP” y reemplaze el archivo estilos.css.

        Responder
        1. admin

          Si tenías que sobreescribir el fichero completo, bastaba con hacer un checkout de la versión del fichero antes de que lo tocases (el que tienes en la rama master) y luego hacer un commit. Si te estoy entendiendo bien, no hacía falta ni siquiera hacer un copy/paste.

          Responder
    2. admin

      …y por cierto, gracias por compartir los programas que usas para hacer backup, no los conocía.

      Alfonso

      Responder
  2. Pingback: Calidad Software: Gestión de artefactos ... y otras especies - Panel Sistemas Informáticos, compañía española de desarrollo de software, servicios de calidad software y outsourcing TI.

  3. Pingback: Calidad Software: Gestión de artefactos ... y otras especies - Panel Sistemas

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *