Git stash: perdre du code, c’est possible
20 janvier 2015 Laisser un commentaire
Parfois on pense naïvement que certains logiciels sont vraiment sûrs. C’est faux et on l’a vu avec OpenSSL (heartbleed, etc), une librairie critique. A présent c’est à git de me décevoir, célèbre logiciel de gestion de source.
Le bug est simple, vos fichiers sont perdus, un comble pour un logiciel de versioning de fichiers. La commande en question est git stash à utiliser when you want to record the current state of the working directory and the index, but want to go back to a clean working directory).
Après un git pull foireux, je me dis que je vais stasher mon code. ERREUR, car j’étais dans un cas particulier où git stash détruit magnifiquement les fichiers sans avertissement. Voici la procédure de reproduction du bug:
$ git --version git version 2.2.1 $ mkdir test $ cd test $ git init Dépôt Git vide initialisé $ # création d'un fichier nommé "important" $ echo "initial" > important $ cat important initial $ git add . $ git commit -m "init" [master (commit racine) 2847f2d] init 1 file changed, 1 insertion(+) create mode 100644 important $ # puis soudain, erreur de logique humaine, un fichier se transforme en dossier $ rm important $ mkdir important $ # creation d'un fichier woot.txt dans important $ echo "super important" > important/woot.txt $ cat important/woot.txt super important $ # le temps passe et un jour... git stash $ git stash Saved working directory and index state WIP on master: 2847f2d init HEAD est maintenant à 2847f2d init $ git st Sur la branche master rien à valider, la copie de travail est propre $ # ensuite on restaure nos données $ git stash pop Suppression de important Sur la branche master Modifications qui ne seront pas validées : (utilisez "git add/rm ..." pour mettre à jour ce qui sera validé) (utilisez "git checkout -- ..." pour annuler les modifications dans la copie de travail) supprimé : important aucune modification n'a été ajoutée à la validation (utilisez "git add" ou "git commit -a") refs/stash@{0} supprimé (9dcc39966175d918f30bb21bfbe11c9e6e8ab5ca) $ # et BIM, tout a disparu $ ls -a . .. .git
Le dossier important n’existe plus, il n’était d’ailleurs pas versionné. A noter que git stash -u ne change rien sur la perte de données:
$ mkdir test02 $ cd test02 $ git init $ echo "initial" > important $ git add . $ git commit -m "init" $ rm important $ mkdir important $ echo "super important" > important/woot.txt $ git st $ git stash -u $ git stash pop $ ls -a . .. .git important $ cat important initial
Évidemment, c’est totalement con de transformer un fichier en dossier. Sauf dans le cas d’un lien symbolique vers un dossier qui se transforme en un vrai dossier, exemple:
$ mkdir test02 $ cd test02 $ git init $ mkdir dir1 $ ln -s dir1 dir2 $ echo "initial" > dir1/important $ git add . $ git commit -m "init" $ unlink dir2 $ mkdir dir2 $ echo "super important" > dir2/woot.txt $ git st $ git stash $ git stash pop $ ls -a $ . .. dir1 .git
La logique humaine est incompréhensible sur le pourquoi du comment on se retrouve dans ce cas, au point de se dire que c’est à cause d’une mauvaise utilisation, mais je ne pense pas, un logiciel de gestion de version se doit de gérer tous les cas, mais surtout il se doit impérativement d’informer l’utilisateur en cas de perte de données possible.
Dans mon cas personnel, c’était un dossier « test », avec heureusement presque rien dedans. Sur un repository de longue date, on oublie facilement qu’un lien symbolique a été transformé en dossier, et on fait confiance au stash qui est censé tout sauvegarder (sauf les untracked, sauf si c’est demandé, dans ce cas comme on a vu, le untracked ne restaure pas les bons fichiers ensuite).
C’est un cas que je qualifierai de très exceptionnel, mais il est arrivé. Perdre des données c’est possible. J’ai quand même cherché pour savoir si j’étais tout seul, mais il semblerait que non, avec TortoiseGit, dont la conclusion est:
I’m able to reproduce this with git version 1.7.10.msysgit.1 as well as on Linux, so please report this upstream to the git mailing list. Thank you.
Même si le cas ne semble pas trop identique (cela concerne des fichiers ignorés), le problème est le même: perte de données. Moi qui utilisait git stash très souvent avec une grande confiance, à présent un backup du working directory sera effectué pour éviter toutes mésaventures sur du vrai code.
Cela me rappelle la fiabilité de linux avec cet article, où au lieu de couper/coller des fichiers, je devais, suite à un bug, copier/coller puis supprimer une fois que tout était bon pour éviter la perte de données… rebelote avec git, faire un backup avant de lancer une commande de « backup »… ahahaha, mais c’est vraiment triste pour linux en fait.