La gestion de versions avec Git, un DVCS (Distributed Version Control System)

Fonctionnement de base

Ce chapitre part de zero et aborde tous les aspects d'une utilisation basique de Git.

Qu'est-ce qu'un dépôt ? Un dépôt est un dossier qui contient les fichiers que l'on souhaite versionner. En général, un dépôt = un dossier = un projet. A la racine d'un dépôt se trouve systématiquement un dossier .git qui contient la configuration du dépôt ainsi que tout l'historique (méta données). Le nom du dossier du dépôt n'est pas important, il peut être changé et le dossier peut être déplacé.

Pour interagir avec un dépôt il faut se trouver dans le dossier du dépôt, peu importe le niveau de profondeur, et utiliser la commande "git" suivie de paramètres et options. Par exemple, la commande "git log" affiche l'historique des versions d'un dépôt :

cd mon_depot.git
git log

Comment obtenir la documentation interne ? Toutes les commandes Git sont documentées et accessible avec la commande "git help" :

>git help log

NAME
       git-log - Show commit logs

SYNOPSIS
       git log [<options>] [<revision range>] [[--] <path>...]

DESCRIPTION
       Shows the commit logs.

       The command takes options applicable to the git rev-list command to control what is shown and how, and options applicable to the git diff-* commands to control how the changes each commit introduces
       are shown.

OPTIONS
       --follow
           Continue listing the history of a file beyond renames (works only for a single file).
...

Configuration basique (nom, email, editeur de texte)

Le fichier de configuration global de Git se touve ici : ~/.gitconfig . Il contient tous les paramètres qui seront appliqués à l'utilisateur quel que soit le dépôt manipulé.

On peut éditer ce fichier à la main ou bien utiliser des commandes Git pour le remplir plus facilement. Il est obligatoire de configurer un nom et une adresse mail pour utiliser Git. Ces informations seront utilisées pour nommer l'auteur de chaque version du dépôt.

Voici les commandes pour définir le nom et l'email :

git config --global user.name "Robert Lecodeur"
git config --global user.email robertcodeur@robertmail.fr

Cette option très pratique permet d'avoir de la couleur dans quasiment tous les résultats de commandes Git :

git config --global color.ui true

Il est aussi très utile de configurer l'éditeur de texte qui va être lancé par Git pour demander des descriptions de versions par exemple :

git config --global core.editor gedit

Ce qui nous donne un fichier de configuration de Git comme celui là :

[user]
    name = Robert Lecodeur
    email = robertcodeur@robertmail.fr
[color]
    ui = true
[core]
    editor = gedit

Avant de commencer, petite introduction théorique

Nous allons donner ici un petit aperçu global du fonctionnement et des concepts de Git. Toutes ces informations seront abordées plus en détail par la suite.

Du point de vue de Git, un projet est un dépôt. Un dépôt est matérialisé par un dossier contenant les fichiers du projet ainsi que l'historique et la configuration du dépôt.

Dans un dépôt, les modifications sont matérialisées par des commits. Un commit est l'assemblage des informations suivantes :

  • un identifiant de commit (hash)
  • un auteur
  • un ensemble de modifications sur des fichiers (diffs)
  • un commit parent

La notion de parenté est essentielle pour la compréhension et l'utilisation de Git. Dans l'historique d'un dépôt, on trouve donc un arbre de commits puisqu'ils sont tous liés les uns aux autre par un lien de parenté. Quand on travaille avec Git, à un instant T, on se trouve toujours à l'intérieur d'une branche, même s'il n'en existe qu'une seule.

Techniquement, une branche est un pointeur vers un commit qui permet de naviguer en arrière dans l'arbre des commits à partir de ce pointeur. De manière plus imagée, on peut décrire une branche comme une partie indépendante de l'historique.

Le pointeur vers la branche courante est appelé HEAD.

Quand on effectue un commit, celui-ci vient se placer à la suite de l'historique existant.

