GIT

Git logo

Présentation de Gauthier C. est mise à disposition selon les termes de la licence Creative Commons Attribution 4.0 International.

ccby

Introduction

Il était une fois

[user@dev monprojet]$ ls
monfichier.txt
monfichier.old
monfichier.old2
monfichier.old.du.lundi
monfichier.old.du.lundi.avant
monfichier.old.bak
...

À propos des gestionnaires de versions

1ère génération : Les systèmes de gestion de version locaux

  • 1972: SCCS

  • 1982: RCS

  • 1985: PVCS

Contraintes

  • Modification d’un fichier à la fois.

  • Vérou sur le fichier pendant la modification.

Les systèmes de gestion de version centralisés

centralized

Les systèmes de gestion de version centralisés

2ème génération: (multi-fichiers, client-server, fusion avant commit)

  • 1986: CVS

  • 1992: Rational ClearCase

  • 1994: Visual SourceSafe

3ème génération: (validation atomique)

  • 1995: Perforce

  • 2000: Subversion

Les systèmes de gestion de version distribués

distributed

Les systèmes de gestion de version distribués

  • 2000: Bitkeeper

  • 2001: GnuArch (Baz en 2004)

  • 2002: Darcs

  • 2003: Monotone

  • 2003: SVK

  • 2005: GNU Bazaar (évolution de Baz)

  • 2005: Mercurial

  • 2005: Git

  • 2010: Veracity

Histoire de Git

  • Source du kernel Linux géré avec Bitkeeper avant 2005.

  • Mars 2005: fin de l’usage gratuit de Bitkeeper.

  • Création de Git le 3 avril 2005 par Linus Torvalds.

  • Utilisation pour la gestion du source du kernel mi-avril 2005.

  • Version 1.0 le 21 décembre 2005

  • Version 2.33.0 le 16 août 2021

Git et ses avantages

  • vitesse ;

  • conception simple ;

  • support pour les développements non linéaires (milliers de branches parallèles) ;

  • complètement distribué ;

  • capacité à gérer efficacement des projets d’envergure tels que le noyau Linux (vitesse et compacité des données).

  • intégrité des données.

  • construit comme un système de fichiers versionné.

Rudiments de Git

Fonctionnement des VCS classiques (cvs, subversion, Perforce, Bazaar, …)

deltas

Ces systèmes sauvent l’information comme des modifications sur des fichiers.

Fonctionnement de Git

snapshots

Git stocke les données comme des instantanés du projet au cours du temps.

Presque toutes les opérations sont locales

  • Fonctionne parfaitement en mode déconnecté.

  • Pas besoin de vpn pour travailler

  • Toutes les révisions sont présentes sur tout les dépôts.

Git gère l’intégrité

  • Vérification de l’intégrité des fichiers fait partie intégrante de la philosophie de l’outil.

  • Le mécanisme que Git utilise pour réaliser les sommes de contrôle est appelé une empreinte SHA-1 (160 bits).

Les 4 états de vos fichiers

lifecycle

Avant de commencer

Paramétrage de son environnement

Configurer son shell pour qu’il affiche l’état du dépôt Git :

  • bash : Installer powerline-go comme indiqué ici.

  • fish : Installer le thème bobthefish avec Oh My Fish ou powerline-go.

  • zsh : Installer un thème avec Oh My Zsh ou powerline-go.

  • ou installer startship

Paramétrage à la première utilisation

  • Fichier /etc/gitconfig : Tous les utilisateurs.

    • `git config --system`

  • Fichier ~/.gitconfig : Spécifique à votre utilisateur.

    • `git config --global`

  • Fichier config dans le répertoire Git (c’est-à-dire .git/config): spécifique au seul dépôt en cours.

    • `git config`

Votre identité

  • git config --global user.name "John Doe"

  • git config --global user.email jd@mail.com

Pour changer d’identité pour un repo spécifique, se placer dans le repo et saisir la commande sans `--global`.

Votre éditeur de texte

  • git config --global core.editor vim

Vérifier vos paramètres

$ git config --list
user.name=John Doe
user.email=jd@mail.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
…
$ git config user.name
John Doe

Obtenir de l’aide

Si vous avez besoin d’aide pour utiliser Git, il y a trois moyens d’obtenir les pages de manuel pour toutes les commandes de Git :

