Table des matières

Git

Fonctionnement interne de Git:

Ouvrir tous les fichiers modifiés

https://stackoverflow.com/questions/28280635/how-to-open-all-modified-files-with-git

vim $(git status --porcelain | awk '{print $2}')

Add

N'ajouter que quelques lignes d'un nouveau fichier

git add -N new
git add -p new

Diff

Lister les fichiers changés depuis un commit

git diff --name-only 60b504d066 HEAD

Il est possible de préciser un fichier pour voir la différence entre la version actuelle et le commit spécifié.

Comparer un fichier entre deux branches

git diff ..branch fichier_a_comparer

Utiliser un outil externe pour visualiser un diff de branches

https://stackoverflow.com/questions/2006032/view-differences-of-branches-with-meld

git config --global diff.tool meld
git difftool master..devel # ouvre meld pour chaque fichier différent
git -d difftool master..devel # ouvre meld avec toute l'arborescence

Pour persister les changements apportés pendant le diff, copier le dépôt et se placer sur l'autre branche, puis utiliser meld en comparant deux dossiers (si on passe directement par Git, les dossiers sont copiés dans un dossier temporaire, et les changements ne sont donc pas sauvegardés).

Merge

On se place sur la branche dans laquelle on veut merger.

git merge <branche à merger>

Supprimer un fichier du suivi de Git

Pour Git le fichier est supprimé, mais il reste sur le disque dur:

git rm --cached <file>

Sous-modules

Source

Installer un sous-module

git submodule add git://github.com/chneukirchen/rack.git rack

Ajoute le sous-module dans le dossier rack.

Installer les sous-modules d'un dépôt

git submodule init
git submodule update

Git avec SSH

Préciser la clé SSH à utiliser

Source

ssh-agent bash -c 'ssh-add /somewhere/yourkey; git clone git@github.com:user/project.git'

Passer des arguments à SSH

Source

GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" git clone user@host

Ne semble fonctionner que depuis Git 2.3.

Sauvegarder des dépôts Git

Source

Première sauvegarde:

git clone --mirror "$url" "$project"

Mettre à jour la sauvegarde:

git fetch --prune

L'option –prune permet de supprimer localement ce qui ne se trouve plus sur le dépôt distant.

Commits

Changer l'auteur des commits

Le dernier commit (source):

git commit --amend --author "New Author Name <New Author Email>"

Certains anciens commits (source):

git rebase -i -p <sha commit avant le premier concerné>
# passer les commits dont il faut changer l'auteur à "edit"
git commit --amend --author "New Author Name <New Author Email>"
git rebase --continue
# ...

Changer la date du dernier commit

git commit --amend --date="$(date)" --no-edit

Ajouter un fichier à un ancien commit

Source

git add <my fixed files>
git commit --fixup=OLDCOMMIT
git rebase --interactive --autosquash OLDCOMMIT^

OLDCOMMIT est le commit à modifier.

Afficher les infos d'un commit sans le diff

https://stackoverflow.com/questions/1828252/how-to-display-metadata-about-single-commit-in-git

git show --quiet

Scinder un (ancien) commit en plusieurs commits

Source

git rebase -i ${commit_avant}
# edit le commit à scinder
git reset HEAD~
# faire tous les commits souhaités (git add / git commit)
git rebase --continue

Faire un rebase avec le premier commit

Source

git rebase -i --root

Shallow clone

git clone --depth 1 ...

Passer ensuite sur une autre branche distante (source) :

git remote set-branches origin '*'
git fetch --depth=1
git checkout $branch

Travailler avec des forks

git remote add upstream https://github.com/octocat/Spoon-Knife.git
git remote -v

Synchroniser son dépôt:

git fetch upstream
git merge upstream/dev
git push

Pour que Git oublie les branches distantes qui ont été supprimées sur les dépôts distants (source):

git remote prune fork
# ou
git fetch --prune

Stashs

Stasher seulement certains fichiers modifiés

git stash -p

Valider les hunks des fichiers à stasher.

Ne fonctionne pas pour seulement quelques hunks à l'intérieur d'un fichier, car l'application du stash ne fonctionne plus après.

Afficher la date des stashs

Source

git stash list --date=local

Afficher les modifications dans un stash

Source

git stash show <stash>
git stash show -p <stash> # produit une sortie comme diff

Branches

Supprimer une branche

Localement:

git branch -d nom_de_branche
git branch -D nom_de_branche # si branche non mergée

Sur un serveur:

git push [remote] --delete [branche]
# donc:
git push origin --delete nom_de_branche
# ou:
git push [remote] :[branche]

Obtenir le nom de la branche courante

Source

git rev-parse --abbrev-ref HEAD

Obtenir toutes les branches d'un serveur

git branch -a  # toutes les branches de tous les serveurs
git branch -r # uniquement les branches distantes

Renommer une branche

https://multiplestates.wordpress.com/2015/02/05/rename-a-local-and-remote-branch-in-git/

git branch -m new-name # on est déjà sur la branche
git branch -m old-name new-name # on est sur une autre branche

Pour une branche distante:

git push origin :old-name new-name # supprime l'ancienne branche distante et crée la nouvelle branche sur le serveur
git push origin -u new-name # pousse le contenu vers la nouvelle branche

Tags

Créer un tag :

git tag <nom_du_tag> # par défaut sur le dernier commit
git tag -a v1.2 9fceb02 # sur un commit précédent

Pusher les tags :

git push origin --tags

Pour pusher un tag spécifique :

git push origin nom_du_tag

Supprimer un tag :