Quand on ajoute des commits à une branche et que ceux-ci n'ont pas le HEAD actuel comme parent, l'arbre de commit se divise en deux branches terminales. Git fait alors en sorte de les fusionner pour ne pas se retrouver avec deux HEAD. La fusion se traduit par un commit supplémentaire qui a pour parent tous ceux qui ont divergé. Dans l'image suivante, le commit C6 a été généré par Git au moment de la fusion. On peut appeler ça le commit de merge.

commitmerge

IMPORTANT Dans un premier temps nous ne parlerons que de l'utilisation de Git avec une seule branche dans notre dépôt local. Cette branche s'appelle master par défaut.

Gestion simple en local (init, commit, checkout, .gitignore...)

Comme nous l'avons vu plus tôt, la création et la manipulation de version se fait en local avec un DVCS comme Git. Nous pouvons créer un dépôt, y ajouter des fichiers, faire plusieurs versions, annuler des modifications etc... sans s'adresser à un serveur/dépôt distant.

Créer un dépôt et (dé)versionner des fichiers

Pour créer un dépôt, on se place dans un dossier (vide ou pas) et on lance la commande :

git init

Cela a pour effet de créer un dépôt vide même si des fichiers sont déjà présents dans le dossier. Dans Git, comme dans la plupart des VCS, on sélectionne les fichiers que l'on va suivre. On dira qu'un fichier est versionné ou pas. Pour versionner un fichier, on utilise la commande :

git add mon_fichier

qui a pour effet d'ajouter mon_fichier au dépôt. Après cet ajout, on peut faire directement la première version du dépôt :

git commit -m "première version"

Pour déversionner un fichier, on utilise la commande "git rm".

Voir l état courant du dépôt local

La commande

git status

indique l'état du dépôt local. C'est à dire qu'elle liste les fichiers modifiés/ajoutés/supprimés depuis la dernière version. Elle liste aussi les fichiers non-suivis.

Voila un exemple presque complet de ce qu'elle peut afficher lorsqu'on est entre deux commits :

Sur la branche master

Validation initiale

Modifications qui seront validées :
  (utilisez "git rm --cached <fichier>..." pour désindexer)

        nouveau fichier: fichier.txt

Modifications qui ne seront pas validées :
  (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé)
  (utilisez "git checkout -- <fichier>..." pour annuler les modifications dans la copie de travail)

        modifié:         fichier.txt

Fichiers non suivis:
  (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé)

        fichier_hors_sujet.txt

Créer une version (commit)

Une fois qu'on a effectué une série de modifications sur des fichiers versionnés et qu'on souhaite "officialiser" celles-ci par une nouvelle version, il est temps d'utiliser la fonction "git commit". Il est conseillé de vérifier l'état du dépôt avant de commiter avec la commande "git status".

Les options à connaitre de commit sont :

  • -m : pour définir un message de commit. Si cette option n'est pas définie, Git ouvrira votre éditeur de texte pour vous demander un message de toute façon.
  • -a : pour inclure toutes les modifications courantes à la version créée

La plupart du temps, on précise l'option -a parce qu'on veut inclure toute ses modifications dans le commit.

