Git est un logiciel de gestion de versions. Il permet de suivre l’évolution d’un fichier (version 1, version 2, version 3, etc), de savoir qui a effectué chaque modification, quand et pourquoi, et de revenir en arrière en cas de problème.
Il permet également de travailler à plusieurs sur des fichiers, sans risquer que les modifications d’une personne efface les modifications d’une autre.
OS | Installation |
---|---|
Windows/Mac | Installer Gitbash |
Linux | sudo apt-get install git |
Certaines commandes git prennent en paramètre un type tree-ish.
Un objet “tree-ish” désigne une arborescence à un instant de l’historique.
Quelques exemples :
Exemple | Description |
---|---|
1ff91bf13a6d5461a85ad44f4cbacd77ee6c4917 | SHA du commit |
1ff91bf1 | SHA abrégé (non ambigu, au moins 4 caractères) |
HEAD | Pointeur en cours |
master | Branche master |
v0.99.8 | Tag v0.99.8 |
HEAD^, acf87505^, master^ HEAD~1, HEAD~ | Le parent de... |
HEAD^^ HEAD~2 | Le grand-parent de... |
HEAD^^^ HEAD~3 | L'arrière grand-parent de... |
La première étape est d’ajouter git au répertoire dont les fichiers doivent être versionnés, puis de versionner les fichiers lorsqu’ils sont prêts.
cd monrepertoire
git init
git status
git diff
git add --all
git status
git commit -m "Init"
Pour afficher la man page d’une commande git, utiliser git help cmd
. Exemple: git help init
. On peut obtenir le même résultat en tapant man git-init
.
git init
permet d’initiliser git pour le répertoire courant et ainsi de versionner les fichiers qui s’y trouvent.
Crée un répertoire .git
, où seront enregistrés les commits (= différentes versions) des fichiers.
git init | Initialise git pour le répertoire courant |
---|
Quand des fichiers ont été modifiés dans un répertoire versionné (= qui contient un répertoire .git), il faut pour enregistrer une version
git add file.txt | Ajoute file.txt au staging area |
---|---|
git add -u | Tous les fichiers modifiés et supprimés (mais pas les nouveaux) |
git add . git add --all | Tous les fichiers ajoutés, modifiés et supprimés |
git add mydir/ | Tous les fichiers dans le répertoire mydir |
git add *.txt | Tous les fichiers .txt dans le répertoire courant (avec l'expansion du shell) |
git add '*.txt' | Tous les fichiers .txt dans tout le projet (avec l'expansion de git) |
Git est conçu pour mémoriser les versions de fichiers, pas les répertoires. Les répertoires vides sont donc ignorés et ne peuvent pas être versionnés. Par convention, pour versionner un répertoire vide on y place un fichier .gitkeep
vide.
git rm file.txt
permet de supprimer un fichier. Le fichier pourra être récupéré via un checkout d’un commit antiérieur.
git rm file.txt | Supprimer file.txt du disque et de git (ou uniquement de git si supprimé manuellement) |
---|---|
git rm --cached file.txt | Supprimer file.txt de git mais pas du disque |
git mv oldname newname
permet de renommer et/ou déplacer un fichier
git mv file.txt newfile.txt | Renommer file.txt en newfile.txt |
---|
Notons qu’on peut obtenir le même résultat avec rm suivit de add. Git compare les données entre les deux fichiers et en déduit qu’il s’agit d’un déplacement ou non. Les fichiers n’ont pas a être identiques, le seuil de tolérance est d’environ 50%.
mv file.txt newfile.txt
git rm file.txt
git add newfile.txt
git status
liste les fichiers qui ont été modifiés depuis le dernier commit (ajoutés, modifiés et supprimés). Indique lesquels sont dans le staging area (= ceux qui ont été marqués pour faire partie du prochain commit) ou non.
git status | Affiche les fichiers modifiés depuis le dernier commit |
---|---|
git status -s | Affiche les fichiers modifiés de manière condensée |
$ git status
Changes to be committed:
(use "git reset HEAD ..." to unstag)
modified: this.txt
Untracked files:
(use "git add ..." to include in what will be committed)
that.txt
$ git status -s
M this.txt
?? that.txt
git diff
affiche les modifications apportés aux fichiers depuis le dernier commit.
Par défaut, les fichiers dans le staging area ne sont pas affichés.
git diff | Affiche les modifications des fichiers |
---|---|
git diff --staged | Affiche les modifications des fichiers dans le staging area |
git diff file.txt | Affiche les modifications du fichier file.txt |
git diff --color-words file.txt | Affiche les modifications du fichier file.txt ligne par ligne |
git diff HEAD^^ | Affiche les modifications depuis l'avant-dernier commit |
git diff HEAD^..HEAD | Entre le dernier et l'avant-dernier commit |
git diff f5a6..4sdsd | Entre les deux commits donnés |
git diff master cat | Entre les branches master et cat |
# Dans file.txt, sur la ligne 1, "Hello World" est devenu "Hello Everybody" :
$ git diff
--- a/file.txt
+++ b/file.txt
@@ -1 +1 @@
-Hello World
+Hello Everybody
$ git diff --color-words file.txt
--- a/file.txt
+++ b/file.txt
@@ -1 +1 @@
Hello WorldEverybody
# Vérifier si le fichier Dockerfile ou requirements.txt
# Ont changés depuis le tag staging-1.0
git diff staging-1.0..HEAD -- Dockerfile requirements.txt
Setter l’option git config color.ui true
pour que diff affiche des couleurs
git show
permet d’afficher le contenu d’un commit donné
git show f5a6
git commit -m "message"
permet de commiter les fichiers du staging area.
Le message de log doit expliquer brièvement à quoi sert le commit.
git commit -m "about" | Commite les fichiers dans le Staging area, avec le message de log "about" |
---|---|
git commit -am "about" | Raccourcis pour git add .; git commit Rappel: ajoute les fichiers modifiés, mais pas les nouveaux ni supprimés |
Il est également possible d’ajouter les modifications au dernier commit avec l’option --amend
. C’est utile si l’on a oublié d’ajouter des fichiers au staging area. Cette méthode modifie le SHA et la date du commit.
NB Pour modifier un commit plus ancien que le dernier, il faut créer un nouveau commit (et éventuellement utiliser un rebase
pour rassembler plusieurs commits)
git commit --amend -m "message" | Modifie le message et/ou les fichiers du dernier commit |
---|
Quand ils versionnés, il est possible de récupérer les fichiers tels qu’ils étaient lors d’une ancienne version, de voir qui a fait des modifications et pourquoi.
git log
git checkout 1ff91bf1
git log
liste tous les commits effectués, du plus récent (en haut) au plus ancien (en bas).
Seule la première ligne du message de commit est affichées (moins de 50 caractères).
git log | Affiche tous les commits |
---|---|
git log -n 2 | Affiche les 2 derniers commits |
git log -- file.txt | Les commits qui ont affectés le fichier file.txt |
git log --oneline | Affiche les commits en version condensée |
git log -p | Affiche les commits et leurs diffs |
git log --stat | Affiche les commits et leur statut (x file changed, x insertion, x deletion) |
--since=2001-01-02 | Commité après le 02/01/2001 |
---|---|
--since=1.day.ago | Depuis hier |
--since="1 year 6 months ago" | Depuis un an et demi |
--until=2001-01-02 | Avant le 02/01/2001 |
--author=Charlie | Commité par Charlie |
--author="Alice\|Bob" | Par Alice ou Bob |
--grep="Init" | Commit dont la description contient "Init", sensible à la casse |
-i --grep="Init" | Dont la description contient "Init", insensible à la casse |
Format date :
(last|next) (second|minute|hour|day|week|month|year)
(X (seconds|minutes|hours|days|weeks|months|years))+ ago
(yesterday|tomorrow)
@XXXXXXXXX (= since epoch)
info date
pour plus de détails (Entrée pour suivre un lien, q pour quitter)
$ git log
commit bcb29516a61cbdf6c8d6eb85d12376344f693cd3
Author: username
Date: Tue Nov 29 19:52:45 2016 +0100
2
commit 6160e8d5ef1c2c2fb78d9af986d440d499220bbe
Author: username
Date: Tue Nov 29 19:24:26 2016 +0100
Init
$ git log --oneline
bcb2951 2
6160e8d Init
$ git log --pretty=format:"%h %ad - %s [%an]"
bcb2951 Tue Nov 29 19:52:45 2016 +0100 - 2 [username]
6160e8d Tue Nov 29 19:24:26 2016 +0100 - Init [username]
$ git log --pretty=format:"%C(white reverse blue bold)%h%Creset %s"
# Affiche le hash en bleu foncé sur fond blanc
bcb2951 2
6160e8d Init
Instructions pretty format :
%ad | author date |
---|---|
%an | author name |
%h | SHA hash abrégé |
%s | subject |
%d | description |
%C(colors) | switch color Couleurs : normal, black, red, green, yellow, blue, magenta, cyan, white Attributs : bold, dim, ul (underline), blink, reverse (swap foreground and background) |
%Creset | reset color |
git help log
pour la doc complète (/PRETTY FORMATS
+ entrée + n
)
git blame file.txt
permet d’afficher l’historique de modification du fichier file.txt, ligne par ligne, avec la date et l’auteur de la modification.
Le format de sortie est le suivant : <hash> (<author> <date> <line>) <content>
.
git blame file.txt | Affiche l'historique des modifications du fichier file.txt |
---|---|
git blame file.txt --date short | Affiche uniquement la date (pas l'heure) |
$ git blame --date short file.txt
96776 (Gregg 2012-06-29 9) Hello
git checkout tree-ish
permet de récupérer les fichiers d’un commit antérieur
git checkout v0.0.1 | Récupère les fichiers du commit taggé v0.0.1 |
---|---|
git checkout bbd70e01 -- file.txt | Le fichier file.txt tel qu'il était au commit bbd70e01 |
git checkout -- file.txt | Le fichier file.txt du dernier commit (= supprime les modifications locales) |
git checkout mybranch | Les fichiers de la branch mybranch |
git revert commit
permet d’inverser les modifications d’un commit.
L’annulation est commitée tout de suite, sans possibilité de modifier.
Si des fichiers ont été renommés ou déplacés, une technique plus avancée sera nécessaire (merge)
git revert bbd70e01 | Annuler les modifications de la révision bbd70e01 |
---|
À chaque fois que le pointeur HEAD bouge (commit, checkout, reset, etc), une entrée est ajoutée dans le reflog. Un reflog est local à un projet et à une machine.
git reflog | Affiche le reflog |
---|
$ git reflog
43c13e7 HEAD@{0} reset: moving to 43c1
1e62107 HEAD@{1} commit: Add third section
Le reflog est utile pour connaître le SHA des commits ou branches supprimés et de pouvoir ainsi les récupérer.
# Récupérer un commit
git reset --hard 1e62
# Récupérer une branche
git branch my_branch 280e
git clean
permet de gérer les fichiers non versionnés
git clean -n | Lister tous les fichiers non versionnés (ni staging area ni commits) |
---|---|
git clean -f | Supprimer tous les fichiers non versionnés |
git ls-tree tree-ish
liste tous les fichiers commités à un instant donné.
Le format de sortie est le suivant: <mode> <type> <refname> <path>
(blob = fichier, tree = répertoire)
git ls-tree HEAD | Liste tous les fichiers commités (à la racine) |
---|---|
git ls-tree -r HEAD | Liste tous les fichiers commités à la racine et dans les sous-répertoires |
git ls-tree HEAD^ | Liste tous les fichiers qui étaient commités lors de l'avant-dernier commit |
git ls-tree master assets/ | Liste tous les fichiers dans le répertoire assets/ de la branche master |
$ git ls-tree HEAD
100644 blob badbc02f6c1a754631baa23fc51d58df8276b359 .gitignore
100644 blob e01bb431533191a62ec6c2d85b439cec2e7a2cdc _config.yml
040000 tree 2eb76a49dd221f11c93a51d0a7a4a8eee35e1446 assets
git filter-branch
permet de supprimer des fichiers de l’historique, par exemple pour supprimer des données sensibles (mots de passe), des fichiers binaires lourds ou des fichiers qui violent un copyright.
filter-branch fait un checkout de chaque commit, exécute la commande shell donnée, et re-commit. À noter que
rm -f
index-filter
). Dans ce cas il n’est pas possible d’utiliser des commandes shell mais uniquement dans commandes gitgit filter-branch --tree-filter 'cmd' -- --all | Executer cmd (commande shell) sur tous les commits de la branche |
---|---|
git filter-branch --tree-filter 'cmd' -- HEAD | Executer cmd (commande shell) sur le dernier commit |
git filter-branch --index-filter 'cmd' | Executer cmd (commande git) sur tous les commits |
Exemples :
# Supprimer le fichier password.txt dans les commits de la branche, via rm (shell)
git filter-branch --tree-filter 'rm -f password.txt' -- --all
# Supprimer le fichier password.txt dans les commits de la branche, via git
git filter-branch --index-filter 'git rm --cached --ignore-unmatch passwords.txt'
# Supprimer le fichier password.txt dans le dernier commit
git filter-branch --tree-filter 'rm -f password.txt' -- HEAD
Après des suppressions de fichier, il arrive que des commits ne contiennent plus aucune modification.
L’option prune-empty
permet de les supprimer.
Exemples :
# Supprimer les commits qui ne modifient aucun fichier
git filter-branch --f --prune-empty -- --all
# Supprimer le fichier password.txt et supprimer le commit s'il est vide
git filter --tree-filter 'rm -f password.txt' --prune-empty -- --all
git reset tree-ish
permet d’annuler des modifications ajoutées au staging area et/ou aux fichiers. Pour ce faire, on déplace HEAD (pointeur qui désigne le dernier commit de la branche en cours), donc on altère l’historique.
git reset --soft bbd70e01 | Déplace HEAD à la révision bbd70e01, sans changer le staging area ni les fichiers locaux En cas de commit, tous les commits qui suivent bbd70e01 sont supprimés - mais les modifications se retrouvent dans le nouveau commit |
---|---|
git reset --mixed bbd70e01 | Déplace HEAD à la révision bbd70e01, calque le staging area sur cette révision sans changer les fichiers locaux Appliqué à HEAD, il annule l'ajout des fichiers au staging area. Mixed est le comportement par défaut de reset. |
git reset --hard bbd70e01 | Déplace HEAD à la révision bbd70e01, calque le staging area et les fichiers locaux dessus ATTENTION, les modifications locales des fichiers sont définitivement perdues |
Le log affiché par git log
affiche les commits jusqu’à HEAD. Pour replacer le HEAD à un commit ultérieur après un reset (tant qu’on a pas commité les modifications), on utilise git reflog
afin de récupérer le SHA du commit voulu et faire un reset dessus.
Git peut être configuré: retenir le nom d’utilisateur et mot de passe, créer des alias, colorer l’interface, etc. Les configurations de Git peuvent être appliquées à tous les utilisateurs, à un seul utilisateur, ou sur un projet en particulier.
Ces configurations sont enregistrées dans des fichiers, qui peuvent être édités directement avec un éditeur de texte, ou en utilisant des commandes git (qui modifient les fichiers de configuration). Si deux fichiers définissent une même configuration, le local écrase le global.
Portée | Description | Commande (préfixe) | Path Linux | Path Windows | |
---|---|---|---|---|---|
Système | S’applique à tous les utilisateurs | git config –system | /etc/gitconfig | Program Files\Git\etc\gitconfig | |
Utilisateur | S’applique à un seul utilisateur | git config –global | ~/.gitconfig | $HOME\.gitconfig | |
Projet | S’applique à un projet | git config | myproject/.git/config | myproject\.git\config |
git config --global --list | Liste les configurations globales |
---|---|
git config --local --list | Liste les configurations locales |
git config --list | Liste les configurations globales (en premier) et locales |
git config --global user.name | Affiche la valeur de la config globale |
git config --local user.name | Affiche la valeur de la config locale |
git config user.name | Affiche la valeur de la config qui s'applique |
git config --global user.name "username" | Met à jour la valeur de la config globale |
git config --global alias.olog "log --oneline" | Définit un alias "olog" |
Quelques configs utiles :
Globales :
user.name "username" Nom d'utilisateur
user.email "bob@exemple.com" Email
core.editor "vim" Editeur de texte à utiliser
color.ui true Colorer l'interface
Locales :
core.autocrlf input Changer les retours chariots CR/LF à LF au commit
core.autocrlf true Changer les retours chariots LF à CR/LF au checkout
push.default matching Pusher toutes les branches
push.default simple Pusher la branche en cours (comportement par défaut avec Git 2.0)
pull.rebase true Utiliser automatiquement rebase au pull (git pull --rebase)
rerere.enabled true Activer reReRe (Reuse Recorded Resolution)
Alias :
Un alias peut s’appeler comme une commande git native, par exemple git olog
.
Pour définir un alias :
git config --global alias.plog "log --pretty=format:'%h %s [%an]' --graph"
git config --global alias.lol "log --graph --decorate --pretty=oneline --abbrev-commit --all"
Les attributs sont des configs de conversion des retours chariot. L’intérêt des attributs est qu’ils sont communs à toute personne qui participe au projet, contrairement aux configurations qui sont locales à une machine (puisqu’elles ne sont pas commités). Les attributs sont définis dans un fichier .gitattributes
, à la racine du projet.
text=auto | Choisir la conversion automatiquement (par défaut) |
---|---|
binary | Ne faire aucune conversion |
text | Convertir au retour chariot de l'OS au checkout, convertir à LF au commit |
text eol=crlf | Convertir à CR/LF au checkout, convertir à LF au commit |
text eol=lf | Convertir à LF au commit |
Exemple :
* text=auto
*.html text
*.css text
*.bat text eol=crlf
*.sh text eol=lf
*.jpg binary
*.png binary
Il est également possible d’indiquer à git d’ignorer des fichiers, pour qu’il ne les affiche plus dans la liste des fichiers non versionnés.
La liste des fichiers à ignorer est placée dans un fichier .gitignore
à la racine du projet (commun entre tous les développeurs).
Les fichiers déjà versionnés ne sont pas ignorés, même s’ils obéissent à la règle.
Exemple :
*.log
npm-debug.log*
.grunt
bower_components
node_modules/
.env
Sont généralement ignorés
Listing des fichiers à ignorer selon le language / frameword / OS
Local au projet :
Même principe que le fichier .gitignore
mais non versionné, le fichier .git/info/exclude
contient la liste des fichiers à ignorer (à partir de la racine du projet).
Global :
Une liste de fichiers à ignorer globale peut également être mise en place (qui se cumule au .gitignore).
Elle doit être activé via les configs :
git config --global core.excludesfile ~/.gitignore | Définit l'emplacement du exclude global |
---|
Permet de modifier l’index du fichier dans git. Les modifications apportés sur l’index ne sont pas commités. Cette commande est particulièrement utile pour “geler” (freeze) le contenu de certains fichiers (que les modifications apportées au fichier soient ignorées par git), par exemple les fichiers de configuration.
git update-index --assume-unchanged foo.rb | Ignore les changements de foo.rb. Le contenu du fichier est écrasé au pull. Utile lorsqu'on part du principe que le développeur ne va pas changer ce fichier (ex: package-lock.json ) |
---|---|
git update-index --no-assume-unchanged foo.rb | Supprime l'entrée assume-unchanged pour foo.rb |
git update-index --skip-worktree foo.rb | Ignore les changements de foo.rb. Le contenu du fichier est conservé au pull. Utile lorsqu'on part du principe que le développeur va changer ce fichier mais ne va pas commiter les changements (ex: docker-compose.yml ) |
git update-index --no-skip-worktree foo.rb | Supprime l'entée skip-worktree pour foo.rb |
Utiliser un serveur distant permet de partager des fichiers versionnés avec d’autres personnes, et qui peuvent éventuellement modifier ces fichiers. Les serveurs les plus connus sont Github et BitBucket (serveurs herbégés), Gitotis et Gitorious (serveurs auto-gérés).
Utiliser un serveur distant n’est absolument pas une obligation, le versionning peut complètement être gardé en local, dans le répertoire .git
.
git clone http://github.com/username/myproject.git
git pull origin master
git push -u origin master
git clone url
permet de récupérer en local un projet situé sur un serveur distant, qui a été crée au préalable sur ce serveur.
Par défaut, seule la branche principale (généralement master) est téléchargée.
Un projet versionné peut être envoyé à différents serveurs (ex: serveur de versioning Github et serveur de production Heroku). Pour cette raison un projet peut être associé à plusieurs URL, auxquelles on donne un raccourcis nommé - ce qui permet de facilement envoyer et récupérer les modifications d’un projet distant en local3.
Git crée automatiquement un raccourcis vers l’URL du projet lorsqu’on clone un projet, qui s’appelle “origin” par défaut (on peut le nommer autrement).
git clone http://github.com/username/myproject.git | Créer un répertoire myproject et télécharge le contenu du projet dedans |
---|---|
git clone http://github.com/username/myproject.git feature | ...en nommant le raccourci "feature" |
git clone -b 00_start http://github.com/username/myproject.git | Récupère la branche 00_start plutôt que master |
Pour télécharger toutes les branches :
mkdir projectname
cd projectname
git clone --mirror http://github.com/username/projectname/file.git .git
git config --bool core.bare false
git reset --hard
Pour supprimer le versioning du projet téléchargé (par exemple pour l’utiliser comme template) :
rm -drf .git
git remote
permet de gérer les raccourcis d’URL pour les projets distants.
git remote -v | Liste les raccourcis d'URL connus pour le projet en cours |
---|---|
git remote add origin | Crée un raccourcis "origin" pour l'URL "http://github.com/username/myproject.git" |
git remote rm name | Supprime le raccourcis "name" |
git fetch
récupère les modifications du projet distant.
Les modifications sont importées dans des branches temporaires, ce qui donne la possibilité de comparer les différences et si besoin de les importer dans la branche normale.
Permet par exemple de vérifier si de nouvelles branches ont été ajoutées.
git fetch | Récupère les modifications du dépot distant sans mettre à jour les fichiers locaux (branche temporaire) |
---|---|
git fetch origin master | ...de la branche master uniquement |
Pour voir les différences entre la branche master
temporaire et la branche locale :
git log master..origin/master
Pour récupérer les modifications :
git checkout master
git merge origin/master
git pull
permet de récupérer les modifications du projet distant en local en une fois (git pull = git fetch + git merge
).
Il est déconseillé d’utiliser un pull tant qu’il y a des modifications locales non commitées.
git pull | Récupère les modifications du dépot distant dans la copie locale |
---|---|
git pull origin master | ...de la branche master uniquement |
git pull --rebase | Récupère les modifications du dépot distant en utilisant un rebase |
Si lors d’un git pull
, utilisé avant git commit
, des modifications locales entrent en conflit avec les modifications distantes (on essaie de modifier une même ligne) alors les deux versions sont gardées dans le fichier avec le format suivant :
<<<<<<< HEAD
the cake is a lie. # Version locale
=======
the cake is telling the truth! # Version distante
>>>>>>>
4e7d3542...
Il est nécessaire d’éditer le fichier en conflit puis de commiter pour marquer le conflit comme résolu.
git pull
vim index.html # Editer le conflit
git commit -am "message" # Commiter les fichiers modifiés
git push
permet d’envoyer les modifications du projet local sur le serveur distant.
git push -u origin master | Envoie les modifications sur la branche master du serveur origin (et garde cet emplacement en mémoire) |
---|---|
git push | ... au dernier emplacement enregistré (1) |
git push heroku-staging staging:master | ... de la branche locale staging à la branche distante master du serveur heroku-staging |
(1) Il est donc nécessaire d’utiliser git push -u remote branch
au moins une fois
Mettre en cache son mot de passe
Le fichier README.md est un simple fichier Markdown situé à la racine du projet, qui est affiché par Github lorsqu’on accède au dépot distant via github.com. Il doit contenir une courte introduction/résumé qui explique le projet.
La syntaxe utilisée est Github Flavored Markdown.
Les fichiers sont commités ensemble lorsqu’ils sont fonctionnels et peuvent faire l’objet d’une nouvelle version (images, css, js, code, etc). Cela peut poser problème lorsqu’on travaille sur plusieurs fonctionnalités en même temps, pour retrouver quels fichiers devraient être commités ensemble. Il est également difficile de créer des “savepoints” pour revenir en arrière si nécessaire, lorsqu’on travaille sur de grosses modifications. Utiliser des branches permet de résoudre ces problèmes.
Une branche est créée à partir d’une branche d’origine et contient tous les fichiers et l’historique de la branche d’origine jusqu’à ce point. Une fois créée, les fichiers et l’historique de cette nouvelle branche peuvent être modifiés de manière indépendente des autres branches.
git branch
permet de lister les branches ou d’en créer, renommer, supprimer.
Il existe au minimum une branche, la branche par défaut, nommée “master”.
git branch | Liste les branches locales (1) |
---|---|
git branch -r | Liste les branches distantes (2) |
git branch -a | Liste toutes les branches |
git branch app01 | Crée branche app01 à partir de la branche en cours (sans changer la branche active) |
git branch -m v1 app01 | Renomme la branche v1 en app01 |
git branch -d alternate | Supprime la branche locale app01 (3) |
git branch -D alternate | Supprime la branche locale app01 même s'il y a des changements non commités |
(1) L’étoile à gauche indique la branche locale.
Les branches non commitées sont entourées de parenthèses
$ git branch
* (HEAD detached from bbd70e01)
master
(2) Ne requête pas le serveur pour vérifier les branches.
Pour voir les nouvelles branches, il faut d’abord utiliser un git fetch
ou git pull
.
Sinon, utiliser git remote show origin
(3) Pour supprimer la branche distante et non la branche locale: git push origin :app01
Si on essaie d’utiliser une branche supprimée sur le serveur distant, une erreur est retournée (stale).
Pour supprimer en local les branches supprimées sur le serveur distant, utiliser git remote prune origin
git checkout
permet de changer de branche active.
En changeant de branche active, les fichiers du répertoire sont mis à jour/ajoutés/supprimés pour refléter l’état de la branche. Il faut donc d’abord commiter ses modifications avant de changer de branche (ou utiliser le stashing).
git checkout app01 | Passe la branche actuelle à app01 (la télécharge si elle n'est pas disponible localement) |
---|---|
git checkout -b admin | Crée la branche admin et se place sur cette branche |
git checkout -b 02_01 origin/02_01 | Télécharge la branche origin/02_01 comme 02_01 et se place sur cette brancge |
git merge mybranch
prend les changements de mybranch
et les apporte à la branche courante.
Crée un “merge commit” dans la branche courante.
Elle est utilisée après un git fetch
pour inclure les changements de la branche temporaire dans la copie locale du projet.
git merge app01 | Merge la branche app01 dans la branche courante |
---|
git rebase
permet d’appliquer les modifications d’une autre branche sur la branche locale. Avec merge
, on aurait un seul commit (message du commit: “merge my_branch into master”). Avec rebase
, on récupère la liste de commits :
git rebase master | Apporte les commits de la branche courante à la branche master |
---|---|
git rebase --continue | Reprend le rebase après que le conflit ait été rectifié |
git rebase --abort | Annule le rebase (en cas de conflit), revient à l'état du dépot avant la tentative de rebase |
Importer les modifications distantes sans avoir à créer un nouveau commit :
git fetch
git rebase
# Pour résoudre un conflit
vim index.html
git add index.html
git rebase --continue
Appliquer les modifications de mybranch dans master, puis supprimer mybranch :
git checkout mybranch
git rebase master
git branch -b mybranch
git push origin :mybranch
Un rebase interractif peut être utilisé pour modifier l’historique.
Cela permet de nettoyer l’historique avant de l’importer dans une autre branche.
Ne JAMAIS utiliser un rebase interractif sur une branche partagée, où d’autres personnes peuvent faire des modifications.
git rebase -i | Démarre un rebase interractif sur la branche en cours (1) |
---|
(1) Affiche un éditeur pour décider ce qu’il faut faire sur les commits (du plus vieux au plus récent).
Pour envoyer les modifications d’historique au serveur distant avec un rebase, il faut utiliser git push -f
.
Un force oblige le dépot distant de se calquer sur le dépot local, sans essayer de faire de merge. Cette manipulation est dangereuse puisqu’elle peut effacer des commits de l’historique et donc supprimer de manière irrécupérable des modifications sur le dépot distant.
Changer l’ordre des lignes pour réordonner les commits :
pick 1ee9572 Switch this one
pick 746ef3e And this one
Renommer le message du commit (un nouvel éditeur va s’afficher pour modifier le message) :
reword 9afe987 The old message
Fractionner un commit en 2 commits ou plus :
edit 39b23ce The message
# Save and close
# Go back to that commit
git reset HEAD^
# Commit the files of the first commit
git add index.html
git commit -m "First commit"
# And then of the second
git add contact.html
git commit -m "Second commit"
# Continue the rebase
git rebase --continue
Rassembler plusieurs commits en un seul (un nouvel éditeur va s’afficher pour éditer le message du commit) :
pick 6e8e5d6 First commit
squash e8005f4 Second Commit
# Will merge the second commit into the first
git cherry-pick
permet de récupérer un ou des commits particuliers d’une autre branche dans la branche actuelle.
Cette commande est utile pour récupérer une correction de bug par exemple.
git cherry-pick 5321e5 | Récupére le commit 5321e5 dans la branche courante
5321e5 est le SHA du commit dans la branche d'origine |
---|---|
git cherry-pick -x 5321 | ... ajoute le SHA du commit source au message du commit |
git cherry-pick --signoff 5321 | ... ajoute le nom de l'utilisateur courant au message du commit |
git cherry-pick --edit 5312 | ... ouvre un éditeur pour modifier le message du commit |
git cherry-pick --no-commit 5321 55ae | Récupère les changements mais ne commite pas Par exemple pour commiter 2 commits en un seul, ou faire quelques modifications |
Un tag est une référence à un commit. Il permet de revenir à l’état du code tel qu’il était au moment où le tag a été crée. On les utilise principalement pour créer des releases, autrement dit pour marquer chaque mise en production d’un numéro de version.
Une bonne pratique est de respecter la convention des versions sémantiques: v[majeur].[mineur].[patch]
Il existe 3 types de tags
git tag | Liste tous les tags |
---|---|
git checkout v0.0.1 | Récupère le commit du tag v0.0.1 |
git tag -a v0.0.3 -m "version 0.0.3" | Crée un tag annoté Si -m est omis, un éditeur va s'ouvrir pour éditer le message |
git push --tags | Envoie les tags au dépot distant |
git tag -a v0.0.3 -m "Version 0.0.3"
git push --tags
On peut utiliser les branches pour créer des releases, sur le même principe qu’un tag. La différence qui les sépare est qu’un tag désigne un commit spécifique tandis qu’une branche peut être mise à jour avec de nouveaux commits (pour rectifier des bugs par exemple). En général, on nomme les branches de release r[majeur].[mineur].[patch]
Il n’est pas nécessaire de créer une branche si la version crée n’a pas de support long-terme.
Un autre possibilité en cas de bug est de créer une branche temporaire pour patcher le tag :
git checkout v1.1
git checkout -b rb1.1
# hotfix
git -m "Hotfix"
git tag v1.1.1 -m "Hotfix"
git checkout master
git merge rb1.1 -m "Merged hotfix"
git branch -d rb1.1
Le stash est un cache temporaire où l’on peut placer ses modifications. Les modifications sont supprimées du dépot local et peuvent être restaurées ultérieurement. Cela permet de changer de branche quand bien même les modifications ne sont pas prêtes à être commitées.
Tous les fichiers sont placés dans le stash, qu’ils soient dans le staging area ou non, mais par défaut, les nouveaux fichiers fichiers ne sont pas sauvegardés.
Plusieurs caches peuvent être utilisés.
git stash | Sauvegarde les modifications en cache et restaure le dernier commit |
---|---|
git stash save | Idem |
git stash save "Le message" | Sauvegarde avec un message |
git stash save --keep-index | Ne sauvegarde pas les fichiers dans le staging area |
git stash save --include-untracked | Sauvegarde aussi les nouveaux fichiers |
git stash list | Liste les caches |
git stash list --stat | Liste les caches et leurs modifications |
git stash show | Liste les modifications du dernier cache |
git stash show stash@{0} | Idem |
git stash apply | Restaure le dernier cache |
git stash apply stash@{0} | Idem |
git stash apply stash@{1} | Restaure stash1 |
git stash drop | Supprime le dernier cache (1) |
git stash drop stash@{1} | Supprime stash1 |
git stash pop | Restaure le dernier cache et le supprime (2) |
git stash branch mybranch stash@{0} | Crée une nouvelle branche et supprime le cache (3) |
git stash clear | Supprime tous les caches |
(1) Après avoir restauré le cache avec apply
, le cache n’est pas supprimé - il faut donc le faire manuellement
(2) Raccourcis de git stash apply; git stash drop
. En cas de conflit, il faudra supprimer le cache manuellement
(3) Il est ensuite nécessaire de commiter (git commit -am "Add my_branch"
)
$ git stash list
stash@{0}: WIP on master: 686b55d Add wolves.
stash@{1}: WIP on gerbils: b2bdead Add dogs.
WIP est l’abréviation de Work In Progress.
Les sous-modules sont des dépots à l’intérieur du dépot, utilisé principalement pour les librairies.
Cela permet
git submodule add git@example.com:css.git | Ajoute un sous-module au dépot courant |
---|---|
git submodule init | Récupère le contenu du sous-module |
git submodule update | Récupère les modifications du sous-module (1) |
git push --recurse-submodules=on-demand | Push les commits du parent ainsi que des sous-modules si nécessaire (2) |
git push --recurse-submodules=check | Push les commits du parent sauf si des sous-modules n'ont pas été pushés |
(1) Une erreur “fatal : reference is not a tree” est levée si le parent a des modifications du sous-module non pushées
(2) Pour créer un alias git pushall
: git config alias.pushall "push --recurse-submodules=on-demand"
Ajouter un sous-module :
git submodule add git@example.com:css.git
git commit -m "Add my submodule"
git push
Modifier un sous-module :
Un sous-module ne commence sur aucune branche en particulier, il est donc nécessaire de faire un checkout en premier
cd css
git checkout master
# Commite les modifications du sous-module
git commit -am "Init submodule"
git push
# Commite le parent
cd ..
git add css
git commit -m "Update submodule"
git push
En cas d’oubli de checkout sur une branche :
git checkout master
git merge b6bb78f
git push
# Puis commiter le parent
Fichiers de configurations des sous-modules
Ressources :
Pour aller plus loin : Github