Git

De Banane Atomic
Aller à la navigationAller à la recherche

Sommaire

Documentation

Commandes utiles

Commande Alias Explication
git init initialise un nouveau dépôts
git clone url-dépôt [/dossier] clone un dépôt
Fichiers
git add file.ext ga file.ext ajoute le contenu de file.ext à l'index
git add --all gaa ajoute les contenus de tous les fichiers du dépôts à l'index (-n dry-run)
git reset HEAD file.ext grh file.ext retire file.ext de l'index
git checkout HEAD file.ext gco HEAD file.ext annule les modifications du fichier file.ext
git reset --hard && git clean -dfx gpristine annule toutes les modifications non-commitées, supprime les fichiers non-suivis
Status
git status gst affiche les fichiers indexés, non-indexés et non-suivis
git status --short gss affiche dans un format court les fichiers indexés, non-indexés et non-suivis
git diff gd affiche les modifications non-indexées
git diff --cached gdca affiche les modifications indexées
Commit
git commit -v gc affiche et valide les modifications indexées
git commit -v --amend gc! valide les modifications indexées dans le dernier commit et modification du message de validation
git commit -v --all gca indexe tous les fichiers versionnés (pas les nouveaux) et valide le tout
Branches
git branch Branche1 gb Branche1 créé Branche1, sans argument liste les branches locales
git branch --all gba liste les branches locales et distantes
git branch --delete Branche1 gbd Branche1 supprime Branche1
git checkout Branche1 gco Branche1 bascule sur Branche1
git checkout master gcm bascule sur master
git checkout develop gcd bascule sur develop
git checkout -b Branche1 gcb Branche1 créé Branche1 et bascule sur Branche1
git merge Branche1 gm Branche1 fusionne Branche1 dans la branche courante
git rebase master grb master
grbm
rebase la branche courante au bout de master
Dépôts distants
git remote add origin url gra origin url ajout du dépôt distant origin avec son url
git remote remove origin grrm origin retire le dépôt distant origin
git remote -v grv lister les dépôts distants
git fetch origin gf origin récupère les changements de toutes les branches du dépôt distant origin
git fetch --all --prune gfa récupère les changements de toutes les branches de tous les dépôts distants
git branch Branche1 origin/Branche1 gb Branche1 origin/Branche1 copie Branche1 du dépôt distant origin dans un branche locale Branche1
git checkout --track origin/Branche1 gct origin/Branche1 copie Branche1 du dépôt distant origin dans un branche locale Branche1
et bascule sur cette la branche locale Branche1
git pull origin master gl origin master récupère les changements de la branche master du dépôt distant origin
et fusionne les changements dans la branche locale master
git pull --rebase origin master gup origin master récupère les changements de toutes les branches du dépôt distant origin
et rebase les changements au bout de la branche locale master
git push --tags origin master gpt origin master pousser la branche locale master et ses tags
pour mettre à jour la branche master du dépôt distant origin

Créez un dépôt

Bash.svg
# depuis le répertoire qui deviendra la racine du dépôt
git init

Ignorez des fichiers

