Git : comprendre la gestion de versions

Cet article a pour but de donner une première approche de git (prononcé ‘guitte’ le plus souvent). Dans cette optique, nous présenterons le système de gestion de versions afin d’avoir une approche saine de git.
Corentin RISSELINMis à jour le 17 Févr 2017
git gestion version

1 Préambule

Cet article a pour but de donner une première approche de git (prononcé guitte le plus souvent). Dans cette optique, nous présenterons le système de gestion de versions afin davoir une approche saine de git. Nous ne verrons pas exhaustivement toutes les fonctionnalités de git mais les plus essentielles. Si vous voulez connaître plus en profondeur les actions possibles avec git, la documentation officielle de git est très bien écrite et vous permettra de connaître les commandes en profondeur. Si cet article remplit son rôle, vous naurez plus quà vous référer à la documentation officielle pour effectuer des actions spécifiques et vous aurez une bonne compréhension du système dans son ensemble.

Notez que la plus grande difficulté dans lutilisation de git est son jargon : beaucoup de gens se sentent perdus car les termes ne semblent pas toujours naturels. Ceux-ci sont pourtant essentiels car en effet git est un système complexe (mais pas difficile), en comprenant les termes vous appréhenderez aisément le système dans son ensemble.

2 Git : pourquoi

Il est difficile de démontrer tous les bénéfices de git par rapport à ses concurrents avant dexpliquer plus en détails son fonctionnement, mais il est clairement important dy répondre. Voici différents points forts de git :

  • Lespace disque utilisé par git est très faible comparé à ses concurrents
  • Le système décentralisé est très flexible et répond à beaucoup de problématiques non résolues par les autres systèmes centralisés (voir chapitre suivant)
  • Licence GNU : git appartient au domaine publique, il est aussi très « suivi » (mis à jour).
  • Git est de loin le système le plus populaire : tout outil de développement « digne de ce nom » lintègre et il existe de nombreux services associés très populaires (Github, Gitlab, )

3 Git : la gestion de versions

3.1 Introduction

Pour commencer parlons des gestionnaires de versions (ou VCS en anglais, pour Version Control System), lidée semble simple au premier abord : avoir un système permettant denregistrer lensemble des fichiers dun projet, comme des back-up (fichiers de secours), que lon pourrait sauvegarder les uns après les autres comme des versions de notre projet.

Lensemble des sauvegardes dun projet (dit versionné) est appelé dépôt (ou repository). Retenez bien le jargon car cela vous aidera afin de comprendre cet article mais aussi toute documentation que vous pourrez lire. 

depot-1024x409.jpg

Nous allons voir comment ce processus devient plus fin et plus complexe en voulant un système performant et puissant.

Si vous imaginez utiliser un tel système de sauvegarde, ou si vous lavez déjà fait, vous vous rendez compte que la grande majorité du temps les modifications ne touchent quune petite partie de votre projet. Ainsi les logiciels de gestion de versions ne vont pas sauvegarder tous les fichiers à chaque fois mais les différences entre la nouvelle version et son antécédent. Ainsi votre dépôt nécessitera un espace bien moindre sur votre disque.

Note : Nayez pas peur de créer une nouvelle version de votre projet pour chaque petite modification apportée. Lespace utilisé sur votre disque est très minime. Une grande modification (touchant beaucoup de lignes/fichiers) sera bien moins lisible si quelquun doit revenir dessus.

Avec seulement ces premiers points, nous pouvons comprendre comment un logiciel de gestion de versions fonctionne. Il y a dun côté le dépôt contenant lensemble des versions (en fait des sortes de patchs afin de passer dune version à lautre), et vous pouvez travailler sur vos fichiers de votre côté. Si vous appréhendez bien cette logique, vous comprenez que les logiciels de gestion de versions fonctionnent avec un côté serveur (gérant le dépôt, sur une machine distante de préférence), et un côté client (appelant le dépôt, sur votre ordinateur).

Vous allez ainsi utiliser votre logiciel de gestion de versions (côté client) avec principalement les actions suivantes :

  • Récupérer le(s) fichier(s) : checkout
  • Envoyer une nouvelle version : commit (normalement accompagné dun message)
  • Récupérer la dernière version : update
  • Voir létat de vos fichiers par rapport à la dernière version : status
  • Voir lhistorique des versions : log
  • Comparer 2 versions : diff

Ces actions sont communes à la grande majorité des logiciels, git ajoutera quelques subtilités que nous verrons plus tard.

