¿Has visto esos ficheros .gitkeep que Ruby on Rails crea cuando generas un proyecto nuevo? ¿por qué están ahí? Git sólo gestiona ficheros, no carpetas. Esto es así por la forma en la que el índice (o staging area) de git se ha diseñado: sencillamente no lo permite. Tal y como se dice en la FAQ, nadie lo suficientemente competente se ha ocupado de implementar el soporte para carpetas. Aún así, nos encontraremos con que en muchas ocasiones nos vendría muy bien poder añadir carpetas vacías al repositorio.
¿Porqué carpetas vacías?
Hay muchas herramientas, aplicaciones y frameworks que requieren de la existencia de ciertas carpetas para funcionar. Un ejemplo: tanto Symfony como Ruby on Rails necesitan disponer de directorios en los que almacenar cachés y logs. El contenido de estas carpetas se ignora siempre del repositorio; son archivos locales que sólo tienen sentido en cada copia local ¿pará que queremos distribuir a nuestros compañeros de trabajo los archivos de log creados por nuestro portátil mientras estamos desarrollando la aplicación? Es un derroche inútil de recursos y una fuente de conflictos que nos quitará mucho tiempo y no nos aportará nada.
El problema que se deriva de esto es que si ignoramos toda la carpeta completa utilizando un patrón de este tipo:
#Ignorando cache y log cache/ log/
cuando otra persona clone el repositorio esas carpetas no se crearán. A no ser que las cree manualmente, la aplicación no funcionará.
La solución es decirle a git que cree las carpetas cuando clone el repositorio y luego que ignore su contenido. ¿Cómo se hace? creamos un fichero vacío dentro de la carpeta, lo añadimos al repositorio y le decimos a git que ignore el resto de archivos que están dentro. Esto se puede hacer de dos maneras:
- A través de un fichero .gitkeep
- A través de un fichero .gitignore
.gitkeep
Lo primero que debemos tener claro es que el uso del fichero .gitkeep es un convenio. En ningún lugar de la documentación de git veréis que se haga referencia a este fichero. De hecho, si no os gusta el nombre nada os impide cambiarlo y usar cualquier otro.
Veamos cómo usar este fichero:
- Antes de añadir al fichero .gitignore el patrón que ignore la carpeta cache, creamos el fichero cache/.gitkeep, bien usando el comando touch o con nuestro editor de texto o entorno de desarrollo.
# touch cache/.gitkeep
- Una vez creado el fichero lo añadimos al repositorio y hacemos el commit:
# git add cache/.gitkeep # git commit -m'Añadiendo el fichero cache/.gitkeep
- Editamos el fichero .gitignore (o lo creamos si no existe) y añadimos el patrón para ignorar la carpeta cache:
# Ignorando los ficheros de la carpeta cache/ cache/
- Hacemos commit del fichero .gitignore
Ya está, la próxima vez que alguien cree el repositorio, se creará el fichero cache/.gitkeep a la vez que se ignora cualquier otro fichero que esté en la carpeta cache/.
Esta técnica utiliza la siguiente característica de git: si un fichero ya está en el índice (es decir, git ya está haciendo seguimiento de las modificaciones de ese fichero) a pesar de que el .gitignore lo ignore, git lo seguirá monitorizando.
Utilizar un fichero .gitignore
El método anterior tiene una pega: tenemos patrones para ignorar ficheros que requieren que tengamos varias excepciones en el índice de git (cache/.gitkeep, log/.gitkeep, etc). No hay problema con ello, aunque si no os gusta podemos utilizar otra de las características de git para no tener excepciones en el índice: utilizar un fichero .gitignore dentro de la carpeta que queremos ignorar.
- Crear el fichero cache/.gitignore con los siguientes patrones
# Ignorar todos los ficheros... * # ...excepto el fichero .gitignore !.gitignore
- Añadir el fichero cache/.gitignore al repositorio y hacer un commit
Si repetís esta operación con las carpetas cuyos ficheros queráis ignorar, no tendréis necesidad de andar incluyendo excepciones en el índice.
Cualquiera de los dos métodos nos permite tener carpetas «vacías» en el repositorio, aunque vacías, vacías del todo no lo están. ¿Qué método usáis vosotros normalmente? ¡Esperamos vuestros comentarios!
¡Happy gitting!