Informations

Cours GIT : révision des commandes de base; Principe de git flow et hooks

% Git - Niveau2
% Manuel Tancoigne
% Novembre 2017

Révisions

Pour de l'aide sur une commande git : git <commande> --help

Dossiers et fichiers:

dossier .git : Dossier où sont stockées les informations du dépôt. Il suffit de le supprimer pour enlever Git.

fichier .gitignore : Exceptions (git ls-files --other --ignored --exclude-standard pour la liste des fichiers ignorés.

fichier .gitattributes : Spécifications sur les formats de fichiers (encodage, fin de ligne, etc...)

Autres:

dossier .github : Fichiers de config spécifiques à github.

Configuration avec git config

La configuration peut être faite pour le dépôt, ou être globale pour l'utilisateur courant (avec l'option --global).

git config user.name "name" : Définit le nom pour la signature des commits.

git config user.email "email : Email servant de sugnature aux commits.

Création

git init "dépôt" : Créée un dépot vide du nom de dépôt.

git init . : Créée un dépot dans le dossier actuel.

git clone "adresse" : Clone le dépot de l'adresse spécifiée dans un nouveau dossier

git clone "adresse" "destination : Clone le dépot dans le dossier destination.

Appliquer des changements

git status : Affiche l'état du dépôt

git diff : Affiche les différences non appliquées (hors stage)

git add "fichier" : Applique un changement (stage)

git add . : Ajoute tous les fichiers modifiés à la liste de modifications (stage)

git reset "fichier" : Enlève un fichier de la liste de modifications (unstage)

git diff --staged "fichier" : Affiche les différences entre le fichier stagé et sa dernière version

git commit -m "message" : Créée un commit avec le "message". Seuls les fichiers stagés seront commités

git commit -am "message" : Ajoute tous les fichiers modifiés à la liste de modifs (stage) et créée un commit.

Etiquettes

git tag : Liste des étiquettes

git tag -n : Liste des étiquettes avec messages

git tag -l "v2.5.*" : Liste les étiquettes avec un certain nom

git tag v2.5 : Créée une étiquette sans description (lightweight) sur le commit actuel

git tag v2.5 -m "Nouvelle version" : Créée une étiquette avec une description sur le commit actuel

git tag -a v3 "sha" -m "Version 3 !" : Créé une étiquette sur un commit anterieur correspondant au hash donné

git show "tag" : Affiche les informations de commit sur un tag donné

Déplacement/suppression

git rm "fichier" : Supprime un fichier et applique le changement (stage)

git rm --cached "fichier" : Supprime un fichier de git mais garde le fichier localement. Pratique pour enlever un fichier de git avant de l'ignorer.

git mv "fichier source" "fichier-dest" : Renomme/déplace "fichier source" et applique le changement (stage)

Rembobiner

git reset "commit" : Défait tous les commits après "commit" mais garde les changements locaux.

git reset --hard "commit" : Défait tous les commits après "commit" et ne garde pas les changements.

Historique

git log : Affiche l'historique, version complète

git log --oneline : Affiche l'historique, version condensée.

git log --follow "fichier" : Affiche l'historique de "fichier". Prends en compte les changements de nom.

git diff "branche1" "branche2" : Affiche les différences entre deux branches.

git show "commit" : Affiche les informations relatives à un commit.

git show "etiquette" : Affiche les informations relatives à un commit.

git blame "fichier" (voir 1) : Affiche les personnes ayant modifié chaque ligne d'un fichier.

(1) - Exemple de git-blame "fichier"

007bfcdd (Olive            2017-04-02 22:39:33 +0200  3)     <div class="form-card__body">{{delegate.title}} {{delegate.first_name}} {{delegate.last_name}}</div>
007bfcdd (Olive            2017-04-02 22:39:33 +0200  4)
007bfcdd (Olive            2017-04-02 22:39:33 +0200  5)     <div class="form-card__actions">
0aa7a163 (Manuel Tancoigne 2017-10-23 16:30:34 +0200  6)       <button @click="displayPanel('edit')"><i class="fa fa-pencil"/><span class="visually-hidden">Editer</span>
0aa7a163 (Manuel Tancoigne 2017-10-23 16:30:34 +0200  7)       </button>
0aa7a163 (Manuel Tancoigne 2017-10-23 16:30:34 +0200  8)       <button @click="displayYesNo('delete')"><i class="fa fa-times"/><span class="visually-hidden">Supprimer</span>
0aa7a163 (Manuel Tancoigne 2017-10-23 16:30:34 +0200  9)       </button>
212ce984 (Manuel Tancoigne 2017-03-30 12:32:45 +0200 10)     </div>