Exercice

  • Effectuez le paramêtrage de votre environnement Git avec git config

    • nom, email, editeur

  • Aidez vous de la commande git help

Les commandes de base

Cycle de vie de vos fichiers

lifecycle

Démarrage d’un dépôt Git local

$ git init

Cela crée un nouveau sous-répertoire nommé .git qui contient tous les fichiers nécessaires au dépôt.

$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version'

Il est nécessaire de lancer la commande git add pour ajouter les fichiers dans l’index avant commit.

Ajout de fichiers

Lorsque le fichier est passé en paramêtre il n’est pas nécessaire de passer par git add pour l’ajouter au Staged.

git commit fichier1 [ fichier2 …​]

  • git commit . ou git commit -a commit uniquement les fichiers présents dans le précédent commit.

  • git add . && git commit commit tous les fichiers présents dans le répertoire et les sous répertoires.

Suppression de fichiers

git rm fichier

  • supprime le fichier de l’index et de la copie de travail.

git commit

  • Valide cette suppression.

Affichage des différences

git diff [ rev_a [ rev_b ] ]

  • Affiche la différence entre de révisions rev_a et rev_b. Par défaut rev_a est l’index et _rev_b la copie de travail.

git diff --staged

  • Différence entre HEAD et l’index.

Commandes de base

  • git status

  • git show

  • git add

  • git diff

  • git commit

  • git rm

  • git mv

Ignorer des fichiers

Exercice

  • Créez un nouveau dossier

  • Initialisez un nouveau dépôt Git dans ce dossier

  • Manipulez et faites des commits pour valider ces modifications avec les commandes suivantes:

    • git status

    • git add

    • git diff

    • git commit

    • git rm

    • git mv

Visualiser l’historique des validations

  • git log

  • git log -p -2

  • git log --stat

  • git log --oneline --graph --all

  • git log --pretty=format:"%h - %an, %ar : %s"

  • git log --pretty=format:"%h %s" --graph

  • git log --since=2.weeks

Les alias Git

Certaines commandes Git sont trop longues ou difficiles à mémoriser, pour nous aider nous pouvons utiliser les alias :

git config --global alias.loga "log --oneline --graph --all"

Branches et fusions

Les branches en bref

  • Une branche dans Git est simplement un pointeur léger et déplaçable vers un commits

  • Master est la branche par défaut créé par la commande git init

Une branche et l’historique de ses commits

branch and history

Créer une nouvelle branche

git branch testing

Cela crée un nouveau pointeur vers le commit courant.

two branches

Vous êtes toujours sur la branche master.

head to master

Changer de branche

$ git checkout testing
head to testing

Qu’est-ce que cela signifie ?

Et bien, faisons une autre validation :

$ vim README.md
$ git commit -a -m 'un changement dans le fichier README'
advance testing

Retournons sur la branche master

$ git checkout master
checkout master

Nouvelle modification pour diverger

$ vim README.md
$ git commit -a -m 'un changement dans le fichier README'
advance master

Suppression d’une branche

$ git branch -d testing

À retenir

  • 3 commandes: commit, branch, checkout

  • Une branche Git n’est en fait qu’un simple fichier contenant les 40 caractères de l’empreinte SHA-1 du commit sur lequel elle pointe.

  • git log --oneline --decorate --graph --all pour visualiser les branches.

  • Quand vous changez de branche, Git réinitialise votre répertoire de travail pour qu’il soit le même que la dernière fois que vous avez effectué un commit sur cette branche.

Exercice

  • Créez une nouvelle branche appelée testing

  • Positionnez-vous sur la branche testing

  • Créez un nouveau fichier et commitez vos modifications

  • Revenez sur la branche master

  • Affichez les différences avec la branche testing

Fusions de branches

Merge Fast-forward

basic branching 4

Merge Fast-forward

$ git checkout master
$ git merge hotfix
Updating f30ab..87ab2
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

Merge Fast-forward

basic branching 5

Merge branches divergentes

advance master

Merge branches divergentes

merge div

Exercice

  • Créez une nouvelle branche appelée hotfix

  • Positionnez-vous sur la branche hotfix

  • Modifiez un fichier et faites un commit

  • Retournez sur la branche master (commande git checkout)

  • Modifiez un fichier et faites un nouveau commit

  • Fusionnez la branche hotfix dans master avec git merge