3.2 Cycle de travail classique

Avant davancer plus spécifiquement sur git voyons un cycle de travail classique dune personne sur un projet (avec un système de version simple).

Dans cet exemple les choses sont très simples mais si vous travaillez en équipe, un problème va apparaître : si le même fichier est modifié par 2 personnes différentes, comment mettre à jour le dépôt? La solution est la fusion (ou merge en anglais), la première personne à envoyer (commit) sa version naura pas de soucis mais la deuxième devra dabord récupérer cette nouvelle version et la fusionner avant de pouvoir commit.

Ce problème de fusion est récurrent et source de beaucoup de problèmes et dincompréhension. Les fichiers à fusionner vont faire apparaître des balises spécifiques afin dindiquer les morceaux à fusionner. Le plus simple, et le plus courant, est dutiliser des programmes afin de gérer les fusions plus simplement (car les balises sont très difficilement lisibles pour les humains).

Ces 2 premiers exemples restent simples, vous allez peut être vouloir travailler sur des fonctionnalités dont vous nêtes pas encore sûr quelles seront intégrées au projet final, ajouter des corrections sur des versions précédentes, ou travailler avec des équipes hiérarchisées. Avec un système simple comme présenté jusquà présent, ces problématiques sont loin dêtre résolues. Cest ici que git nous montrera tout son potentiel.

3.3 Git : un système décentralisé

Le système de gestion de versions décrit jusquici représente une gestion de versions proche de Subversion (abrégé SVN, développé par Apache). SVN est(était?) très plus populaire, nous le prendrons comme représentant des anciens systèmes de gestion (comme CVS ou dautres). La popularité de git est toujours croissante, bon nombre de particuliers et dentreprises migrent vers git, beaucoup de sources considèrent désormais git comme étant très largement le plus utilisé (exemple de statistique : Google trend).

La grande différence de git : la décentralisation et les branches.

Ces fonctionnalités permettent de résoudre les problématiques décrites en fin du dernier chapitre.

Note : Il existe aussi Mercurial (GNU) comme système décentralisé.

3.3.1 La décentralisation

La décentralisation est un concept assez simple, chaque client devient aussi un serveur indépendant. Votre dépôt habituel peut être considéré comme un simple client.

Ainsi, chaque client (ordinateur) possède son propre dépôt (repository), dit local. Un commit n’envoie donc plus sur un dépôt central mais sur le local.

Une nouvelle commande fait son apparition : push, celle-ci permet denvoyer le(s) versions contenues dans le dépôt local vers un distant (dit remote). Vous pouvez voir cette opération comme une synchronisation (dans un sens seulement).

Aussi, léquivalent de la commande update sera pull (en opposition à push) afin de récupérer les informations du dépôt distant dans votre dépôt local (les fichiers sont mis à jour par la même occasion).

Comprenez bien que, désormais, vous pouvez aussi avoir plusieurs dépôt distants, lors dun push vous pouvez donner ladresse du dépôt destinataire. Cependant, pour éviter de répéter toujours cette information, le plus courant est de définir votre dépôt par défaut : votre upstream. Ne vous inquiétez pas trop sur ce point, si vous loubliez, git vous rappellera élégamment comment laffecter si vous faite un simple push.

Afin de gérer ces dépôts distants, git possède plusieurs sous-commandes depuis la commande remote, parmi lesquels:

  • git remote : affiche la liste des dépôts enregistrés (simplement les nom)
  • git remote -v : affiche la liste des dépôts enregistrés (nom et adresse)
  • git remote add <nom du dépôt> <adresse du dépôt> : ajoute un nouveau dépôt
  • git remote remove <nom du dépôt> : supprime un dépôt

Par défaut le dépôt principal est souvent noté origin, donnant la commande :

git remote add origin <
adresse du dépôt>

Note : si vous avez bien compris le système vous devriez mieux appréhender le fait quon ne commit pas directement vers un dépôt distant. En fait, on ne fait normalement aucune opération directement sur un dépôt distant, on effectue les opérations souhaitées sur son dépôt local puis on push.

Note : grâce à ce système vous pouvez donc faire des commit même si vous navez aucune connexion (internet/à votre dépôt distant).

3.3.2 Les branches

Ce concept existait en fait sur les anciens systèmes aussi mais restait très rudimentaire. Une branche est une sorte de sous-dépôt, elle peut aussi commencer depuis une version particulière et se terminer.

