Chapitre 2. Astuces de base

Plutôt que de plonger dans l’océan des commandes Git, utilisez ces commandes élémentaires pour commencer en vous trempant les pieds. Malgré leur simplicité, chacune d’elles est utile. En effet, lors de mon premier mois d’utilisation de Git, je ne me suis jamais aventuré au-delà de ce qui est exposé dans ce chapitre.

Enregistrer l'état courant

Vous êtes sur le point d’effectuer une opération drastique ? Avant de le faire, réalisez une capture de tous les fichiers du dossier courant :

$ git init
$ git add .
$ git commit -m "Ma première sauvegarde"

Si jamais votre opération tourne mal, vous pouvez retrouver votre version initiale, immaculée :

$ git reset --hard

Pour enregistrer un nouvel état :

$ git commit -a -m "Une autre sauvegarde"

Ajouter, supprimer, renommer

Les commandes ci-dessus ne font que garder traces des fichiers qui étaient présents lorsque vous avez executé git add pour la première fois. Si vous ajoutez de nouveaux fichiers ou sous-dossiers, il faut le signaler à Git :

$ git add readme.txt Documentation

De même, si vous voulez que Git oublie certains fichiers :

$ git rm kludge.h obsolete.c
$ git rm -r incriminating/evidence/

Git supprime les fichiers pour vous si vous ne l’avez pas encore fait.

Renommer un fichier revient à supprimer l’ancien nom et ajouter le nouveau. Il y a également le raccourci git mv qui a la même syntaxe que la commande mv. Par exemple :

$ git mv bug.c feature.c

Annuler/Reprendre avancé

Parfois vous voulez seulement revenir en arrière et oublier les modifications effectuées depuis un certain temps parce qu’elles sont toutes fausses. Dans ce cas :

$ git log

vous montre une liste des commits récents, accompagnés de leur empreinte SHA1 :

commit 766f9881690d240ba334153047649b8b8f11c664
Author: Bob <bob@example.com>
Date: Tue Mar 14 01:59:26 2000 -0800

    Remplacement de prinf() par write()

commit 82f5ea346a2e651544956a8653c0f58dc151275c
Author: Alice <alice@example.com>
Date:   Thu Jan 1 00:00:00 1970 +0000

    Commit initial

Les premiers caractères de l’empreinte sont suffisants pour spécifier un commit ; ou alors, copiez et collez l’empreinte en entier. Saisissez :

$ git reset --hard 766f

pour restaurer l'état correspondant au commit donné et supprimer de manière permanente tous les commits plus récents de l’enregistrement.

Parfois vous ne voulez faire qu’un bref saut dans un état précédent. Dans ce cas, saisissez :

$ git checkout 82f5

Ceci vous ramène en arrière dans le temps, tout en conservant les commits récents. Toutefois, comme pour le voyage temporel de la science-fiction, si vous faites des modifications suivies d’un commit, vous entrerez dans une réalité parallèle puisque vos actions sont différentes de ce qu’elles étaient la première fois.

Cette réalité parallèle est appelée une branche (branch), et nous en dirons plus après. Pour le moment rappelez-vous simplement que :

$ git checkout master

vous ramènera dans le présent. De plus, pour éviter que Git se plaigne, réalisez toujours un commit ou un reset de vos modifications avant de faire un checkout.

Pour reprendre l’analogie du jeu vidéo :

  • git reset --hard : recharge une ancienne sauvegarde et supprime toutes les sauvegardes plus récentes.
  • git checkout : recharge une ancienne partie, mais si vous jouez avec, l'état de la partie va différer des enregistrement suivants que vous aviez réalisés la première fois. Chaque nouvelle sauvegarde sera sur une branche séparée représentant la réalité parallèle dans laquelle vous êtes entré. On s’en occupe plus loin.

Vous pouvez choisir de ne restaurer que certains fichiers et sous-dossiers en les nommant à la suite de la commande :

$ git checkout 82f5 un.fichier un-autre.fichier

Faites attention car cette forme de checkout peut écraser vos fichiers sans avertissement. Pour éviter les accidents, faites un commit avant toute commande checkout, surtout quand vous débutez avec Git. En général, quand vous n'êtes pas sûr des conséquences d’une opération, et pas seulement des commandes Git, faites d’abord un git commit -a.