Visualisation graphique de l’exercice

Travailler avec des dépôts distants

Cloner un dépôt distant

  • Via https:

git clone https://framagit.org/gauthier/SlideGit.git
  • Via ssh:

git clone git@framagit.org:gauthier/SlideGit.git
  • Depuis un autre dossier:

git clone /home/user/git/MonProjet.git

Afficher les dépôts distants

$ git remote -v
origin   https://framagit.org/gauthier/SlideGit.git (fetch)
origin   https://framagit.org/gauthier/SlideGit.git (push)

Ajouter des dépôts distants

$ git remote
origin
$ git remote add paul https://gitlab.com/paul/SlideGit
$ git remote -v
origin   https://framagit.org/gauthier/SlideGit.git (fetch)
origin   https://framagit.org/gauthier/SlideGit.git (push)
paul   https://gilab.com/paul/SlideGit.git (fetch)
paul   https://gilab.com/paul/SlideGit.git (push)

Récupérer et tirer depuis des dépôts distants

$ git fetch [remote-name]

Récupérer et tirer depuis des dépôts distants + fusion

$ git pull [remote-name]

Pousser son travail sur un dépôt distant

$ git push [nom-distant] [nom-de-branche]

Inspecter un dépôt distant

$ git remote show origin
* distante origin
  URL de rapatriement : git@framagit.org:gauthier/SlideGit.git
  URL push : git@framagit.org:gauthier/SlideGit.git
  Branche HEAD : master
  Branche distante :
    master suivi
  Branche locale configurée pour 'git pull' :
    master fusionne avec la distante master
  Référence locale configurée pour 'git push' :
    master pousse vers master (à jour)

Retirer et renommer des dépôts distants

$ git remote rename paul polo
$ git remote
origin
polo

Exercice

Par soucis de simplicité, nous travaillerons avec un pseudo dépôt distant.

  • Créer un nouveau dépôt remote.git avec l’option --bare

  • Ajouter un nouveau remote origin vers ce dépôt

  • Envoyer le contenu du projet de l’exercice précédent dans remote.git avec la commande git push.

  • Cloner ce projet dans un troisième répertoire avec git clone.

  • Pousser et tirer les modifications vers remote.git depuis les 2 dépôts de travail.

Stockage des identifiants

SSH

  • Création d’un bi-clé

  • Dépôt de la clef publique sur le serveur

  • Charger la clef en mémoire avec ssh-add

Authentification HTTP

Plusieurs modes proposés:

  • Par défaut, rien n’est mis en cache.

  • Le mode « cache » conserve en mémoire les identifiants pendant 15 minutes par défaut.

git config --global credential.helper "cache --timeout 900"
  • Le mode « store » sauvegarde les identifiants dans un fichier texte (en clair) sur le disque, et celui-ci n’expire jamais.

git config --global credential.helper "store --file ~/.my-credentials"

Authentification HTTP

  • Sous Mac, Git propose un mode « osxkeychain », qui met en cache les identifiants dans un trousseau sécurisé attaché à votre compte système.

  • Sous Windows, vous pouvez installer une application appelée « Git Credential Manager for Windows » similaire à « osxkeychain ».

Étiquetage/Tag

Créer des étiquettes annotées

$ git tag -a v1.4 -m 'ma version 1.4'
$ git tag
v1.3
v1.4

Vous pouvez visualiser les données de l’étiquette à côté du commit qui a été marqué en utilisant la commande git show

Les étiquettes légères

Pour créer une étiquette légère, il suffit de n’utiliser aucune des options -a, -s ou -m :

$ git tag v1.4-lg
$ git tag
v0.1
v1.4
v1.4-lg
v1.5

Regarder la différence de sortie avec git show.

Lister vos étiquettes

Lister les étiquettes existantes dans Git est très simple. Tapez juste git tag :

$ git tag
v0.1
v1.3

Recherche avec un motif

$ git tag -l 'v1.3.*'
v1.3.1
v1.3.2

Étiqueter après coup

Pour étiqueter un ancien commit, vous spécifiez la somme de contrôle du commit (ou une partie) en fin de commande :

$ git tag -a v1.2 9fceb02