Au sein dun dépôt, vous allez donc pouvoir commit sur une branche en particulier, par défaut, la branche principale est master.

Afin de gérer les branches vous utiliserez le plus souvent les commandes suivantes :

  • git branch  : créer une nouvelle branche
  • git checkout  : change de branche (oui cest comme récupérer un dépôt en fait)
  • git merge  : fusionne une branche vers la branche courante

Vous comprendrez que ce système de branche permet à plusieurs personnes de travailler sur le même projet sans créer de conflits. Une fois les travaux terminés, les branches peuvent être fusionnées par la suite. De même, vous pouvez imaginer un système de branches hiérarchisées. En fait, la souplesse induite par ce système permet beaucoup de possibilités et la difficulté principale sera pour vous de trouver une structure adaptée à votre projet et à votre équipe.

Note : le système de branche peut aussi vous permettre de faire des commits intermédiaires sur une branche spéciale si vous voulez avec des sauvegardes régulières puis fusionné sur une branche dont les commits correspondent plus au processus de développement plutôt quà des impératifs heuristiques (si vous en avez). En effet, il est préférable davoir des commits reflétant lajout de fonctionnalités/correctifs et non des commits partielles effectués par simple sécurité.

3.4 Git : le staging

Si vous avez suivi larticle jusquici, vous connaissez lopération commit pour envoyer une nouvelle version. Cependant, il peut être très intéressant de vérifier le commit avant de lenvoyer ou de nenvoyer quune partie des fichiers.

Pour ceci git ajoute une nouvelle étape : le staging (ou encore lindex).

Lidée de base encore une fois est simple : vous annoncez dabord les fichiers que vous voulez envoyer avant de faire votre commit. Il y a en effet un index (à limage de lindex dun livre) contenant les différentes entrées (ici des fichiers) pour le futur commit. Les commandes de git pour gérer cette phase vont jouer sur cet index :

  • git add <fichier/dossier> : Ajouter un fichier/dossier à lindex (possibilité de wildcard comme *.html)
  • git rm cached <fichier/dossier> : Enlève un fichier/dossier à lindex (sans lattribut cached vous supprimer le fichier par la même occasion)
  • git status : Affiche la différence entre vos fichiers et la dernière version (de la branche actuelle). Cette opération, avec git, montre aussi les fichiers indexés (prévus pour le prochain commit) et ceux qui ne le sont pas.

Note : pour supprimer un fichier sur votre dépôt vous devez donc le supprimer normalement puis ajouter son entrée à lindex (ce processus peut sembler déroutant aux premiers abords puisque lon utilise bien la commande git add, bien que nous voulons supprimer un fichier).

Note : vous pouvez inclure un fichier nommé .gitignore dans votre projet (dans le dossier racine) afin que git ignore complètement certains fichiers (comme si ils étaient transparents). Dans ce fichier chaque ligne représentera un pattern de fichier/dossier à ignorer.

Note : beaucoup de commandes peuvent être effectuées sur les fichiers indexés seulement, vous verrez alors les attributs cached ou staged. Ces 2 noms désignent bien la même chose (exemple : git diff cached et git diff staged pour voir les différences entre une version et les fichiers indexés).

4 Git : exemple dutilisation

4.1 Installation

Cet article (déjà trop long) ne traitera malheureusement pas de linstallation. Rassurez-vous le site officiel est très bien présenté et vous ne devriez rencontrer aucune difficulté sur cette étape.

4.2 Création du serveur

Beaucoup de personnes utilisent Github ou Gitlab, ces services permettent de gérer des dépôts distants, avec des services dauthentification, de tickets (pull request, issues). Cependant vous pouvez aussi très simplement créer vos dépôts vous-même.

Pour cela, il suffit de créer un dossier (ce sera votre dépôt), la convention habituelle veut que vous le nommiez en .git (comme projet.git). Noubliez pas la gestion des permissions de lecture/écriture, vous pouvez utiliser la commande push avec une adresse se connectant en root mais ceci nest vraiment pas recommandé, normalement on utilise git avec lutilisateur git créé spécialement lors de linstallation (sous linux si vous avez fait un apt-get).

La seule commande nécessaire à la préparation dun dépôt est init (avec lattribut bare).

mkdr projet.git
cd projet.git
git init --bare

Note : lattribut bare sert en fait à ne pas préparer le work tree permettant de scanner larborescence de fichier (en vue de créer lindex pour le stage). Le serveur na en effet pas besoin de stage (pour faire des commit).