(Pour plus de détails sur la sélection des modifications à inclure au commit : http://git-scm.com/book/fr/v1/Les-bases-de-Git-Enregistrer-des-modifications-dans-le-dépôt C'est un point qui nécessite éclaircissement qui se transmet mieux à l'oral ou par un graphique.)

Donc un commit ressemble à ça :

git commit -a -m "correction du bug dans la fonction timer du grille pain"

Une fois le commit effectué, git status devrait indiquer quelque chose comme ça :

Sur la branche master
Fichiers non suivis:
  (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé)

        fichier_hors_sujet.txt

aucune modification ajoutée à la validation mais des fichiers non suivis sont présents (utilisez "git add" pour les suivre)

Vous pouvez voir votre dernier commit en détail avec la commande "git show".

Annuler les modifications depuis le dernier commit

Si on a des modifications non commitées que l'on veut annuler, on peut utiliser la commande "git checkout" en lui passant des fichiers en paramètre pour que ces fichiers se trouvent à nouveau dans l'état qu'ils avaient au commit précédent. En bref, on annule les modifications faites depuis le dernier commit.

Par exemple, imaginons que j'ai un fichier toto.txt et que je sois juste après un commit :

>cat toto.txt
je suis le contenu de tot

>echo "nouvelle ligne" >> toto.txt

>cat toto.txt
je suis le contenu de tot
nouvelle ligne

>git checkout toto.txt
>cat toto.txt
je suis le contenu de tot

La commande checkout, quand elle prend pour seul paramètre un fichier ou un dossier, ramène un ou plusieurs fichiers dans l'état du dernier commit.

Les voyages dans temps et l'espace sont plus détaillés dans ce chapitre sur la modification de l'historique.

Visualiser l historique (log, diff, gitk...)

  • La commande "git status" donne un aperçu de l'état actuel du dépôt.

  • À tout moment, on peut voir les modifications apportées aux fichiers versionnés avec la commande "git diff" : diff Cette commande montre un diff pour chaque fichier versionné qui compare l'état au dernier commit et l'état actuel.

  • gitk est un outil graphique très complet de visualisation de l'historique. Il est détaillé dans ce chapitre.

Nous parlerons ici des commandes checkout, reset, revert, amend et du rebase interactif. (parler du fait qu'on puisse faire bcp de commits voire même trop)

Avec Git, on peut se déplacer dans l'historique de version et aussi le modifier. Ces deux actions sont très différentes et n'ont pas la même utilité. On a des tonnes de possibilités, encore faut-il savoir qu'elles existent, quel est notre but et quels sont les effets réels de chaque action. Nous attaquons ici le premier aspect magique des DVCS : la modification de l'historique local.

warning ATTENTION Tout ce qui suit peut être destructif.

warning ATTENTION BIS Si on travaille avec des dépôts distants, il faut bien veiller à ne pas modifier la partie de l'historique qui a déjà été publiée (poussée). Si on le fait, on ne pourra pousser vers les dépôts distants que si on L'ECRASE, ce qui n'est pas très conseillé si d'autres personnes pullent souvent depuis ce dépôt distant...

Nous allons partir des cas simples les plus courants pour aller vers les possibilités avancées en matière de modification de l'historique.

Se déplacer, remettre le dépôt dans un état précédent

La commande "git checkout" peut être utilisée, comme vu précédemment, pour remettre un fichier son état au moment du dernier commit. La signification générale de cette commande peut être résumée à "mettre à jour des fichier pour les mettre dans l'état d'une version ou d'une branche". En fait on peut utiliser cette commande pour faire voyager les fichiers dans le temps. Mais le voyage dans le temps n'est pas sans conséquence...

Si on lui donne en paramètre un identifiant de commit, elle aura pour effet d'amener l'intégralité des fichiers du dépôt dans leur état au moment de ce commit. L'historique n'est pas modifié par cette commande, seulement l'état des fichiers.

Exemple :

git checkout 95aa29b715f22a005fb64f4bba83e9f9597b3814

On se retrouve alors au commit 95aa29b715f22a005fb64f4bba83e9f9597b3814 . Nous sommes donc dans le passé et nous avons créé temporairement un début d'historique parallèle appelé branche.

Si on veut revenir au dernier commit, on pourrait donner l'identifiant du dernier commit à checkout mais on resterait dans cet historique parallèle, cette branche temporaire. Au lieu de ça, on donne à checkout le nom de la branche sur laquelle on veut se retrouver. Dans le cas général, c'est la branche par défaut : la branche master.

git checkout master

Et nous voila tranquillement revenus de notre voyage dans le temps sans avoir touché au passé et donc sans avoir créé d'historique parallèle. On dira plutôt qu'on a détruit cette branche temporaire et qu'on est revenu exactement là d'où on était parti. Ouf.

Si on avait fait des modifications et un commit dans le passé on aurait eu besoin du chapitre sur les branches pour s'en sortir et jongler entre les deux dimensions parallèles.

Modifier le dernier message de commit

Imaginons qu'on ait fait une erreur dans un message de commit et qu'on s'en rende compte immédiatement. Il est possible de corriger celui ci sans plonger dans les profondeurs de Git avec la commande "git commit --amend". Regardez bien :

git commit -a -m "dessin de l'aréoport presque terminé"
git commit --amend -m "dessin de l'aéroport presque terminé"

warning L'option --amend de commit ne modifie pas uniquement le nom du dernier commit : Dans le manuel de la commande "git commit", il est écrit que l'option --amend remplace le TIP (dernier commit de la branche courante) par un nouveau commit contenant le TIP plus les nouvelles modifications non commitées. En bref si on a des modifications non commitées, elles seront inclues dans le commit précédent.

Defaire un commit sans modifier l historique passé (revert)

Parfois, on veut annuler un commit que l'on a effectué mais on ne veut pas modifier l'historique pour ne pas poser de problème de communication avec ses collaborateurs. La solution est alors de produire un nouveau commit qui défait un commit passé. C'est possible avec la commande "git revert". Cette commande nécessite d'être dans un état "propre" c'est à dire de n'avoir aucune modification depuis le dernier commit.

warning Il se peut que la modification que l'on veut annuler concerne des lignes qui ont été modifiées à nouveau depuis par d'autres commit. Le revert va alors provoquer un conflit qui se résout de façon classique avec "git mergetool" ou à la main. Voila ce qu'affiche git si un revert échoue :

>git revert ad068c9c33bfbbcf19ec56bdea8d904e7ad57840
error: impossible d'annuler ad068c9... plop mod 1 line
astuce: après résolution des conflits, marquez les chemins corrigés
astuce: avec 'git add <chemins>' ou 'git rm <chemins>'
astuce: puis validez le résultat avec 'git commit'

Réécrire l historique à partir d un certain commit

Une fonctionnalité un peu plus avancée et plus complexe de Git est celle de "rebaser". Le rebase est une alternative à la fusion (merge) pour intégrer des modifications d'un autre branche. Nous n'aborderons pas cet aspect du rebase.

Ce dont nous allons parler ici est l'utilisation du rebase en mode interactif d'une branche sur elle même qui permet de réécrire progressivement l'historique à partir d'un commit dans le passé.

En bref, le rebase interactif permet de fusionner deux commits successifs, changer les messages de commit, ajouter des fichiers...

Le rebase interactif est utile, par exemple, si on veut nettoyer son arbre de commit quand on a fait trop de petits commits, ou quand on se rend compte qu'on a oublié d'ajouter un fichier plusieurs commits auparavant.

Cette fonctionnalité est décrite en détails ici

Travailler avec des dépôts distants

Ce qui fait de Git un gestionnaire de version distribué est la séparation entre gestion de l'historique et communication des versions. Ce chapitre aborde les bases de la communication entre les dépôts Git.

Nous n'aborderons pas ici l'hébergement de dépôt Git. Nous considérerons que les dépôts distants auxquels nous nous adressons existent déjà.

Git est capable d'utiliser plusieurs protocoles pour accéder à des dépôts distants :

  • file:// : accès au système de fichier local
  • ssh:// : accès par une connexion ssh
  • http:// : web
  • https:// : web+ssl
  • git:// : protocole propre à Git qui est sensé être le plus rapide

Avec Git, on peut récupérer une copie locale d'un dépôt distant, on appelle cela un clone.

Une fois le clone obtenu, on y effectue des modifications, on y ajoute des versions. Il est possible ensuite de pousser (push) ses modifications vers un dépôt distant. Si le dépôt distant a évolué, il est possible de tirer (pull) les nouvelles versions.

Cloner un dépôt

Voila quelques exemples de clonages :

# syntaxe de base (le paramètre 'destination' est facultatif)
git clone origine destination

# en local
git clone file:///home/julien/depots/formation.git
# est équivalent à
git clone /home/julien/depots/formation.git

# en ssh (petite différence de syntaxe, le ':' à la fin du nom de domaine
git clone ssh://julien@hebergeur.univ.fr:/depots/formation.git
# est équivalent à
git clone julien@hebergeur.univ.fr:/depots/formation.git

# en http
git clone https://github.com/utilisateur/formation.git

# en git
git clone git://hebergeur.univ.fr/depots/formation.git

Si on ne précise pas de destination, le clonage va créer le dépôt dans le dossier courant avec le même nom que le dépôt distant.

Le dépôt est directement utilisable après clonage. Un dépôt cloné retient (dans sa configuration locale) l'adresse du dépôt distant duquel il provient et la nomme : origin. origin est le dépôt distant par défaut lors de toutes les opérations de communication.

Comme il est local, on a tous les droits (effacer ce que l'on veut par exemple). Mais warning attention car si vous modifiez une partie de l'historique qui est déjà présente sur le dépôt distant, vous allez diverger en amont du TIP du dépôt distant et vous ne pourrez plus pousser sur celui-ci puisque git n'accepte pas de pousser si cela crée une divergence sur le dépôt de destination.

Récupérer des commits depuis un dépôt distant (fetch et pull)

La commande fetch récupère les versions d'un dépôt distant qui ne sont pas présentes en local. Je ne m'attarderai pas sur cette commande parce qu'elle ne fusionne pas les informations récupérée avec les données locales. La commande pull est plus fréquemment utilisée.

La commande pull (tirer) récupère le travail effectué sur le dépôt distant (plus précisément une branche du dépôt distant) et la fusionne avec une branche locale, la branche courante, dans notre cas, la branche master.

Le pull le plus courant :

git pull origin master

On dit à Git de tirer depuis le dépôt "origin" (celui depuis lequel on a cloné) sur la branche master.

Si le pull se passe bien, il affiche ce genre de sortie :

Mise à jour 40336c4..516f16e
Fast-forward
 fichier.txt | 1 +
 1 file changed, 1 insertion(+)

Il est possible que les données tirées entrent en conflit avec le travail local. Ce chapitre aborde la résolution de conflit.

Si origin n'est pas défini, c'est à dire que le dépôt local ne provient pas d'un clonage, on peut le définir avec la commande "remote" : http://git-scm.com/book/fr/v1/Les-bases-de-Git-Travailler-avec-des-dépôts-distants#Ajouter-des-dépôts-distants

Pousser ses modifications sur un dépôt distant

Une fois que vous avez produit des versions et que vous êtes prêt à les publier sur un dépôt distant (éventuellement accessible à d'autres personnes), vous devez les pousser avec la commande push.

Cette commande est symétrique à la commande pull. On lui indique vers quel dépôt distant on veut pousser et vers quelle branche :

git push origin master

Un push peut être refusé s'il vous manque des données du dépôt distant. Il vous faudra alors d'abord tirer (pull) pour vous mettre à jour, éventuellement résoudre un conflit, avant de pouvoir pousser.

Les plateformes ouvertes d hébergement de dépôt (github, bitbucket, gitlab universitaire)

Si vous ne possédez pas de compétence/connaissance en matière d'hébergement de dépôt Git, vous pouvez demander à un administrateur à votre portée de créer et d'héberger un dépôt pour vous.

Vous pouvez aussi vous adresser à une plateforme ouverte d'hébergement de dépôts à travers une interface web. Les plus connues sont :

  • Github : gratuite si votre projet est libre et public. n'accepte que les dépôts Git.
  • Bitbucket : gratuite. accepte les dépôts Mercurial et Git
  • Gitlab qui est un cas à part puisqu'il s'agit d'un système de gestion de dépôts Git déployable sur son propre serveur. Il existe donc plusieurs instances de Gitlab. L'université de Montpellier en met un à disposition de tous les membres de l'université : https://gitlab.info-ufr.univ-montp2.fr/users/sign_in

Ces trois solutions incluent des outils de gestion de projet comme un wiki, des fils de discussion, un système de pull-request...

En général, lorsqu'on crée un dépôt sur ce genre de plateforme, l'interface nous indique son adresse complète. Pour commencer à travailler avec ce nouvau dépôt, on peut ensuite le cloner vide ou pousser depuis un dépôt local existant.

Conflits : merge avec meld ou vimdiff

Lorsqu'on effectue un pull, si on a divergé par rapport au dépôt distant, deux branches vont être temporairement créées et Git va tenter de faire un merge entre elles. Ce merge peut fonctionner automatiquement si aucune modification n'est conflictuelle :

remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
Depuis ../dist
* branch            master     -> FETCH_HEAD
Fusion automatique de fichier_a_fusionner
Merge made by the 'recursive' strategy.
 fichier_a_fusionner | 1 +
 1 file changed, 1 insertion(+)

Dans ce cas là, Git va demander un message de commit pour finaliser la procédure de merge. On aura ainsi un commit qui héritera des deux têtes (HEAD) divergentes.

Mais si les modifications sur le fichier a fusionner concernent les mêmes lignes, on peut obtenir un conflit :

remote: Counting objects: 13, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 9 (delta 3), reused 0 (delta 0)
Unpacking objects: 100% (9/9), done.
Depuis /tmp/dist
* branch            master     -> FETCH_HEAD
   9abd000..ad068c9  master     -> origin/master
Fusion automatique de fichier_a_fusionner
CONFLIT (contenu) : Conflit de fusion dans fichier_a_fusionner
La fusion automatique a échoué ; réglez les conflits et validez le résultat.

Et on est bloqué au milieu de la procédure de merge. Git est en attente de résolution de conflit.

A ce moment précis, le ou les fichiers qui ont déclenché un conflit sont modifiés automatiquement par Git. Ils contiennent des marques de conflit à l'intérieur desquelles se trouvent les différentes modifications conflictuelles.

La manière générique pour résoudre un conflit est d'éditer le fichier concerné par le conflit afin qu'il soit dans l'état de notre choix, puis on commite cette modification.

On peut résoudre un conflit en éditant le fichier à la main mais aussi utiliser un outil de résolution de conflit plus communément appelé "merge tool".

Sans outil

En cas de conflit, on peut éditer le fichier qui pose problème à la main pendant la procédure de merge. Cette solution fonctionne bien mais il est possible d'utiliser des outils qui présentent plus clairement les raisons du conflit.

On peut résoudre un conflit avec son éditeur de texte préféré.

Supposons que le fichier qui pose problème est dans cet état :

ligne neutre au milieu
ligne neutre au milieu

<<<<<<< HEAD
haha robert
=======
haha jean-claude
>>>>>>> ad068c9c33bfbbcf19ec56bdea8d904e7ad57840

ligne neutre au milieu
ligne neutre au milieu

On peut voir ici que Robert et Jean-Claude ont modifié tous les deux la même ligne pour y ajouter leur prénom. Il faut maintenant choisir l'état dans lequel on veut amener le fichier source de conflit. Imaginons qu'on veut garder la modification de Jean-Claude, alors on édite le fichier pour qu'il ressemble à

ligne neutre au milieu
ligne neutre au milieu

haha jean-claude

ligne neutre au milieu
ligne neutre au milieu

et on peut ensuite commiter pour finaliser le merge :

git commit -a -m "a la sortie du conflit, on garde la modif de jean-claude plutot que celle de robert"

Meld

Généralement, les outils de diff évolués présentent trois version du fichier qui pose problème, une qui date d'avant le conflit et les deux conflictuelles. On appelle ça du diff3 ou du diffn.

http://meldmerge.org/

Meld est le plus connu des diff graphiques capable de faire du diff3. Il est libre, sobre et efficace. Le fichier de base (avant le conflit) se situe au milieu des deux autres. C'est ce fichier qu'il faut modifier pour résoudre le conflit. Meld demande la sauvegarde de ce fichier au moment de quitter.

meld

Vimdiff

Si on aime VIM, on aime VIMDIFF. Il place les fichiers à comparer dans des splits verticaux et montre les lignes différentes avec des couleurs. Lorsqu'on l'utilise avec Git pour résoudre un conflit de merge (git mergetool -t vimdiff) il ouvre aussi un split horizontal en bas qui contient le fichier conflictuel tel qu'il est réellement.

Le fichier à modifier pour résoudre les conflits est celui du bas avec les marques. Lorsque le curseur de sélection est à l'intérieur d'un bloc de marque de conflit, on peut exécuter la commande diffget avec le paramètre BA, RE ou LO.

  • diffget BA : remplace le bloc entouré de la marque de conflit par la version de BASE (juste avant le conflit)
  • diffget RE : remplace le bloc entouré de la marque de conflit par la version distante (REMOTE) qui est celle qui a probablement été écrite par quelqu'un d'autre (sauf si on provoque un conflit avec soi-même ce qui montre qu'on a pas suivi les bons usages )
  • diffget LO : remplace le bloc entouré de la marque de conflit par la version LOCALE qui est celle que l'on a écrit

vimdiff

Les bons usages

Ces bons usages sont totalement subjectifs et dépendants de mon expérience. Il n'existe pas de bonne manière officielle pour utiliser Git.

Quand commiter ?

À quel moment dois-je commiter ? Quelle quantité de modifications dois-je inclure dans chacun de mes commits ?

Vous pouvez faire comme bon vous semble mais lorsqu'on travaille à plusieurs il peut être utile de faire en sorte que nos changements soient compréhensibles pour les autres. Pour cela, voila quelques conseils :

  • faire des commits atomiques, c'est à dire ne pas inclure des modifications qui n'ont rien à voir entre elles dans un même commit
  • faire des commits de taille relativement petite et assez souvent. Disons qu'un commit très gros ne permet pas une navigation progressive dans l'historique. À l'inverse, de trop nombreux petits commits rendent l'historique difficile à lire.
  • un commit doit avoir du sens

Que mettre dans les messages de commit ?

Si on respecte les conseils précédents sur la taille, la fréquence et l'atomicité d'un commit, il est assez simple de décrire en quelques mots un commit.

Si plusieurs commits concernent une même fonctionnalité, on peut ajouter un préfixe au message de commit, par exemple : [simulation] .

Si le projet est libre et public, il est nécessaire d'écrire ses messages de commits en anglais pour ne pas restreindre les participations extérieures potentielles.

Quand tirer (pull) ?

Pour rappel, vous devez tirer lorsque le dépôt est dans un état stable.

Pour la fréquence de pull, tout dépend de la forme de votre projet. Si vous êtes tout seul alors vous devriez savoir si vous avez besoin de récupérer le travail que vous même avez poussé d'ailleurs.

Si vous êtes plusieurs et que vous travaillez chacun sur des parties totalement indépendantes les unes des autres, alors vous pouvez faire comme si vous étiez seul concernant la fréquence de pull.

Si vous êtes plusieurs et que vous dépendez du travail des autres vous aurez besoin de tirer plus souvent.

Il est recommandé de tirer au minimum une fois en début de session de travail. Au maximum vous pouvez tirer à chaque commit que vous faites.

Quand pousser (push) ?

Cette question est plus difficile que la précédente. L'action de pousser est très souvent synonyme de publication de son travail. Il est alors conseillé de ne pas pousser des modifications qui rendent le projet inutilisable parce qu'elle publient une version inutilisable du code (qui ne compile pas ou qui ne fonctionne pas, par exemple).