Vous n’aimez pas copier et coller les empreintes ? Alors utilisez :

$ git checkout :/"Ma première s"

pour arriver sur le commit qui commence avec ce message. Vous pouvez aussi demander la cinquième sauvegarde en arrière :

$ git checkout master~5

Reprise (revert)

Dans une cour de justice, certains évènements peuvent être effacés du procès verbal. De même vous pouvez sélectionner des commits spécifiques à défaire :

$ git commit -a
$ git revert 1b6d

défera le dernier commit ayant cette empreinte. La reprise est enregistrée comme un nouveau commit, ce que vous pourrez constater en lançant un git log.

Génération du journal des modifications (changelog)

Certains projets demandent un changelog. Créez-le en tapant :

$ git log > ChangeLog

Télécharger des fichiers

Faites une copie d’un projet géré par Git en saisissant :

$ git clone git://serveur/chemin/vers/les/fichiers

Par exemple, pour récupérer les fichiers utilisés pour créer ce site :

$ git clone git://git.or.cz/gitmagic.git

Nous aurons beaucoup à dire sur la commande clone d’ici peu.

Le dernier cri

Si vous avez déjà téléchargé une copie d’un projet en utilisant git clone, vous pouvez la mettre à jour vers la dernière version avec :

$ git pull

Publication instantanée

Imaginez que vous avez écrit un script que vous voudriez partager avec d’autres. Vous pourriez leur dire de le télécharger de votre ordinateur, mais s’ils le font au moment où vous êtes en train d’améliorer le script ou d’y effectuer des modifications expérimentales, ils peuvent se retrouver dans la panade. Bien sûr, c’est pour cela qu’on a créé la publication de versions successives. Les développeurs peuvent travailler sur un projet fréquemment, mais ils ne rendent le code disponible quand lorsqu’ils le trouvent présentable.

Pour faire ça avec Git, dans le dossier qui contient votre script :

$ git init
$ git add .
$ git commit -m "Première publication"

Ensuite vous pouvez dire à vos utilisateurs de lancer :

$ git clone votre.ordinateur:/chemin/vers/le/script

pour télécharger votre script. En considérant qu’ils ont accès à votre ordinateur via ssh. Sinon, lancez git daemon et dites plutôt à vos utilisateurs de lancer :

$ git clone git://votre.ordinateur/chemin/vers/le/script

À partir de maintenant, chaque fois que votre script est prêt à être publié, exécutez :

$ git commit -a -m "Nouvelle version"

et vos utilisateurs peuvent mettre à jour leur version en allant dans leur dossier contenant votre script et en saisissant :

$ git pull

Vos utilisateurs ne se retrouveront jamais avec une version de votre script que vous ne vouliez pas leur montrer.

Qu’ai-je fait ?

Retrouvez les modifications faites depuis le dernier commit avec :

$ git diff

Ou depuis hier :

$ git diff "@{yesterday}"

Ou entre une version spécifique et la version deux commits en arrière :

$ git diff 1b6d "master~2"

Dans chacun de ces cas, la sortie est un patch (rustine) qui peut être appliqué en utilisant git apply. Vous pouvez aussi essayer :

$ git whatchanged --since="2 weeks ago"

Souvent je parcours plutôt l’historique avec qgit, pour sa pimpante interface photogénique, ou tig, une interface en mode texte qui fonctionne même sur les connexions lentes. Autrement, installez un serveur web, lancez git instaweb et dégainez n’importe quel navigateur internet.

Exercice

Soit A, B, C, D quatre commits successifs où B est identique à A à l’exception de quelques fichiers qui ont été supprimés. Nous voudrions remettre les fichiers en D. Comment faire ?

Il y a au moins trois solutions. En considérant que nous sommes à D :

  1. La différence entre A et B sont les fichiers supprimés. Nous pouvons créer un patch représentant cette différence et l’appliquer :

    $ git diff B A | git apply
    
  2. Vu que nous avions enregistré les fichiers en A, nous pouvons les reprendre :

    $ git checkout A foo.c bar.h
    
  3. Nous pouvons aussi voir le chemin de A à B comme une modification à défaire :

    $ git revert B
    

Quel est le meilleur choix ? Celui que vous préférez. C’est facile d’obtenir ce que vous voulez avec Git, et souvent il y a plein de manières de le faire.