Partager les étiquettes

Par défaut, la commande git push ne transfère pas les étiquettes vers les serveurs distants. Il faut explicitement pousser les étiquettes après les avoir créées localement.

$ git push origin v1.5

La commande suivante transférera toutes les nouvelles étiquettes vers le serveur distant.

$ git push origin --tags

Gestion sémantique de version

Étant donné un numéro de version Majeur.Mineur.Fix, il faut incrémenter le numéro de version:

  1. Majeur quand il y a des changements non rétrocompatibles,

  2. Mineur quand il y a des changements rétrocompatibles,

  3. de Fix quand il y a des corrections d’anomalies rétrocompatibles.

Conflits de fusion

Si vous avez modifié différemment la même partie du même fichier dans les deux branches que vous souhaitez fusionner, Git ne sera pas capable de réaliser proprement la fusion.

Merge avec conflit

Si votre résolution du problème #53 a modifié la même section de fichier que le correctif, vous obtiendrez un conflit qui ressemblera à ceci :

$ git merge prob53
Fusion automatique de index.html
CONFLIT (contenu) : Conflit de fusion dans index.html
La fusion automatique a échoué ; réglez les conflits et validez le résultat.

Git n’a pas automatiquement créé le commit de fusion. Il a arrêté le processus le temps que vous résolviez le conflit.

Verification de la liste des fichiers impactés

$ git status
Sur la branche master
Vous avez des chemins non fusionnés.
  (réglez les conflits puis lancez "git commit")
  (use "git merge --abort" to abort the merge)

Chemins non fusionnés :
  (utilisez "git add <fichier>..." pour marquer comme résolu)

        modifié des deux côtés :  index.html

aucune modification n'a été ajoutée à la validation (utilisez "git add" ou "git commit -a")

Correction du conflit à la main

 <<<<<<< HEAD:index.html
 <div id="footer">contact : email.support@github.com</div>
 =======
 <div id="footer">
  please contact us at support@github.com
 </div>
 >>>>>>> prob53:index.html

C’est au développeur de prendre la décision et d’enregistrer le fichier. Ensuite git add et d’un git commit pour terminer l’opération.

Abandonner une fusion

$ git merge --abort

Ignorer les caractères invisibles lors de la fusion

$ git merge -Xignore-all-space mabranche

ou

$ git merge -Xignore-space-change mabranche

La première option ignore complètement tous les espaces tandis que la seconde traite les séquences d’un ou plusieurs espaces comme équivalentes.

git rebase

La seconde façon de combiner les contenus de deux branches est rebase. Rebase prend un ensemble de commits, les recopie, et les ajoute en bout de chaîne à un autre endroit.

Avant le git rebase

advance master

Action du git rebase

$ git checkout testing
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command

Après le git rebase

basic rebase 2

Résultat final

À ce moment, vous pouvez retourner sur la branche master et réaliser une fusion en avance rapide (fast-forward merge) pour obtenir ceci:

basic rebase 3

À retenir

  • Toutes les modifications apparaissent en série même si elles ont eu lieu en parallèle.

  • Le commit résultant d’un merge ou d’un rebase est strictement identique.

  • L’historique de fusion et les résolutions de conflit ne sont pas conservés.

  • Les conflits sont à résoudre pour chaque commit. (git merge: une seule résolution de conflit)

Ne rebasez jamais des commits qui ont déjà été poussés sur un dépôt public.

Exercice

  • Créez une nouvelle branche appelée bugFix

  • Positionnez-vous sur la branche bugFix

  • Modifiez un fichier et faites un commit

  • Retournez sur la branche master (commande git checkout)

  • Modifiez un fichier et faites un nouveau commit

  • Positionnez-vous sur la branche bugFix et faites un git rebase master

Visulation graphique de la manipulation

Bien gérer ses commits

Donner du sens au message de commit

  • Pour une meilleur lisibilité

  • Pour les nouveaux et les autres en général

  • Pour la revue de code

Conventions de commit

  • Exemple pour le projet angularjs

    < type > (< scope >): < Subject >

    < BLANK LINE >

    < body >

    < BLANK LINE >

    < footer >