.gitignore
# ignorez les fichiers temporaires
*~
# ignorez un dossier
MonDossier/*
Le fichier .gitignore affecte le dossier dans lequel il se trouve ainsi que les sous-dossiers.
On peut donc créer des fichiers .gitignore spécifiques pour certains sous-dossiers.

Clonez un dépôt

Bash.svg
# créé un dossier contenant une copie du dépôt distant
git clone git://url/projet.git [destination]
# si destination n'est pas précisée, git extrait un nom de l'url, ici: projet

# Récupérer seulement les n dernier commit de la branche pointé par HEAD
git clone --depth n git://url/projet.git

# Récupérer seulement une branche (par défaut, la branche pointé par HEAD)
git clone git://url/projet.git [--branch master] --single-branch [destination]

Ajouter / retirer de l'index

Bash.svg
# Ajouter MonFichier à l'index
git add MonFichier

# Ajouter tous les nouveaux fichiers et les fichiers modifiés à l'index
git add -A -n
# utilisez l'option -n pour tester l'ajout sans ajouter
# git add .   → équivalent à  git add -A
# git add -u  → stages modified and deleted, without new, untracked files
# git add -n  → dry-run

# Retirer MonFichier de l'index
git reset HEAD MonFichier

# Retirer tout de l'index
git reset HEAD

Indexation partielle

Permet de ne valider qu'une partie des modifications d'un fichier.
Utilisez l'option patch de git : git add -p
Options pour chaque bloc de modification du fichier :

indexer cette partie [y,n,a,d,/,j,J,g,e,?]?
y - indexer cette partie
n - ne pas indexer cette partie
a - indexer cette partie et toutes celles restantes dans ce fichier
d - ne pas indexer cette partie ni aucune de celles restantes dans ce fichier
g - sélectionner une partie à voir
/ - chercher une partie correspondant à la regexp donnée
j - laisser cette partie non décidée, voir la prochaine partie non encore décidée
J - laisser cette partie non décidée, voir la prochaine partie
k - laisser cette partie non décidée, voir la partie non encore décidée précédente
K - laisser cette partie non décidée, voir la partie précédente
s - couper la partie courante en parties plus petites
e - modifier manuellement la partie courante
? - afficher l'aide

Valider l'index

Bash.svg
# Valider l'index
git commit

# Ajouter tous les nouveaux fichiers et les fichiers modifiés à l'index puis valider l'index
git commit -a

Visualiser les modifications

Bash.svg
# visualiser l'état dans lequel se trouve les changements: indexé, non-indexé, non-versionné
git status

# visualiser les modifications qui n'ont pas encore été ajoutées à l'index
git diff

# visualisez les modifications ajoutées à l'index
git diff --cached

# comparer un fichier entre 2 branches
git diff master MaBranche -- MonFichier.ext

Supprimer / déplacer des fichiers

Bash.svg
# supprimer MonFichier de git (arrêtez le suivi de version du fichier) et de la copie de travail
git rm MonFichier

# supprimer le MonFichier de git (arrêtez le suivi de version du fichier) mais le conserver dans la copie de travail
git rm --cached MonFichier

git mv ancien_fichier nouveau_fichier
# équivalent de:
# mv ancien_fichier nouveau_fichier
# git rm ancien_fichier
# git add nouveau_fichier
Le dossier parent peut être renommé sans influence sur le dépôt local ou distant.

Visualisez l'historique des validations

Bash.svg
# énumère en ordre chronologique inversé les commits réalisés
git log

Options :

  • -p : montre les différences introduites entre chaque validation
  • -2 : limite la sortie de la commande aux 2 entrées les plus récentes
  • -pretty=format="%h - %an, %ar : %s" : décrit précisément le format de sortie
  • --name-only : affiche la liste des fichiers modifiés
  • --name-status : affiche la liste des fichiers affectés accompagnés du staus ajout, modification ou suppression
Bash.svg
# Utilisez une interface graphique pour visualiser l'historique
gitk

Annulez des actions

Annuler n'importe quelle action locale

Bash.svg
# accès à l'historique de MaBranche (HEAD par défaut)
git reflog MaBranche

# annuler la dernière action
git reset --hard MaBranche@{1}

Ajout d'un fichier au dernier commit

Bash.svg
# Exemple vous faites un commit puis réalisez que vous avez oublié un fichier
git commit -m 'version 2.0'

# Ajout du fichier oublié
git add fichier_oublié
# Second commit qui remplace le premier
git commit --amend

# Changer l'auteur du dernier commit
git commit --amend --author "New Author Name <email@address.com>"

# Modifiez le commentaire du dernier commit
git commit --amend -m "Nouveau commentaire"

Retirer un fichier du dernier commit

Bash.svg
# met le dernier commit en édition
git reset --soft HEAD^

# retire le fichier souhaité
git reset HEAD /path/to/unwanted_file

# sauvegarde le commit
git commit -c ORIG_HEAD

Modifiez un commit autre que le dernier

Bash.svg
# pour modifier l'avant-dernier commit
git rebase -i HEAD~2
# ici on désigne le parent du commit à modifier : HEAD~2
# dernier commit : HEAD , avant-dernier commit : HEAD~1 , parent de l'avant-dernier commit : HEAD~2

# marquer les commits à modifier → remplacer pick par edit
# commiter avec la possibilité de changer le message et en forçant un nouvel auteur
git commit --amend --author "New Author Name <email@address.com>"

# pour terminer/continuer le rebase
git rebase --continue
Tous les commit entre celui qui sera modifié et HEAD seront réécrit
Ne pas utiliser git rebase pour les commit qui ont déjà été poussé sur le serveur

Diviser l'avant-dernier commit

Bash.svg
# HEAD~2: parent de l'avant-dernier commit
git rebase -i HEAD~2
# marquer l'avant-dernier commit à modifier -> edit

# défait le commit et laisse les fichiers modifiés non indexés
git reset HEAD^

# indexation d'une partie des fichiers non indexés
git add -p
# commit de la première partie
git commit -m "partie1"
# commit du reste
git commit -m "partie2"

# terminer le rebase
git rebase --continue

Ajouter une modification à l'avant-dernier commit

Bash.svg
# mettre de côté la modification
git stash

# rebase jusqu'au commit à modifier HEAD~2: parent de l'avant-dernier commit
git rebase -i HEAD~2
# marquer l'avant-dernier commit à modifier → remplacer pick par edit

# ressortir la modification
git stash pop

# ajouter le fichier contenant la modification
git add my-file.txt

# modifier le commit
git commit --amend

# terminer le rebase
git rebase --continue

Stopper temporairement le suivi d'un fichier

Bash.svg
# ignore temporairement tous les changement apportés à MonFichier
git update-index --assume-unchanged MonFichier

# reprend le suivi de MonFichier
git update-index --no-assume-unchanged MonFichier

Supprimer les modifications non-commitées

Bash.svg
# Réinitialisez un fichier
git checkout -- fichier_à_réinitialiser

# Réinitialisez tous le dépôt
git reset --hard && git clean -dfx

Supprimez les éléments non-versionnés

Bash.svg
git clean -dxf

Options :

  • -d : affecte les dossiers en plus des fichiers
  • -n : affiche les éléments qui seront supprimés mais ne supprime rien
  • -x : ne pas utiliser les règles d'exclusion (.gitignore, $GIT_DIR/info/exclude)
  • -f : obligatoire si la variable clean.requireForce est à true

Supprimer les derniers commits

What's the difference between git reset --mixed, --soft, and --hard?

reset pour les commits locaux

Fait reculer HEAD, les commits resetés sont perdus.

Bash.svg
# annuler le dernier commit, retour à staging
git reset --soft HEAD~1

git reset --hard xxxxxxxx
# xxxxxxxx : 8 premiers caractères du code du commit
# --hard: overwrites all uncommitted changes in the working directory

# obtenir le code des commits
git log --pretty=oneline

# il peut être utile de créer une branche qui pointe sur le dernier commit avant de faire reculer HEAD
git branch test

revert pour les commits publics

Créé un nouveau commit qui contient les modifications inverses du commit à annuler.
Permet d'annuler un commit qui n'est pas le dernier.

Bash.svg
git revert --hard xxxxxxxx
# xxxxxxxx : 8 premiers caractères du code du commit
# --hard: overwrites all uncommitted changes in the working directory

Ré-appliquer un commit

Bash.svg
git cherry-pick xxxxxxxx
# xxxxxxxx : 8 premiers caractères de l'id du commit
Utiliser git log pour connaitre les ids des commits.

Déplacer les commits d'une branche locale vers une autre

Des commits locaux ont été fait sur la branche badone par erreur. Il faut les déplacer vers la branche goodone.

Bash.svg
# Si la branche goodone n'existe pas déjà: depuis la branche badone, création de la branche goodone
git checkout goodone
# Si la branche goodone existe pas déjà: on merge badone dans goodone
git checkout goodone
git merge badone

# suppression de tous les commits locaux sur la branche badone
git checkout badone
git reset --hard origin/badone

Se déplacer dans l'arbre

Bash.svg
# se déplacer à un commit précis (detached head state)
git checkout [commit id]

# retourner au dernier commit (se réattacher à la branche)
git checkout [branch name]

# pour lister les commit ids
git log

Remisage: git stash

Bash.svg
# remise les modifications non-commitées
git stash push -u
# -u, remise aussi les untracked files puis les supprime avec un clean

# lister les remises
git stash list

# afficher le contenu de la dernière remise
git stash show

# applique la dernière remise, puis la supprime
git stash pop

# scénario: impossible de faire un pull à cause de conflits
# remiser les modifications locales
git stash
# récupérer les modifications distantes sans conflics
git pull
# ré-appliquer les modifications locales et gérer les éventuels conflits
git stash pop

Le remisage

Étiquetage (Tags)

Par défaut la commande git push n'envoie pas les étiquettes vers les serveurs distants.
Pour ce faire : git push --tags

Créez des étiquettes

Bash.svg
# Étiquette la dernière validation
git tag v2.0

# Étiquette la dernière validation dont la somme de controle commence par 9fceb02
git tag v1.2 9fceb02

# Supprimez le tag v1.2
git tag -d v1.2
# Supprimez le tag v1.2 sur la branche distante
git push --delete origin v1.2

Listez vos étiquettes

Bash.svg
# Listez les étiquettes existantes
git tag

# Recherchez les étiquettes correspondant à un motif particulier
git tag -l 'v1.*'

# Affichez le commit correspondant au tag v1.0.0
git show v1.0.0

Dépots distants

Ajoutez des dépôts distants

Bash.svg
# listez les dépôts distants
git remote -v

# ajoutez un dépôt distant
git remote add nom_dépôt_distant git://github.com/createur/projet.git

# lier nom_dépôt_distant/nom_branche à la branche courante
git branch -u nom_dépôt_distant/nom_branche
# -u nom_dépôt_distant/nom_branche : --set-upstream-to=nom_dépôt_distant/nom_branche

# renommez un dépôt distant
git remote rename nom_du_dépôt_distant nouveau_nom_du_dépôt_distant

# retirez un dépôt distant
git remote rm nom_dépôt_distant

Mise à jour et validation

Bash.svg
# récupère les modifications effectués sur le dépôt distant origin (met à jour les branches distantes origin/*)
# ne modifie pas la branche courante ni ne bascule vers une autre branche
git fetch origin

# fusionne la branche distante origin/master dans la branche locale courante
git merge origin/master

# récupérer la branche MaBranche du dépôt distant origin et la nommer localement MaBranche
git branch MaBranche origin/MaBranche
# équivalent avec checkout en plus
git checkout -b MaBranche origin/MaBranche
git checkout --track origin/MaBranche

# fetch + merge : récupère les modifications effectués sur le dépôt distant et les fusionne avec la branche courante
git pull origin master

# Pousser son travail sur un dépôt distant
git push --tags origin master
# --tags permet de pousser ses tags vers le dépôt distant, ce que ne fait pas push par défaut

# Pousser une branche locale nouvellement créée
git push -u origin <Ma_Nouvelle_Branche>

Branches des dépôts distants

Bash.svg
# listez les branches distantes
git branch -r

# listez toutes les branches
git branch -a

# url d'une branche distante
git config --get remote.origin.url

# supprimez la branche MaBranche sur le dépôt distant origin
git push origin :MaBranche

Branches locales

Bash.svg
# listez les branches locales et indique quelle est la branche courante
git branch

# listez les branches qui ont déjà été fusionnées et qui peuvent donc être supprimées
git branch --merged

# listez les branches qui n'ont pas encore été fusionnées
git branch --no-merged

# listez toutes les branches locales et distantes
git branch -a
Bash.svg
# création de MaBranche à partir du dernier commit de la branche courante
git branch MaBranche

# création de MaBranche à partir du dernier commit d'une AutreBranche ou d'un ID de commit ou d'un tag
git branch MaBranche [AutreBranche|Commit-ID|Tag]

# bascule vers MaBranche
git checkout MaBranche

# créé une nouvelle branche et bascule dessus
# les changements non commités reste inchangés et peuvent être commités sur cette nouvelle branche
git checkout -b NouvelleBranche

# supprimer la branche locale NouvelleBranche
git branch -d NouvelleBranche

# récupérer un fichier d'une autre branche
git checkout AutreBranche path/file.ext
git ne permet de basculer vers une branche que si toutes les modifications de la branche courante ont été commitées

Merge

Bash.svg
# fusion de MaBranche avec master :
# 1 - bascule vers master
git checkout master
# 2 - fusion de MaBranche avec la branche courante (master)
git merge MaBranche
# 3 - suppression de MaBranche
git branch -d MaBranche

# en cas de conflits
# lancez l'outils graphique d'édition de conflits
git mergetool
# marquez le conflit comme résolu pour MonFichier.ext
git add MonFichier.ext

# merge partiel de MaBranche dans master: seulement jusqu'au commit <commit-hash>
git merge --ff-only <commit-hash>

Rebase

Bash.svg
# 1 - rebase de MaBranche au bout de master
git rebase master MaBranche
# ou en 2 temps
# 1 - bascule vers MaBranche
git checkout MaBranche
# 2 - rebase de la branche courante (MaBranche) au bout de master
git rebase master

# 3 - retour sur master
git checkout master
# 4 - avance rapide (fast forward) de la branche courante (master) vers MaBranche
git merge MaBranche

# suppression de MaBranche
git branch -d MaBranche

Rebase vs Merge

  • Réécrit les commits de la branche à rebaser (MaBranche) comme des tout nouveaux commit au sommet de la branche courante (master)
  • Permet de simplifier l'historique.
Ne rebasez jamais des commits qui ont déjà été poussés sur un dépôt public

Règle générale:

  • When pulling changes from origin/develop onto your local develop use rebase.
  • When finishing a feature branch merge the changes back to develop.

Noms de branches insensible à la casse

Les noms de branches git ne sont pas sensible à la casse

Bash.svg
# checkout d'une branche distante en minuscule vers une branche locale en majuscule
git checkout -b My_New_Branch /origin/my_new_branch
# pull fonctionne, mais lors du push, création d'une nouvelle branche en majuscule

# renommer My_New_Branch en my_new_branch
# comme git est insensible à la casse il faut passer par une branche intermédiaire
git branch -m My_New_Branch tmp_branch
git branch -m tmp_branch my_new_branch

Autre solution: forcer git à ignorer la casse

%HomePath%\.gitconfig
[core]
    ignorecase = true
Bash.svg
# supprimer les branches locales et locale-remote
# mettre à jour les branches distantes
git fetch -p

Exportez dans une archive

Bash.svg
git archive mon_tag -o mon_archive.zip -9 --prefix=mon_dossier/
# -9 compression max de l'archive, -0 pas de compression
# HEAD peut-être utilisé comme tag

# tar.gz
git archive mon_tag --prefix=mon_dossier/ >mon_archive.tar.gz

Blame

Bash.svg
# Affiche les lignes 12 à 22 de fichier.ext avec pour chaque ligne son auteur et la révision associée
git blame -L 12,22 fichier.ext

# seulement la ligne 12
git blame -L 12,12 fichier.ext

# avec une interface graphique, ouvre fichier.ext à la ligne 12
git gui blame --line=12 fichier.ext

bisect

Définit un commit de début et un commit de fin et permet de lancer un test sur chaque commit intermédiaire.
Permet de localiser un commit introduisant un bug.

Installation

Bash.svg
sudo pacman -S git tk
# tk pour gitk
# sans tk l'erreur suivante s'affiche: /usr/bin/gitk: line 3: exec: wish: not found
~/.bashrc
# activer l'autocomplétion
source /usr/share/git/completion/git-completion.bash

GUI

  • gitk, installé avec git. Nécessite l'installation du paquet tk. À lancer dans le répertoire à analyser.
  • GitKraken
  • giggle

Git for Windows

Filename too long

Powershell.png
git config --system core.longpaths true

Configuration

Fichiers

  • .git/config accès par défaut ou avec l'option --local
  • ~/.gitconfig accès avec l'option --global
  • /etc/gitconfig accès avec l'option --system
Bash.svg
# ouvre le fichier de configuration dans le éditeur de texte
git config --global --edit

Commandes

Bash.svg
git config --global core.editor "nano -w"

git config --global user.name "Prénom Nom"
git config --global user.email "compte@email.com"

git config --global color.ui true

git config --global merge.tool meld

# autorise git à conserver le mot de passe pendant 15mn (valeur par défaut)
git config --global credential.helper cache
# autorise git à conserver le mot de passe pendant 1h
git config --global credential.helper 'cache --timeout=3600'

# stocke les informations d'identification dans le fichier ~/.git-credentials
git config --global credential.helper store

# LF - CRLF
# lors du checkout converti les LF → CRLF
git config --global core.autocrlf true
# lors du commit converti les CRLF → LF
git config --global core.autocrlf input
# checkout et commit des fichiers tels quels
git config --global core.autocrlf false

# Gnome Keyring
# compilez le credential pour gnome-keyring
cd /usr/share/git/credential/gnome-keyring
sudo make
# configurez git
git config --global credential.helper /usr/share/git/credential/gnome-keyring/git-credential-gnome-keyring
~/.gitconfig
[core]
	editor = nano -w
[user]
	name = Prénom Nom
	email = compte@email.com
[color]
	ui = true
[merge]
	tool = meld
[credential]
	helper = cache | store

Les alias Git

Bash.svg
# permet de taper 'git unstage' au lieu de 'git reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

# alias pour visualiser plus facilement le dernier commit
git config --global alias.last 'log -1 HEAD'

# permet de taper 'git ci' au lieu de 'git commit'
git config --global alias.ci commit
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.st status
~/.gitconfig
[alias]
	unstage = reset HEAD --
	last = log -1 HEAD
	ci = commit
	co = checkout
	br = branch
	st = status

git diff avec meld

meld

Bash.svg
# se placer dans le dossier git
meld .

difftool

Bash.svg
git difftool -y fichier.ext
# -y: no prompt

diff external

git-diff-meld.sh
#!/bin/bash
meld $2 $5
Bash.svg
git config --global diff.external /path/to/git-diff-meld.sh
~/.gitconfig
[diff]
	external = /path/to/git-diff-meld.sh

Serveur Git

Bash.svg
# créer un dossier de stockage
cd /srv
mkdir git
chown git:git git

# créer un projet de test
cd /srv/git
git init project.git --bare --shared
# bare: dépôt vide
# shared: dépôt partagé rwxrwsr-x au lieu de rwxr-xr-x
# et le fichier config contient sharedrepository = 1 et denyNonFastforwards = true
chown -R git:git project.git
# ajouter le groupe git aux utilisateurs pour qu'ils puissent pousser leurs modifications

# ajouter le dépôt fraîchement créé à un dépôt local
git remote add origin user@server:/srv/git/projet.git
# envoyer les modifications locales vers le dépôt distant
git push origin master

# récupérer le projet depuis un client avec le protocole ssh
git clone user@server:/srv/git/projet.git

# démarrer le serveur Git. Seulement utile pour le protocole git
systemctl start git-daemon.socket

Protocoles

local le dépôt distant est un autre répertoire dans le système de fichiers
par exemple un répertoire partagé via NFS
git clone /srv/git/projet.git
ssh permet de cloner et de pousser git clone utilisateur@serveur:/srv/git/projet.git
git daemon écoute sur le port 9418
pas d'authentification, tous le monde peut cloner et pousser
http(s) permet de cloner mais pas de pousser git clone http://server/projetgit.git

Gitweb

Bash.svg
pacman -S perl-cgi fcgiwrap

# démarrer le service fcgiwrap
sc-start fcgiwrap.socket
/etc/nginx/nginx.conf
server {
    listen 80;
    server_name gitweb.myserver;

    location /gitweb.cgi {
        include fastcgi_params;
        gzip off;
        fastcgi_param   SCRIPT_FILENAME  /usr/share/gitweb/gitweb.cgi;
        fastcgi_param   GITWEB_CONFIG    /etc/gitweb.conf;
        fastcgi_pass    unix:/run/fcgiwrap.sock;
    }

    location / {
        root /usr/share/gitweb;
        index gitweb.cgi;
    }
}
/etc/gitweb.conf
# The directories where your projects are. Must not end with a slash.
our $projectroot = "/srv/git"; 

# Base URLs for links displayed in the web interface.
our @git_base_url_list = qw(git://myserver http://git@myserver);

# enable "blame" view
$feature{'blame'}{'default'} = [1];

# enable syntax highlighting (installer le package highlight)
$feature{'highlight'}{'default'} = [1];