====== Git ====== * [[:git-python-api|API en Python]] * [[git:gpg|Signer les tags et les commits]] * [[git:gitlab|GitLab]] * [[http://www.qanuq.com/2019/09/08/trouver-date-suppression-fichier-git/]] * [[http://www.qanuq.com/2019/09/18/generer-archive-depot-git/]] * [[https://blog.garamotte.net/posts/2019/10/12/fr-git-recover-lost-commits.html|Git - Récupérer des commits perdus]] * [[https://ohshitgit.com/fr]] * [[https://about.gitlab.com/blog/2018/08/08/git-happens/|Git happens! 6 Common Git mistakes and how to fix them]] * [[https://hupstream.com/git-je-veux-ma-version-a-moi-de-ce-fichier/|Je veux ma version à moi de ce fichier !]] * [[https://github.blog/2015-06-08-how-to-undo-almost-anything-with-git/|How to undo (almost) anything with Git]] * [[https://github.com/onlywei/explain-git-with-d3]] * [[https://blog.seboss666.info/2021/05/utiliser-un-proxy-socks-ssh-pour-git-et-gitlab/|Utiliser un proxy Socks SSH pour Git et GitLab]] * [[https://blog.stephane-robert.info/docs/developper/version/git/introduction/|Maîtrisez les Commandes Git Essentielles]] * [[https://blog.scottlowe.org/2023/12/15/conditional-git-configuration/|Conditional Git Configuration]] * [[https://lucasoshiro.github.io/posts-en/2023-02-13-git-debug/|Git as debugging tool]] * [[https://jvns.ca/blog/2024/02/16/popular-git-config-options/|Popular git config options]] * [[https://blog.gitbutler.com/git-tips-3-really-large-repositories/|Git Tips 3: Really Large Repositories]] * [[https://adamj.eu/tech/2024/09/02/git-avoid-reset-hard-use-keep/|Git: avoid reset --hard, use reset --keep instead]] * [[https://github.com/k88hudson/git-flight-rules|Flight rules for Git]] * [[https://blog.shevarezo.fr/post/2025/03/12/git-sparse-checkout|Gérer efficacement vos dépôts avec git sparse-checkout]] * [[https://refactoringenglish.com/chapters/commit-messages/|How to Write Useful Commit Messages]] * [[https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/git-no-forge/|Git without a forge]] * [[https://blog.gitbutler.com/how-git-core-devs-configure-git/|How Core Git Developers Configure Git]] * [[https://maurycyz.com/misc/easy_git/|You already have a git server]] Fonctionnement interne de Git: * [[https://eagain.net/articles/git-for-computer-scientists/]] * [[https://github.blog/2020-12-17-commits-are-snapshots-not-diffs/]] * [[https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone]] * [[https://blog.meain.io/2023/what-is-in-dot-git/|What is in that .git directory?]] * [[https://jvns.ca/blog/2023/09/14/in-a-git-repository--where-do-your-files-live-/|In a git repository, where do your files live?]] * [[https://avestura.dev/blog/creating-a-git-commit-the-hard-way|Creating a Git commit: The Hard Way]] * [[https://blog.brachiosoft.com/en/posts/git/|A Git story: Not so fun this time]] * [[https://blog.gitbutler.com/20-years-of-git/|20 years of Git. Still weird, still wonderful.]] ==== 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 ==== Supprimer un fichier du suivi de Git ==== Pour Git le fichier est supprimé, mais il reste sur le disque dur: git rm --cached ==== Sous-modules ==== [[https://git-scm.com/book/fr/v1/Utilitaires-Git-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 === [[https://stackoverflow.com/questions/4565700/specify-private-ssh-key-to-use-when-executing-shell-command|Source]] ssh-agent bash -c 'ssh-add /somewhere/yourkey; git clone git@github.com:user/project.git' === Passer des arguments à SSH === [[https://stackoverflow.com/questions/7772190/passing-ssh-options-to-git-clone|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 ==== [[https://web.archive.org/web/20190728064015/https://www.competa.com/blog/making-backupmirror-github-repositories/#__do_not_save__|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 ([[https://stackoverflow.com/questions/3042437/how-to-change-the-commit-author-for-one-specific-commit/28845565|source]]): git commit --amend --author "New Author Name " Certains anciens commits ([[https://www.git-tower.com/learn/git/faq/change-author-name-email|source]]): git rebase -i -p # passer les commits dont il faut changer l'auteur à "edit" git commit --amend --author "New Author Name " git rebase --continue # ... === Changer la date du dernier commit === git commit --amend --date="$(date)" --no-edit === Ajouter un fichier à un ancien commit === [[https://stackoverflow.com/questions/2719579/how-to-add-a-changed-file-to-an-older-not-last-commit-in-git|Source]] git add 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 === [[https://stackoverflow.com/questions/6217156/break-a-previous-commit-into-multiple-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 ==== [[https://stackoverflow.com/questions/22992543/how-do-i-git-rebase-the-first-commit|Source]] git rebase -i --root ==== Shallow clone ==== git clone --depth 1 ... Passer ensuite sur une autre branche distante ([[https://stackoverflow.com/questions/23708231/git-shallow-clone-clone-depth-misses-remote-branches|source]]) : git remote set-branches origin '*' git fetch --depth=1 git checkout $branch ==== Travailler avec des forks ==== * [[https://help.github.com/articles/fork-a-repo/]] * [[https://help.github.com/articles/syncing-a-fork/]] 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 ([[https://makandracards.com/makandra/6739-git-remove-information-on-branches-that-were-deleted-on-origin|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 === [[https://stackoverflow.com/questions/15551618/get-the-creation-date-of-a-stash|Source]] git stash list --date=local === Afficher les modifications dans un stash === [[https://stackoverflow.com/questions/7677736/git-diff-against-a-stash|Source]] git stash show git stash show -p # 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 === [[https://stackoverflow.com/questions/6245570/how-to-get-the-current-branch-name-in-git|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 ==== * [[https://git-scm.com/book/fr/v2/Les-bases-de-Git-%C3%89tiquetage]] Créer un tag : git 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 '' 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 ==== [[https://stackoverflow.com/questions/771897/selectively-revert-or-checkout-changes-to-a-file-in-git|Source]] git checkout -p ==== 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 ([[https://stackoverflow.com/questions/505467/can-i-store-the-git-folder-outside-the-files-i-want-tracked|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 ==== [[https://stackoverflow.com/questions/25563455/how-do-i-get-last-commit-date-from-git-repository|source]] ou [[https://stackoverflow.com/questions/3814926/git-commit-date|source]] : git log -1 --format=%cd git show --no-patch --format=%ci ==== Historique d'un fichier ==== [[https://stackoverflow.com/questions/278192/view-the-change-history-of-a-file-using-git-versioning|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 ==== [[https://koukia.ca/how-to-remove-local-untracked-files-from-the-current-git-branch-571c6ce9b6b1|Source]] Utiliser la commande ''git clean''. Options: * ''-n'': dry-run * ''-f'': supprime vraiment * ''-d'': supprime aussi les dossiers * ''-X'': supprime les fichiers ignorés * ''-x'': supprime les fichiers ignorés et non ignorés ==== Chercher dans tout l'historique ==== === Un fichier === * [[https://stackoverflow.com/questions/7203515/git-how-to-find-a-deleted-file-in-the-project-commit-history]] git log --all --full-history -- "**/thefile.*" === Grep === * [[https://stackoverflow.com/questions/2928584/how-to-grep-search-committed-code-in-the-git-history]] 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 ([[https://stackoverflow.com/questions/307579/how-do-i-copy-a-version-of-a-single-file-from-one-git-branch-to-another|source]]) : git checkout branche fichier git show branche:fichier > fichier git restore -s branche fichier ==== Récupérer un fichier supprimé dans un commit ==== [[https://stackoverflow.com/questions/953481/how-do-i-find-and-restore-a-deleted-file-in-a-git-repository|Source]] git checkout ^ -- ==== 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 ==== [[https://stackoverflow.com/questions/1125968/how-do-i-force-git-pull-to-overwrite-local-files|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 ==== [[https://stackoverflow.com/questions/35945860/view-git-log-without-merge-commits|Source]] Options: * ''%%--%%no-merges'': n'affiche pas les commits indiquant un merge * ''%%--%%first-parent'': n'affiche pas les commits provenant d'un merge * ''%%--%%author="Author"'': n'affiche que les commits de //Author// === Voir l'historique d'une portion de fichier === Pour voir l'historique de la ligne 337 ([[https://stackoverflow.com/questions/8435343/retrieve-the-commit-log-for-a-specific-line-in-a-file|Source]]): git log -L 337,337:rr.tex === Lister tous les fichiers modifié par quelqu'un === En prenant en compte tous ses commits ([[https://stackoverflow.com/questions/53927301/list-all-files-changed-by-a-specific-user-in-a-git-repository|source]]) : git log --pretty= --committer= --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 === [[https://stackoverflow.com/questions/7335420/global-git-ignore|Source]] Créer un fichier ''~/.gitignore_global'', puis : git config --global core.excludesfile ~/.gitignore_global ==== Compter le nombre de commits ==== [[https://stackoverflow.com/a/11657647|Source]] git rev-list --count HEAD # branche courante git rev-list --count # spécifie une branche git rev-list --count HEAD ^ # depuis la création de la branche git rev-list --no-merges --count HEAD # ignore les commits de merge ==== Envoi de mails ==== * https://git-send-email.io ==== 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: export GIT_DISCOVERY_ACROSS_FILESYSTEM=1 === Configurer l'éditeur de commits === [[https://stackoverflow.com/questions/2596805/how-do-i-make-git-use-the-editor-of-my-choice-for-commits|Source]] git config --global core.editor "vim" === Alias === [[https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases|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é === [[https://www.shellhacks.com/git-verbose-mode-debug-fatal-errors/|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 ==== [[https://stackoverflow.com/questions/2180270/check-if-current-directory-is-a-git-repository|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