<type> ( < scope > ): < Subject >

  • feat (feature)

  • fix (correction de bugs)

  • docs (documentation)

  • style (formatage, ponctuations manquantes, …)

  • refactor

  • test (lors de l’ajout de tests manquants)

  • core (maintenir)

<type> ( < scope > ): < Subject >

Scope ou portée en français, indique la partie de code impactée par le changement.

Il est important, avant de commencer le projet, de convenir d’une convention de nommage sur les différentes parties du programme.

Optionnel, une modification peut impacter la totalité du code.

<type> ( < scope > ): < Subject >

  • Décrire ce que l’on apporte à l’application et non pas au code.

  • pas de majuscule sur la première lettre

  • pas de point (.) en fin de ligne

< body >

  • Complément du sujet

  • Détail de l’implémentation du changement

Optionnel

< footer >

  • Référence sur le commit

  • Indication du numéro de bugfix

  • Indication des ruptures dans le code ( expliquer la migration, l’impact )

Optionnel

Exemple

fix($compile): couple of unit tests for IE9

Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.

Closes #392
Breaks foo.bar api, foo.baz should be used instead

Git add interactive

git add --interactive

Cette commande affiche la liste des sous commandes de git add.

 *** Commands ***
   1: status       2: update       3: revert       4: add untracked
   5: patch        6: diff         7: quit         8: help
 What now> 1

git add --edit

Permet d’éditer directement le patch et de retirer les lignes que l’on souhaite exclure de l’index.

git add --patch

Permet de choisir block par block ce que l’on souhaite ajouter à l’index.

   y - stage this hunk
   n - do not stage this hunk
   q - quit; do not stage this hunk or any of the remaining ones
   a - stage this hunk and all later hunks in the file
   d - do not stage this hunk or any of the later hunks in the file
   g - select a hunk to go to
   / - search for a hunk matching the given regex
   j - leave this hunk undecided, see next undecided hunk
   J - leave this hunk undecided, see next hunk
   k - leave this hunk undecided, see previous undecided hunk
   K - leave this hunk undecided, see previous hunk
   s - split the current hunk into smaller hunks
   e - manually edit the current hunk
   ? - print help

Réécrire l’histoire

Motivations

  • Corriger un oubli lors du précédent commit

  • Historique des commits plus linéaire

  • Nettoyer une branche avant un push

  • Retour arrière

  • Supprimer un contenu qui ne doit pas être là.

Annuler des actions

git commit --amend

Remplace le commit précédent. Utile si vous avez oublié un fichier, ou vue une faute de frappe dans votre message.

$ git commit -m 'validation initiale'
$ git add fichier_oublie
$ git commit --amend

Vous n’aurez au final qu’un unique commit — la seconde validation remplace le résultat de la première.

Si vous ne souhaitez pas modifier le message de commit, ajoutez l’option --no-edit.

Défaire les fusions

Avec Git il n’est pas interdit de faire des erreurs, parce qu’il reste toujours possible de les corriger.

$ git reset --hard HEAD~

reset --hard réalise généralement trois étapes :

  1. Déplace la branche pointée par HEAD,

  2. Faire ressembler l’index à HEAD,

  3. Faire ressembler le répertoire de travail à l’index.

À éviter après un push ou un autre commit.

Inverser le commit

Si les déplacements des pointeurs de branche ne sont pas envisageables, Git vous donne encore l’option de créer un nouveau commit qui défait toutes les modifications d’un autre déjà existant.

$ git revert -m 1 HEAD

L’option -m 1 indique quel parent est le principal et devrait être conservé.

Attention, une nouvelle fusion ne donnera rien, car la branche a déjà été fusionnée.

Désindexer un fichier déjà indexé

$ git add .
$ git status
Sur la branche master
Votre branche est à jour avec 'origin/master'.
Modifications qui seront validées :
  (utilisez "git reset HEAD <fichier>..." pour désindexer)

      renommé :   README.md -> README
      modifié :   CONTRIBUTING.md

La commande est rappelée lors du git status.

$ git reset HEAD CONTRIBUTING.md
Modifications non indexées après reset :
M       CONTRIBUTING.md

Réinitialiser un fichier modifié

$ git checkout -- CONTRIBUTING.md
$ git status
Sur la branche master
Votre branche est à jour avec 'origin/master'.
Modifications qui seront validées :
  (utilisez "git reset HEAD <fichier>..." pour désindexer)

          renommé :         README.md -> README
