Añadir a git los ficheros migrate de django en pycharm

Pycharm doesn't love django + git

Si usas el IDE pycharm y django ≥ 1.7 (o < 1.7 con south) y como gestor de versiones usas git, probablemente te ha pasado que haces un commit y se te olvida añadir (git add) los ficheros de las migraciones. Pycharm hace «git add» automáticamente a todos los ficheros creados, salvo a los creados tras hacer un makemigrations. Para saberlo, pycharm nos los muestra en rojo en lugar de en verde.
¿Por qué este comportamiento? Realmente lo desconozco, pero imagino que porque no ha sido una acción hecha directamente por el usuario, sino como consecuencia de un migrate.

A mí me pasa a menudo que hago un commit y luego otro como un comentario «los migrates del anterior commit». Cuando esto no sólo te pasa a ti, sino que es algo común en los demás compañeros empiezas a preguntarte cómo solucionarlo, y ya de paso convertirte en el héroe que evita el 1×2 en los commits. Depende de la manera de trabajar que tengas, el tipo de integración de las ramas que hagas y demás, esto puede serte útil o no, pero nunca está de más probar algo desconocido.

Para ello podemos usar los hooks de git, que son pequeños scripts que se ejecutan cuando ocurre algún evento, como commit, push, receive. Podemos crear un hook de tipo pre-commit, que se ejecutará antes de hacer un commit, para que no nos deje hacer commit si tenemos algún fichero sin añadir.

Los hooks se instalan en la carpeta .git/hooks del repositorio de git que queramos. Cuando inicializamos un repositorio ya nos crea el directorio con algunos ejemplos.

De acuerdo con la respuesta correcta de este hilo de stackoverflow, podemos crear meter el siguiente código en el fichero pre-commit hook:

ud=`git status -u | grep '^Untracked files:$'`
 
if [ -n "$ud" ];
then 
    cat < <EOF 
¡Cuidado! Hay ficheros que no se han añadido al repositorio
EOF
    exit 1
fi

Este script lo único que hace es ver si al ejecutar git status -u existe la frase ‘Untracked files’. Si es así nos avisa con un bonito texto y no efectúa el commit. De esta manera nos dará un aviso antes de efectuar el commit y podremos subsanarlo sin tener que añadir posteriormente un commit separado.

Si aún así queremos dejar ficheros sin subir, podemos usar git commit --no-verify para que no ejecute el hook.

Más sobre git hooks:

http://git-scm.com/book/es/v2/Customizing-Git-Git-Hooks
http://githooks.com/
https://www.atlassian.com/git/tutorials/git-hooks/