git tag -d nom_du_tag
git push origin --delete nom_du_tag

Patchs

Toujours en se plaçant dans le dossier racine (à défaut, le paramètre -p <n> peut aider).

git diff > hotfix.patch
git apply hotfix.patch

Si le patch est rejeté, possibilité de l'appliquer partiellement et stocker les hunks inapplicables dans les fichiers correspondants en ajoutant l'extension .rej:

git apply --reject --whitespace=fix mypath.patch

Pour générer le patch d'une branche:

git checkout feature
git format-patch master
git am *.patch

Il est possible d'éditer les patchs avec editdiff ou rediff, fournis par le paquet patchutils.

Annuler les modifications d'une partie d'un fichier

Source

git checkout -p <fichier>

Préciser l'emplacement du dossier Git

Pour lancer des commandes sans être dans le dossier: ajouter l'option --git-dir=chemin/vers/dossier/.git, ou juste l'option -C chemin/vers/le/dossier.

Pour cloner un dépôt, tout en plaçant le dossier .git ailleurs (source):

git clone --separate-git-dir=../../dev/pm2.git git@gitlab.inria.fr:pm2/pm2.git pm2

Obtenir le dossier racine du dépôt

git rev-parse --show-toplevel

Il est donc possible de faire un alias dans son bashrc:

alias gro='cd $(git rev-parse --show-toplevel)'

Obtenir le commit actuel

git rev-parse HEAD
git rev-parse --short HEAD

Obtenir la date du dernier commit

source ou source :

git log -1 --format=%cd
git show --no-patch --format=%ci

Historique d'un fichier

Source

git log [filename] # Affiche les commits impactant le fichier
git log -p [filename] # Affiche les diffs du fichier de tous les commits impactant le fichier
gitk [filename] # Interface graphique

L'option --follow permet de suivre le fichier si celui-ci a été renommé.

Pour avoir l'historique d'un fichier supprimé, il faut séparer les options de git log et le chemin du fichier avec --.

Supprimer tous les fichiers non suivis

Source

Utiliser la commande git clean.

Options:

Chercher dans tout l'historique

Un fichier

git log --all --full-history -- "**/thefile.*"

Grep

git grep foo $(git rev-list --all)

Une solution plus performante est :

git log -Sfoo

Afficher un fichier tel qu'il était à un commit

git show HEAD:fichier

Pour récupérer un fichier tel qu'il est dans une branche (source) :

git checkout branche fichier
git show branche:fichier > fichier
git restore -s branche fichier

Récupérer un fichier supprimé dans un commit

Source

git checkout <deleting_commit>^ -- <file_path>

Bisect

https://delicious-insights.com/fr/articles/git-bisect/

git bisect start
# se placer sur un commit foireux
git bisect bad
# se placer sur un commit bon
git bisect good
# itérer git bisect bad/good selon si le commit est correct ou non
# Git finit par indiquer le commit qui pose problème
git bisect reset # revient au commit lors du start

Forcer un pull à réécrire l'historique local

Source

Lorsque la branche distante a réécrit les commits déjà présents en local:

git fetch
git reset --hard origin/master

Si Git râle que fatal: argument ambigu : révision inconnue ou chemin inexistant., la branche n'existe pas pour Git. On peut le vérifier avec git branch --all et mettre à jour si nécessaire .git/config.

Log

Source

Options:

Voir l'historique d'une portion de fichier

Pour voir l'historique de la ligne 337 (Source):

git log -L 337,337:rr.tex

Lister tous les fichiers modifié par quelqu'un

En prenant en compte tous ses commits (source) :

git log --pretty= --committer=<username> --name-only | sort -u

Ignorer des fichiers

Ignorer une extension seulement à la racine du dépôt

Préfixer le pattern par un slash: /*.pdf. Les PDFs dans les sous-dossiers seront ainsi versionnés.

Avoir un gitignore global

Source

Créer un fichier ~/.gitignore_global, puis :

git config --global core.excludesfile ~/.gitignore_global

Compter le nombre de commits

Source

git rev-list --count HEAD # branche courante
git rev-list --count <branch-name> # spécifie une branche
git rev-list --count HEAD ^<branch-name> # depuis la création de la branche
git rev-list --no-merges --count HEAD # ignore les commits de merge

Envoi de mails

Configuration

Autoriser Git à remonter les points de montages

Nécessaire lorsqu'un dépôt Git sur un montage réseau souhaite aller chercher des informations dans la configuration globale de l'ordinateur local:

~/.zshrc
export GIT_DISCOVERY_ACROSS_FILESYSTEM=1

Configurer l'éditeur de commits

Source

git config --global core.editor "vim"

Alias

Source

Ajouter un alias:

git config --global alias.logg "log --oneline --graph --decorate=full"

Coloration automatique

git config --global color.ui auto

Pas de pager pour lister les branches

git config --global pager.branch false

Lister tous les paramètres possibles

git help --config

Verbosité

Source

time GIT_TRACE=true GIT_CURL_VERBOSE=true GIT_SSH_COMMAND="ssh -vvv" GIT_TRACE_PACK_ACCESS=true GIT_TRACE_PACKET=true GIT_TRACE_PACKFILE=true GIT_TRACE_PERFORMANCE=true GIT_TRACE_SETUP=true GIT_TRACE_SHALLOW=true git pull

Tester si on est dans un dépôt Git

Source

if git rev-parse --git-dir > /dev/null 2>&1; then
  : # This is a valid git repository (but the current working
    # directory may not be the top level.
    # Check the output of the git rev-parse command if you care)
else
  : # this is not a git repository
fi