Vous pouvez constater que les modifications ont été annulées.

Git rebase interactif

git rebase --interactif

Permet de réécrire l’histoire, de permuter les commits, de les supprimer, de les fusionner, modifier le message du commit.

Exemple

  • git rebase -i permet de réorganiser les commits depuis le dernier push.

  • git rebase -i HEAD~5 permet de rééditer les 5 derniers commits.

  • git rebase -i master permet de réorganiser les commits de sa branche sur master.

Commandes:

p, pick = utilise le commit sans y toucher
r, reword = édite du message sans changer le commit
e, edit = permet d'éditer les fichiers, de modifier le commit
s, squash = utiliser le commit, en fusionnant le commit précédent
f, fixup = comme "squash", mais rejette le message de ce commit
x, exec = exécute la commande (le reste de la ligne) en utilisant le shell
d, drop = supprime le commit
  • Les lignes de commit peuvent être ré-ordonnées; elles sont exécutées de haut en bas.

  • Si vous supprimez une ligne le commit sera perdu.

  • Si vous supprimez tout les lignes, le rebase sera annulé.

Exercice

  • Effectuez 5 modifications dans vos fichiers avec 5 commits différents.

  • Utilisez la commande git rebase -i pour fusionner les 2 premiers commits.

  • Réécrire le message du 3ème commit.

  • Supprimer le 4ème commit.

Astuce

Au début, si vous avez peur de vous tromper, créez une branche avant de rebaser pour facilement revenir en arrière.

$ git branch avantRebase
$ git rebase -i
...
$ git reset --hard avantRebase

Gérer les interruptions

Remiser votre travail

git stash permet de remiser son travail.

git stash list permet de lister les travaux remisés.

Appliquer le contenue du stash

Au même endroit mais plus tard, ou encore dans une autre branche:

# Pour le dépiler.
$ git stash pop
# En le gardant dans le stash pour l’appliquer
# plusieurs fois.
$ git stash apply

Remisage créatif

git stash --keep-index

L’option --keep-index indique à Git de ne pas remiser ce qui aurait été déjà indexé au moyen de la commande git add.

Défaire l’effet d’une remise

Il n’existe pas de commande stash unapply.

 git stash show -p stash@{0} | git apply -R

Si la remise n’est pas indiquée, Git utilise la plus récente.

Créer une branche depuis une remise

git stash branch teststash

C’est un bon raccourci pour récupérer facilement du travail remisé et pouvoir travailler dessus dans une nouvelle branche.

Nettoyer son espace de travail

Enfin, vous pouvez ne pas souhaiter remiser certain fichiers de votre répertoire de travail, mais simplement vous en débarrasser. La commande git clean -f s’en chargera pour vous.

Faites néanmoins très attention avec cette commande car elle supprime tous les fichiers non-suivis de votre répertoire de travail, sauf les fichiers ignorés.

Les hooks dans Git

Présentation

Les hooks permettent d’automatiser des tâches annexes au versionnage, mais dépendant de celui-ci.

Ceux-ci sont présents dans le répertoire .git/hooks de votre dépôt de travail, et directement dans hooks pour un dépôt bare. Ils consistent simplement en une série de fichiers exécutable ayant le même intitulé que le hook qu’il représente.

Côté client

  • Pre-commit : revue automatique du code à commiter.

  • Prepare-commit-msg : génération du message de commit.

  • Commit-msg : validation du message de commit.

  • Post-commit : notifications.

  • Applypatch-msg : validation du message du patch.

  • Pre-applypatch : validation du contenu d’un patch.

  • Post-applypatch : notification de l’application d’un patch.

  • Pre-rebase : avant d’effectuer un rebase.

  • Post-checkout : après avoir changé de branche.

  • Post-merge : après avoir mergé.

Côté serveur

  • Pre-receive : valide ou non la poussée : vérification de la qualité du code, que l’utilisateur ne modifie pas de fichiers interdits, etc.

  • Post-receive : notification par emails, au logiciel d’intégration continue, ou encore mise à jour du bug tracker, etc.

  • Update : équivalent au hook post-receive, mais avec une segmentation par branche.

Fonctions avancées de Git

Les sous-modules de Git

Concepts

