Git

Pense-bête

Faire un diff entre la version actuelle et la précédente

git diff HEAD^ HEAD

Afficher la version d’un fichier à une révision spécifique

git show 0ac056dcc7895d222eccb6ab40e9b2f911ba2634:mon_fichier.c

Effacer tous les changements effectués sur une copie locale

git checkout -f                # pour effacer tout changement fait sur l'intégralité des fichiers
git checkout -f fichier.txt    # pour effacer les changements faits sur le fichier "fichier.txt"

Récupérer des fichiers contenus dans une autre branche

git checkout mon_autre_branche mon/fichier.txt

Annuler le dernier commit

git reset --soft 'HEAD^'

À ne faire que si le commit n’a pas été poussé sur un dépôt distant.

Modifier le message du dernier commit

git commit --amend

Attention, ceci ne fonctionne que pour le dernier commit (HEAD), et si le commit n’a pas été poussé sur un dépôt distant.

Créer une branche indépendante

Il est possible de créer dans un dépôt une nouvelle branche qui ne soit pas corrélée à une autre branche – elle est considérée “orpheline” :

git checkout --orphan <nom de la nouvelle branche>

Supprimer une branche distante

git push origin --delete <nom de la branche>

Supprimer en local les branches distantes qui n’existent plus par rapport à l’origine distante

Le titre est un peu confus, mais visualisez la situation suivante : vous synchronisez votre dépôt local par rapport un dépôt distant (“origin”), et récupérez donc ses branches. Au bout d’un certain temps, quelqu’un supprime une ou plusieurs branches sur cette origine, mais les branches que vous avez récupéré auparavant figurent toujours dans la liste des branches de votre dépôt local.

Dans notre exemple, nous commençons avec plusieurs branches “historiques” obtenues par notre référent distant “origin” :

marc@ellone:~/mon_projet% git branch --all
  0.1
  feature4
* master
  remotes/origin/0.1
  remotes/origin/HEAD -> origin/master
  remotes/origin/feature1
  remotes/origin/feature2
  remotes/origin/feature3
  remotes/origin/feature4
  remotes/origin/master

marc@ellone:~/mon_projet% git branch --remote
  origin/0.1
  origin/HEAD -> origin/master
  origin/feature1
  origin/feature2
  origin/feature3
  origin/feature4
  origin/master

Nous synchronisons notre dépôt local par rapport à l’origine (ici github.com:moi/mon_projet) :

marc@ellone:~/mon_projet% git fetch --prune
From github.com:moi/mon_projet
 x [deleted]         (none)     -> origin/feature1
 x [deleted]         (none)     -> origin/feature2
 x [deleted]         (none)     -> origin/feature3

marc@ellone:~/mon_projet% git branch --remote
  origin/0.1
  origin/HEAD -> origin/master
  origin/feature4
  origin/master

Notre dépôt local est désormais synchronisé avec les branches présentes sur l’origine, les branches obsolètes feature1, feature2 et feature3 ont été supprimées :

marc@ellone:~/mon_projet% git branch --all
  0.1
  feature4
* master
  remotes/origin/0.1
  remotes/origin/HEAD -> origin/master
  remotes/origin/feature4
  remotes/origin/master

Supprimer un tag distant

git tag -d v42
git push origin :refs/tags/v42

Astuces

Exclure définitivement certains fichiers du versionnage

Si vous ne voulez pas que Git prenne en compte les fichiers temporaires (ex : fichiers temporaires .xxxxx.swp générés par Vim) ou encore les fichiers non pertinents (ex : fichiers de cache .pyc de Python), ajoutez les patterns correspondant dans le fichier .gitignore à la racine de votre copie de travail :

*.pyc
*.swp

Commandes Git raccourcies grâce aux aliases

Les mots-clés raccourcis (co, ci, up…) de Subversion vous manquent ? Pas de panique, il est possible d’utiliser les commandes de Git avec des alias raccourcis. Dans votre fichier ~/.gitconfig, ajoutez les lignes suivantes :

[alias]
    ci = commit
    co = checkout
    st = status

