:PROPERTIES:
:ID:       e93719b3-088d-4fe7-9ef8-fc9a4fd84827
:mtime:    20221229111938
:ctime:    20220501191904
:END:
#+title: Git

* Introduction
 * Outil de gestion de versions,
 * Créé par L. TORVALDS,
 * Fonctionnement décentralisé.

* Commandes
| Commande       | Action                                                                                                                                           |
|----------------+--------------------------------------------------------------------------------------------------------------------------------------------------|
| ~git init~     | Crée un nouveau dépôt                                                                                                                            |
| ~git clone​~    | Clone un dépôt distant                                                                                                                           |
| ~git add​~      | Ajoute de nouveaux /blobs/ dans la base des objets pour chaque fichier modifié depuis le dernier commit. Les objets précédents restent inchangés |
| ~git commit~   | Intègre la somme de contrôle SHA-1 d'un /tree/ et les sommes de contrôle des /commits/ parents pour créer un nouvel /commit/                     |
| ~git branch~   | ​Liste les branches                                                                                                                               |
| ~git merge~    | ​Fusionne une branche dans une autre                                                                                                              |
| ~git rebase~   | ​Déplace les /commits/ de la branche courante devant les nouveaux /commits/ d’une autre branche                                                   |
| ~git log​~      | Affiche la liste des commits effectués sur une branche                                                                                           |
| ~git push~     | Publie les nouvelles révisions sur le remote                                                                                                     |
| ~git pull~     | ​Récupère les dernières modifications distantes du projet (depuis le Remote) et les fusionne dans la branche courante                             |
| ~git stash~    | ​Stocke de côté un état non commité afin d’effectuer d’autres tâches                                                                              |
| ~git checkout~ | ​Annule les modifications effectuées, déplacement sur une référence (branche, hash)                                                               |
| ~git switch~   | ​Changement de branche                                                                                                                            |
| ~git remote~   | ​Gestion des remotes                                                                                                                              |

Pour positionner ~HEAD~ :
 * Au commit père : ~git checkout HEAD^~ ou ~git checkout HEAD~1~,
 * En cas de plusieurs pères : ~git checkout HEAD^2~ pour positionner au second père,
 * Au commit grand-père : ~git checkout HEAD^^~ ou ~git checkout HEAD~2~

~HEAD~ est /detached/ lorsqu'un /checkout/ est effectué sur un /commit/ et non pas une /branch/.

Pour forcer le déplacement d'une branche : ~git branch -f <nom_branche> <commit>~.

Pour retourner en arrière :
 * Branche locale : ~git reset <commit>~ (position où nous souhaitons être).
   * Différentes options :
     * ~--soft~ : le commit sera supprimé mais les changements seront conservés et /stashed/,
     * ~--mixed~ (par défaut) : le commit sera supprimé mais les changements seront conservés et /unstashed/,
     * ~--hard <commit_ref>~ pour les changements à ne pas conserver.
 * Branche distante (/remote/) : ~git revert <commit_ref>~ :
   * Création d'un nouveau /commit/ qui inversera les modifications apportées par le ~<commit_ref>~,
   * Conservation de l'historique,
   * Pour supprimer plusieurs /commit/ consécutifs : ~git revert <older_ref>..<newer_ref>~ (~<older_ref>~~ exclu,
     ~<newer_ref>~ inclus).

Pour copier une série de commits après l'emplacement actuel (/HEAD/) : ~git cherry-pick <commit_1> <commit_2> <...>~

*Rebase* interractif (~git rebase -i~) permet de :
 * Réarranger les /commits/,
 * Omettre certains /commits/ (/pick/),
 * Ecraser des /commits/.

Pour modifier le dernier commit : ~git commit --amend~.

Pour décrire (/describe/) les changements entre /HEAD/ et le tag le plus récent : ~git describe~ (~git describe <ref>~ sinon).

Pour mettre à jour une branche distante : ~git fetch~ :
 * Télécharge les /commits/ que le dépôt distant possède mais qui ne sont pas dans le notre, puis,
 * Met à jour nos branches distantes (par exemple, origin/main),
 * Ne met par à jour nos branches locales (par exemple, main),

Pour rapatrier (/fetch/) les branches distantes et les fusionner (/merge/) : ~git pull~.

Pour rapatrier (/fetch/) les branches distantes et /rebase/ : ~git pull --rebase~

Pour créer une branche afin que celle-ci suive une distante :
 * Création d'une nouvelle branche : ~git checkout -b <branche_locale> <branche_distante> ;git
pull~,
 * La branche existe déjà : ~git branch -u <branche_distante> <branche_locale>~

** Correction
Pour supprimer un fichier du dernier commit non /pushed/ : ~git reset --soft HEAD <filename>~.
Pour commiter la correction d'un précédent /commit/ :
#+BEGIN_SRC shell
git commit --fixup <hash_commit_à_corriger>
git rebase -i --autosquash
#+END_SRC

** Comparaison
Pour comparer deux branches : ~git diff <branche_a>..<branche_b>~.
Pour comparer un fichier ou un répertoire entre deux branches : ~git diff <branche_a>..<branche_b> -- <path>~.
Ajouter l'option ~-w~ à /git diff/ pour ignorer les espaces.

** Logs
Pour afficher l'historique d'une fonction ou d'un fichier : ~git log -L:<class_name>:<filename>~
Pour afficher les dernières positions de /HEAD/ : ~git reflog~.

* Outils tiers
** Visualisation de dépôts
*** [[https://github.com/rgburke/grv/][grv]]
Visualisation de dépôts git depuis un terminal.
*** [[https://github.com/o2sh/onefetch][onefetch]]
Informations du dépôt courant au lancement d'un terminal.
*** [[https://github.com/git-up/GitUp][GitUp]]
Application de visualisation de dépôts pour MacOS.
** Visualisation de différences
*** [[https://github.com/dandavison/delta][Delta]]
Affichage de ~git diff~.
*** [[https://github.com/darrenburns/dunk][Dunk]]
Affichage de ~git diff~.

* Apprentissage
** [[https://github.com/benthayer/git-gud][Git-gud]]
Jeu en ligne de commande permettant d'apprendre l'usage de Git.
** [[https://learngitbranching.js.org/][learngitbranching.js.org]]
Site permettant l'apprentissage de l'usage de Git.

* Références
 * [[https://martinheinz.dev/blog/43][Advanced Git features you didn't know You needed - Martin Heinz]]
 * [[https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa][Getting solid at Git rebase vs. merge - Christophe Porteneuve]]
 * [[https://medium.com/@porteneuve/mastering-git-reset-commit-alchemy-ba3a83bdfddc][Mastering Git Reset: Commit Alchemy - Christophe Porteneuve]]