Les sous-modules vous permettent de gérer un dépôt Git comme un sous-répertoire d’un autre dépôt Git. Cela vous laisse la possibilité de cloner un dépôt dans votre projet et de garder isolés les commits de ce dépôt.

Démarrer un sous-module

Pour ajouter un nouveau sous-module, nous utilisons la commande git submodule add avec l’URL du projet que nous souhaitons suivre.

git submodule add https://github.com/hakimel/reveal.js.git

Comme pour git clone nous pouvons préciser un dossier cible.

git status permet de constater la création de 2 entrées:

Sur la branche master
Modifications qui seront validées :
  (utilisez "git reset HEAD <fichier>..." pour désindexer)

        nouveau fichier : .gitmodules
        nouveau fichier : reveal.js

.gitmodules est le fichier de configuration qui stocke la liaison entre l’URL du projet et le sous-répertoire local dans lequel vous l’avez tiré.

cat .gitmodules

[submodule "reveal.js"]
        path = reveal.js
        url = https://github.com/hakimel/reveal.js.git

Si vous avez plusieurs sous-modules, vous aurez plusieurs entrées dans ce fichier.

Cloner un projet avec des sous-modules

Quand vous récupérez un projet avec des sous-modules, vous obtenez les différents répertoires qui contiennent les sous-modules, mais encore aucun des fichiers.

git clone https://monprojet...
git submodule init
git submodule update

ou

git clone https://monprojet...
git submodule update --init --recursive

ou

git clone --recurse-submodules https://monprojet...

Commiter les changements dans un sous-modules

  • S’assurer que vous n’êtes pas dans l’état HEAD détaché

git merge master && git checkout -B master
  • modifier vos fichiers dans le sous-modules et commiter.

  • Pousser les modifications sur le remote.

  • Revenir dans le dossier parent.

  • Commiter le sous-modules.

  • Pousser les modifications.

Limites des sous modules

  • Il est difficiles de fusionner des sous-modules modifiés par 2 développeurs en même temps.

  • Risque de perte de fichier lors d’un commit avant la mise à jour du sous-modules.

  • Nécessite que tous les développeurs connaissent les sous-modules.

  • Beaucoup de commandes à exécuter.

Alternatives aux sous-modules

git cherry-pick

git cherry-pick permet de picorer des commits à droite, à gauche et venir les appliquer dans notre branche.

git worktree

Il est parfois nécessaire de modifier en même temps 2 branches d’un même projet, et nous ne voulons pas sans arrêt lancer la commande git checkout.

$ git worktree add -b mabranche /home/user/dev/TestWorktree
$ git worktree list
/home/user/dev/Projet        6706591 [master]
/home/user/dev/TestWorktree  e2cdd3e [mabranche]

git filter-branch

git filter-branch traite tout l’historique du référentiel à travers les filtres donnés et réécrit les commits si leur contenu est modifié.

Exemple :

$ git filter-branch --tree-filter "rm -f passwords.txt"

git reflog

Comment retrouver un commit que l’on pense avoir définitivement supprimé ?

git bisect

Mes collègues écrivent plein de tests, mais ne les lancent pas à chaque commit. Comment retrouver le commit qui a introduit un bug ?

git blame

Qui a modifié cette ligne de code ? git blame va m’aider à retouver le coupable.

Zut c’est moi :-/

Principaux Workflow Git

Préambule

les workflows présentés ici ne sont que des exemples de ce qui est possible. Ce ne sont pas des règles strictes pour utiliser Git.

Adaptez l’outil à votre façon de travailler, pas l’inverse.

Workflow Centralisé

WorkflowCentralized

Présentation

  • Référentiel central.

  • Migration depuis un VCS centralisé sans changer les habitudes.

  • Chaque utilisateur dispose d’une copie complète du dépôt.

Mise en œuvre

  1. Création d’un dépôt central.

  2. Clone du dépôt par les développeurs.

  3. Les développeurs poussent leurs modifications vers la branche master du dépôt.

  4. Si le dépôt local n’est pas à jour git pull --rebase origin master pour rebaser leur travail et fusionner le travail des autres.

Avantages

  • Workflow simple

  • Idéale pour une transition depuis un VCS centralisé vers un workflow plus complet.

  • Résolution des conflits au fil de l’eau

  • Historique propre et linéaire.