Branches

git branch : Affiche les branches et la branche actuelle (avec un *) (voir 2))

git branch -v : Affiche les branches et leurs derniers commit (voir 3)

git branch "nom" : Créée une nouvelle branche

git checkout "branche" : Se place sur la branche "branche" et met à jour les fichiers. Garde les changements si possible

git checkout -b "branche" : Créée une nouvelle branche et se place sur celle-ci.

git branch -d "branche1" : Supprime la "branche1", localement si elle a été mergée.

git branch -D "branche1" : Supprime la "branche1", localement même si elle n'a pas été mergée.

(2) - Exemple de git branch

  dev
  feature/newgui
  fix/Important
* master
  olive
  release/1.2.0

(3) - Exemple de git-branch -v

  dev            3129407 Updated roadmap and changelog
  feature/newgui ab10ccc Updated changelog and version
  fix/Important  2e21708 Fixed modal structure for v-bar
* master         3129407 Updated roadmap and changelog
  olive          c884b63 WS tests
  release/1.2.0  84c2708 Updated roadmap

Combinaison de branches

git merge "branche" : Combine la branche spécifiée dans la branche courante.

git merge "branche1" "branche2" : Combine la "branche1" dans la "branche2"

git merge --no--ff : Force la création d'un merge commit lors de la combinaison de branche. Pratique pour garder une trace (ex: pour une fin de tâche spécifique par exemple)

git merge --ff-only : Ne combine les branches que s'il n'y a pas besoin de créer de commit (ex: s'il n'y a pas de conflit à gérer)

Manipulation de commits

git rebase --interactive --autosquash HEAD~N : Fusionne N commits pour n'en faire qu'un

git cherry-pick -n "sha" : Incorpore le commit avec le hash donné

git revert -n "sha" : Créée un commit qui annule le commit avec le hash donné

Synchronisation distante

git remote -v : Liste les differentes copies distantes enregistrée;

git remote add "url" : Ajoute une référence vers une copie distante.

git fetch "remote" : Télécharge l'historique d'une copie distante. Ne change rien au dépôt local

git fetch "remote" "branche" : Télécharge l'historique d'une branche donnée d'une copie distante. Ne change rien au dépôt local

git merge "remote"/"branche" : Combine une branche distante dans la branche courante.

git push : Envoie les derniers commits de la branche actuelle sur la remote principale

git push "remote" : Envoie les derniers commits de la branche actuelle sur la remote spécifiée

git push "remote"/"branche" : Envoie les derniers commits de la branche actuelle sur la branche spécifiée de la remote spécifiée...

git pull : Récupère et applique les changements provenant de la remote principale

git pull --rebase : Récupère les changements provenant de la remote principale et applique les vôtres.

Git-flow

Git flow est une méthode de travail permettant de standardiser son flux de versions:

  • Fonctionnalités
  • Releases
  • Hotfixes

La branche principale est la branche master; elle est stable et doit pouvoir être poussée en prod

La branche de travail est develop ou dev; c'est elle qui va acueillir les nouveautés

Fonctionnalités:

Une fonctionnalité, ou feature commence obligatoirement à partir de la branche de développement. Elle doit avoir un nom commençant par feature/

Bien que les fonctionnalités sont généralement uniquement locales, elles peuvent tout de même être partagée comme une branche standard aux autres développeurs.

# On part de dev
git checkout dev
# On créée la fonctionnalité et on bascule sur la nouvelle branche
git checkout -b feature/mailer

Une fois terminée, la fonctionnalité doit être combinée à la branche de développement avec un commit. Celà permet de garder un arbre de versionning propre, tout en gardant la trace des actions liées à une fonctionnalité donnée.

La feature doit ensuite être supprimée, afin d'éviter les futures erreurs.

# ... On a fait plein de commits

# On rebascule sur dev
git checkout dev
# On merge avec un commit
git merge feature/mailer --no-ff
# On supprime ensuite la branche:
git branch -d feature/mailer

Hotfixes

Les hotfixes sont des branches partant de master, destinées à corriger un bug en production. Elles doivent avoir un nom commençant par hotfix/.

# On part de master
git checkout master
# On créée le hotfix et on bascule sur la nouvelle branche
git checkout -b  hotfix/bug-login

Une fois terminé, le hotfix doit être mergé au master (et étiquetée) et à la branche de développement. Chaque développeur pourra ensuite l'incorporer à ses propres fonctionnalités.