Note : si vous voulez utiliser un système avec plusieurs utilisateurs vous pouvez utiliser lattribut shared (voir la documentation).

Et cest tout, comme vous pouvez le voir ce fut très simple. Lors dun futur appel dun client sur le serveur, git regardera si un dépôt est bien présent et pour ce dossier en effet nous avons préparé un dépôt (totalement vide).

Note : vous vous demandez peut être si votre firewall risque de bloquer git sur votre serveur. Selon la méthode daccès (le protocole dans ladresse de votre dépôt) vous devrez ouvrir le port nécessaire. Souvent (en fait par défaut) le protocole SSH est utilisé (port 22), exemple dadresse : git@mycompany.com:/git/project.git. Ici le git avant @ spécifie lutilisateur avec lequel votre client git se connecte en SSH (le mot de passe sera demandé ensuite), vous pourriez par exemple utiliser root@[…] (non recommandé). Plusieurs protocoles daccès sont possibles, nous ne présenterons pas ici toute les possibilités.

Note : vous pouvez aussi avoir un dépôt distant (remote) sur le même ordinateur: auquel cas vous pouvez utiliser le protocole file://.

4.3 Création et premier push côté client

Après linstallation de git sur votre ordinateur, il vous faut savoir quun commit est obligatoirement accompagné dun message et dune identité (nom + email). Le message sera écrit lors de lopération de commit mais votre identité doit être préalablement enregistrée. Afin de définir votre nom et email, vous pouvez utiliser les commandes suivantes :

"John Doe"</code>
<code class="gp"></code>git config --global user.email johndoe@example.com

Vous navez pas vraiment besoin de retenir ceci car git vous rappellera ces commandes si vous ne lavez pas encore fait.

Note : il existe aussi un système de configuration par dépôt (comme lattribut global le sous-entend).

Nous supposons que votre projet est dans un dossier nommé simplement projet. Nous allons créer un dépôt local à partir de ce dossier (donc synchronisant tous les fichiers, vous pouvez préparer un fichier .gitignore préalablement). Puis commit notre première version et push sur notre serveur.

cd projet
git init

Cette fois nous avons utiliser la commande init simplement afin de préparer notre dépôt local (qui scannera le dossier courant par défaut).

git add .

Nous ajoutons ensuite à lindex tous le dossier courant (le dossier . est le dossier courant).

git commit -m "Premier commit"

Puis nous pouvons commit, vous noterez que nous accompagnons le commit de son message directement avec lattribut -m. Sinon vous serez emmené sur un éditeur par défaut afin déditer un fichier (temporaire) contenant le message (qui est obligatoire avec git) associé à votre commit.

git remote add origin <
adresse du dépôt distant>
git push

Enfin, nous ajoutons notre dépôt distant et nous faisons un simple push.

Ici le push simple ne marchera pas car si vous vous souvenez nous navons pas défini notre upstream (dépôt distant pas défaut). Il est plus simple, dans un premier temps, de ne retenir que le fait de devoir faire un push, git vous rappellera élégamment la commande adéquate afin deffectuer le push sur votre dépôt origin (nom que nous avons donné) tout en linscrivant comme upstream (ainsi les futurs push simple fonctionneront). Cette dernière commande étant en fait :

git push --set-upstream origin master

4.4 Récupération du projet

Pour récupérer un projet, nous devrions suivre un processus tel que : init -> add remote -> checkout. Cependant, git nous propose un raccourci avec la commande clone.

git clone <
adresse du dépôt distant>

5 Conclusion et perspectives

Comme nous lavons vu, git est en effet un système complexe : il est composé de plusieurs couches quil est nécessaire de comprendre pour ne pas sy perdre. Mais la complexité nest pas synonyme de difficulté : chaque couche est en fait proprement structurée et les commandes sont claires et simples (cest bien leur multiplicité qui rend le système globalement difficile pour débuter).

Il y a encore beaucoup de choses à apprendre sur les possibilités de git mais vous devriez avoir une bonne compréhension du système après cet article.

Bonus Migration de SVN vers git

Si vous aviez déjà un dépôt SVN, git propose une commande simple afin de migrer celui-ci en git. Ici vous est montré la version la plus simple, vous pouvez aussi récupérer le nom dutilisateur SVN (voir la documentation officielle) :

git svn clone <
adresse du dépôt SVN> --no-metadata
cd <
dossier du projet>
git remote add origin <
adresse du dépôt distant git>
git push
git push --set-upstream origin master