…et ainsi de suite, selon vos envies.

Colorier l’affichage des messages de Git

Pour mettre un peu de couleurs dans l’affichage de Git selon la nature des messages affichés, ajoutez la configuration suivante à votre fichier ~/.gitconfig :

[color]
    ui = auto

[color "branch"]
    current = yellow bold

[color "diff"]
    frag = magenta bold
    meta = yellow bold
    new = blue bold
    old = red bold

[color "status"]
    added = green bold
    changed = red bold

Vous trouverez la liste exhaustive des mots-clés dans le man git-config(1).

Utiliser un dépôt distant “d’échange”

Si vous avez besoin d’un dépôt central Git servant uniquement de transition entre 2 ou plusieurs autres dépôts distants, voici la procédure à suivre. Pour l’exemple, nous appellerons “X” le dépôt faisant la transition entre 2 autres dépôts “A” et “B”.

Depuis le dépôt X (situé sur le serveur un.serveur.distant.com) :

# Créé le dépôt minimal dans "chemin/vers/depot":
git init --bare chemin/vers/depot

Depuis le dépôt A :

cd depot

# Ajoute une nouvelle origine distante "<un.serveur.distant.com>:chemin/vers/depot"
git remote add origin <un.serveur.distant.com>:chemin/vers/depot 

# Pousse la branche master du dépôt local vers l'origine précédemment définie
git push origin master

Pour éviter d’avoir à spécifier “origin” à chaque fois que vous voulez mettre à jour le dépôt A, ajoutez les lignes suivantes dans le fichier depot/.git/config :

[branch "master"]
    remote = origin
    merge = refs/heads/master

Depuis le dépôt B :

# Clone le dépôt distant
git clone <un.serveur.distant.com>:chemin/vers/depot

Transformer un dépôt “normal” en dépôt “bare”

Git gère 2 types de dépôts : les dépots “normaux” — qui sont des copies de travail locales, contenant les fichiers versionnés — et les dépôts dits “bare” qui ne servent qu’à recevoir les commits sans permettre de manipuler directement les fichiers qui y sont versionnés. Pour “transformer” un dépot normal en un dépot “bare”, deux méthodes possibles :

a) cloner le dépôt existant :

git clone -l --bare blah blah.git # "blah.git" est la version "bare" du dépôt normal "blah"

b) manuellement :

cd blah
mv .git .. && rm -fr *
mv ../.git .
mv .git/* .
rmdir .git
git config --bool core.bare true
cd .. && mv blah blah.git # facultatif, "<nom du dépôt>.git" est juste une convention

Afficher uniquement la branche courante

Si vous avez besoin de récupérer le nom de la branche actuellement utilisée sans Patrick fioritures — par exemple pour utilisation dans un script —, voici une commande pratique :

git rev-parse --abbrev-ref HEAD

Alterner rapidement entre deux branches

Si vous alternez souvent entre deux branches lors de votre développement, il existe un raccourci pratique pour accéder à la branche utilisée précédemment en spécifiant le caractère - (tiret) au lieu du nom de la branche :

git checkout dev    # passe sur la branche "dev"
git checkout master # passe sur la branche "master"
git checkout -      # retourne sur la branche "dev"

Mettre à jour simultanément un dépôt local et ses sous-modules

Si vous utilisez des sous-modules dans un dépôt, vous avez probablement remarqué qu’il est pénible de devoir les mettre à jour par rapport à leur origine (git pull) indépendamment du dépôt “hôte”. À l’aide de l’alias suivant (git pullall), il est possible de synchroniser un dépôt et ses sous-modules en une commande :

git config --global alias.pullall '!git pull --all && git submodule foreach git pull --all'

Afficher la date de création des stashes

Git permet de mettre de côté des changements apportés aux fichiers versionnés d’un dépôt via les sous-commandes git stash (littéralement “planquer”). La sous-commande git stash list liste les modifications “planquées”, toutefois cette dernière n’affiche pas la date à laquelle celles-ci ont été créées par défaut. Pour obtenir cette information :

git stash list --date=local