Feature Branch

WorkflowFeature

Branche par fonctionnalité

Présentation

  • Évolution du workflow centralisé

  • Tout développement de fonctionnalités doit avoir lieu dans une branche dédiée au lieu de la branche principale.

  • La branche est fusionnée dans master lorsque le développement de la fonctionnalité est terminé.

Mise en œuvre

  1. Création d’un dépot central.

  2. Les développeurs créent une nouvelle branche à chaque fois qu’ils commencent à travailler sur une nouvelle fonctionnalité.

  3. Une fois la fonctionnalité terminée, ils poussent la branche vers le serveur central et déposent une requête demandant de fusionner leurs ajouts dans master.

  4. La fusion peut être faites par le responsable du projet ou par le développeur.

Avantages

  • La branche master reste propre et fonctionnelle.

  • Adapté au Pull/merge request des outils web de gestion de dépots Git.

  • Facilite l’examen du code avant fusion dans master par d’autres développeurs.

Attention !

  • Rebaser régulièrement son travail pour ne pas trop diverger de master.

Gitflow

WorkflowGitflow

Présentation

  • Évolution du workflow Feature Branch

  • Création de branches ayant des rôles spécifiques (Develop, Release, Feature, Hotfix).

  • Définitions des interactions entre les branches.

  • Seules les branches Hotfix et concernant une Release ont le droit d’être fusionnées dans master.

Mise en œuvre

Branches principales

  • Ce workflow utilise 2 branches pour enregistrer l’historique du projet (master et Develop).

Branches de fonctionnalités

  • Chaque nouvelle fonctionnalité doit résider dans sa propre branche, qui peut être transférée sur le référentiel central.

  • Ces branches doivent utiliser Develop comme branche parent.

Branches de Release

  • Lorsque le code présent dans la branche Develop commence à être prêt, nous créeons une branche correspondant à la release que nous désirons sortir.

  • Une fois la release prête, nous la fusionnons dans master.

  • L’utilisation d’une branche dédiée pour préparer les versions permet à une équipe de peaufiner la version actuelle alors qu’une autre équipe continue à travailler sur les fonctionnalités de la prochaine version.

Branche Hotfix

  • Les branches de maintenance ou «correctif» sont utilisées pour corriger rapidement les versions de production.

  • Dès que le correctif est terminé, il doit être fusionné dans master et develop (ou la branche de release actuelle), et master doit être étiqueté avec un nouveau numéro de version.

Avantages

  • Permet une collaboration efficace dans des gros projets.

  • Extension Git pour faciliter le travail.

  • Documentation en français.

Git Forking

WorkflowForking

Présentation

  • Un référentiel coté serveur par développeur.

  • Chaque contributeur a 2 dépots Git distants: un perso et un officiel.

Mise en œuvre

  1. Fork du projet officiel dans son espace de travail

  2. Clone du fork sur le poste du développeur.

  3. Ajout du projet officiel dans les remotes.

  4. Création d’une branche locale.

  5. Commiter, rebaser depuis le dépot officiel.

  6. Pousser ses modifications sur son reférentiel.

  7. Demander un Pull/merge request.

Avantages

  • Workflow par défaut des projets Opensource sur Github, Bitbucket, GitLab…

  • Tout le monde peut participer à un projet public (pas besoin d’accès en écriture).

Les plate-formes d’hébergement de dépôts Git

Github

  • Site: https://github.com

  • Premier site d’hébergement de dépôt Git (40 millions d’utilisateurs en janvier 2020).

  • Gratuit pour un nombre illimité de dépôts publics (+ 28 millions).

  • Nombre illimité de développeurs par projet.

  • Payant pour les projets privés.

  • Réseau Social du développeur.

  • Fonctionnalités: https://github.com/features

  • Racheté par Microsoft en juin 2018.

Bitbucket

GitLab

  • Site: https://gitlab.com (téléchargement & plate-forme)

  • La version CE est opensource.

  • Intégre une solution complète de CI/CD.

  • Version auto-hebergé et Saas.

  • 3 niveaux de licences : Free, Premium et Ultimate.

  • Fonctionnalités: https://about.gitlab.com/features/

  • Version Ultimate gratuite pour former des étudiants.

Fin