La branche du hotfix sera ensuite supprimée.

# ... On a fait plein de correctifs

# On rebascule sur master
git checkout master
# On merge avec un commit
git merge hotfix/bug-login --no-ff
# On créée l'étiquette
git tag bug-login -m "Correctif bug login"
# On merge avec dev:
git checkout dev
git merge hotfix/bug-login --no-ff
# On supprime ensuite la branche:
git branch -d feature/mailer

Attention, ne pas oublier de pousser l'étiquette : git push --tags

Releases

Les realeases sont des branches préparant une nouvelle version. Elles permettent de finaliser le développement et de corriger les bugs restants lorsque toutes les fonctionnalités d'une version sont prêtes. Elles sont donc créées à partir de la branche de développement et doivent commencer par release/.

# On a fini les features nécessaires

# On passe sur dev
git checkout dev
# On créée la branche de release et on bascule dessus
git checkout -b release/v1.0.0

Une fois terminée, la release est mergée au master avec un merge-commit. Une étiquette est ensuite associée à ce commit pour le référencer. Puis, la branche est mergée à dev.

# On a fait les modifs nécessaires sur la branche de release

# On passe à master
git checkout master
git merge release/v1.0.0 --no-ff
# On créée l'étiquette
git tag v1.0.0 -m "Version 1 terminée"
# On merge dans dev
git checkout dev
git merge release/v1.0.0 --no-ff
# On supprime la branche
git branch -d release/v1.0.0

Attention, ne pas oublier de pousser l'étiquette : git push --tags

Outils

Il existe un outil, git flow permettant de réaliser ces taches de manière plus rapide. Il est généralement intégré aux clients git type SourceTree, GitKraken ou SmartGit.

Git hooks

Les hooks sont des scripts lancés avant ou après qu'un commit ait eu lieu. Il permet :

  • d'interagir sur le commit et de bloquer sa validation (ex: messages trop courts, fautes, tests unitaires)
  • déclencher des actions si le commit est validé (ex: passage en production)

Ce sont des scripts placés dans .git/hooks, et chaque dépôt vide est initialisé avec des exemples:

pre-commit.sample:

#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments.  The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
[...]

Format des fichiers

Les fichiers de hook sont executables, il faut donc vérifier leur permission (chmod +x). De plus tous les fichiers se terminant par .sample sont ignorés.

Les fichiers de hook n'ont pas d'extension; l'interpréteur est déterminé par le shebang du fichier et il est tout à fait possible d'utiliser des langages de programmation plus poussés que le simple shell (ex: #!/usr/bin/env python pour un hook en python).

Portée

Les hooks sont locaux: ils ne sont pas commités et partagés entre les dépôts. Ce qui veut dire que vous ne pouvez forcer personne à les utiliser.

Hooks locaux

Les hooks "locaux" sont uniquement utilisés sur les clients (sur les machines des développeurs). Ils servent généralement à aider le développeur dans ses tâches

  • pre-commit (juste avant que git ne demande un message lors d'un commit)
  • prepare-commit-msg (prépare le message de commit)
  • commit-msg (Juste après que le message soit entré. Peut stopper le commit)
  • post-commit (Ne peut pas stopper le commit. Sert principalement de notification)
  • post-checkout (juste après git-checkout. ex: supprimer une build avant màj)
  • pre-rebase (Juste avant git rebase)

Hooks serveur

Les hooks serveur sont uniquement utilisés sur les serveurs git (type GitHub, BitBucket,...). Ils servent à tester et rejeter des commits ne correspondant pas aux standards voulus (style du code, tests non validés, etc...). Les messages d'erreur sont renvoyés au client, ce qui lui permet de comprendre ce qu'ils se passe en cas de problème. (note: tant que le serveur n'a pas envoyé de réponse, le terminal utilisateur est bloqué...)

  • pre-receive (sur git push)
  • update (après le pre-receive)
  • post-receive (en fin de git push, lors d'un succès)

Templates

Il est possible de créer des templates pour le dossier .git (par défaut: /usr/share/git-core/templates).

Pour utiliser un template lors de la création d'un dépot, utiliser l'option --template="chemin/vers/le/dossier/de/template". Si --template n'est pas défini, git va regarder dans les dossiers suivants :

  • --template
  • $GIT_TEMPLATE_DIR si défini
  • init.templateDir (défini avec git config --global init.templateDir="chemin")
  • le dossier par défaut, /usr/share/git-core/templates

Liens

Add comment