Aide-mémoire Git [PDF]
(wizardzines.com)- Un PDF qui regroupe les opérations qui bloquent souvent avec Git, pour retrouver rapidement les commandes de création de commits, changement de branche, comparaison de modifications, synchronisation distante et annulation de changements
- Le flux de travail local repose sur
git status,git add,git commitetgit diffpour vérifier l’état avant et après staging et créer des commits - Le travail sur les branches utilise
git switch,git checkout,git branch,git merge,git rebaseetgit cherry-pickpour créer, changer, fusionner et rebaser - L’exploration de l’historique et la restauration incluent
git log,git blame,git show,git reflog,git resetetgit restore; les branches, tags,HEADet branches distantes peuvent aussi servir de références de commit - Les opérations sur dépôt distant couvrent la récupération et l’envoi de changements avec
git remote add,git fetch,git pull,git push,git push --force-with-leaseetgit push --tags
Démarrer un dépôt et vérifier l’état actuel
- Démarrer un nouveau dépôt :
git init
- Cloner un dépôt existant :
git clone $URL
- Vérifier l’emplacement et l’état actuels :
git status
Préparer et créer des commits
- Ajouter un fichier non suivi :
git add $FILE
- Ajouter tous les fichiers non suivis et les modifications non indexées :
git add .
- Indexer seulement certaines modifications d’un fichier :
git add -p
- Supprimer ou déplacer un fichier :
git rm $FILEgit mv $OLD $NEW
- Retirer un fichier du suivi Git sans le supprimer :
git rm --cached $FILE
- Annuler tout le staging :
git reset HEAD
- Créer un commit :
git commit- Ouvre un éditeur de texte pour rédiger le message
- Créer un commit en indiquant directement le message :
git commit -m 'message'
- Créer un commit avec un message en incluant aussi les modifications non indexées :
git commit -am 'message'
Changer de branche et gérer les branches
- Changer de branche :
git checkout $NAMEgit switch $NAME
- Créer une branche :
git checkout -b $NAMEgit switch -c $NAME
- Afficher la liste des branches :
git branch
- Trier les branches par commit le plus récent :
git branch --sort=-committerdate
- Supprimer une branche :
git branch -d $NAME
- Supprimer une branche de force :
git branch -D $NAME
Explorer l’historique et suivre le code
- Voir l’historique d’une branche :
git log main
- Voir sous forme de graphe la relation entre deux branches :
git log --graph a b
- Afficher le log sur une ligne :
git log --oneline
- Voir qui a modifié en dernier chaque ligne d’un fichier :
git blame $FILENAME
- Voir tous les commits qui ont modifié un fichier :
git log $FILENAME
- Trouver les commits qui ont ajouté ou supprimé un texte précis :
git log -S banana
Comparer les modifications
- Voir la différence entre un commit et son parent :
git show $COMMIT_ID
- Voir la différence entre un commit de merge et les parents fusionnés :
git show --remerge-diff $COMMIT_ID
- Voir un résumé du diff :
git diff $COMMIT_ID --statgit show $COMMIT_ID --stat
- Comparer deux commits :
git diff $COMMIT_ID $COMMIT_ID
- Comparer seulement un fichier précis avec un commit :
git diff $COMMIT_ID $FILENAME
- Comparer l’ensemble des modifications indexées et non indexées :
git diff HEAD
- Comparer seulement les modifications indexées :
git diff --staged
- Comparer seulement les modifications non indexées :
git diff
Fichiers de configuration et options
- Fichier de configuration Git local :
.git/config
- Fichier de configuration Git global :
~/.gitconfig
- Liste des fichiers à ignorer :
.gitignore
- Définir une option de configuration :
git config user.name 'Julia'
- Définir une option globale :
git config --global ...
- Ajouter un alias :
git config alias.st status
- Consulter les options de configuration possibles :
man git-config
Modifier l’historique et restaurer des fichiers
- Annuler le commit le plus récent en conservant le répertoire de travail tel quel :
git reset HEAD^
- Annuler un rebase raté :
git reflog BRANCHNAMEgit reset --hard $COMMIT_ID
- Fusionner les 5 derniers commits en un seul :
git rebase -i HEAD^^^^^^- Pour les commits à fusionner, remplacer
pickparfixup
- Récupérer la version d’un fichier depuis une autre branche ou un autre commit :
git checkout $COMMIT_ID $FILEgit restore $FILE --source $COMMIT_ID
- Modifier le message de commit ou ajouter un fichier oublié :
git commit --amend
Fusionner des branches
- Fast-forward merge pour mettre à jour la branche actuelle avec une autre branche :
git switch maingit merge banana
- Copier un commit vers une autre branche :
git cherry-pick $COMMIT_ID
- Rassembler des branches divergentes avec rebase :
git switch bananagit rebase main
- Rassembler des branches divergentes avec merge :
git switch maingit merge bananagit commit
- Rassembler des branches divergentes avec squash merge :
git switch maingit merge --squash bananagit commit
Dépôts distants et synchronisation
- Ajouter un dépôt distant :
git remote add $NAME $URL
- Push de la branche
mainvers le distantorigin:git push origin main
- Envoyer une branche pour la première fois sur
originet définir la branche de suivi :git push -u origin $NAME
- Push de la branche actuelle vers la branche distante suivie :
git push
- Force push :
git push --force-with-lease
- Push des tags :
git push --tags
- Récupérer les modifications sans modifier les branches locales :
git fetch origin main
- Fetch de toutes les branches :
git fetch --all
- Rebase de la branche actuelle après fetch :
git pull --rebase
- Merge dans la branche actuelle après fetch :
git pull origin maingit pull
Façons de désigner un commit
- Plusieurs références peuvent être utilisées à la place de
$COMMIT_ID:- Branche :
main - Tag :
v0.1 - ID de commit :
3e887ab - Branche distante :
origin/main - Commit actuel :
HEAD - Commit 3 commits avant :
HEAD^^^ - Commit 3 commits avant :
HEAD~3
- Branche :
Abandonner des modifications
- Supprimer les modifications indexées et non indexées d’un fichier :
git checkout HEAD $FILE
- Supprimer les modifications non indexées d’un fichier :
git checkout $FILE
- Supprimer toutes les modifications indexées et non indexées :
git reset --hard
- Mettre de côté les modifications indexées et non indexées avec stash :
git stash
- Supprimer les fichiers non suivis :
git clean
1 commentaires
Avis de Hacker News
Il y a quelques commandes qui sont de vrais joyaux cachés :
git diff --stagedmontre la différence entre le dernier commit et ce que vous avez actuellement indexé, ce qui est pratique pour vérifier que seul ce que vous vouliez est inclus quand vous ajoutez des fichiers ou des hunks de façon finegit log <file>n’affiche que les commits qui ont modifié ce fichier, ce qui évite de fouiller tout legit log, et c’est particulièrement utile pour les fichiers qui changent rarementQuand vous utilisez
git add --patch, si vous voulez choisir plus finement que les hunks découpés par Git, essayez l’optione. Les indications pour inclure/exclure des lignes individuelles sont fournies, donc pas besoin de les mémorisergit diff --stagedest un alias degit diff --cached. J’utilisecacheddepuis des années, maisstagedest effectivement beaucoup plus intuitif. Reste à savoir si j’arriverai à effacer cette mémoire musculaireSi ça vous intéresse, vous pouvez jeter un œil ou proposer des alias : https://gitlab.com/Falimonda/gitrc
git config --global commit.verbose true, Git ajoute automatiquement le diff indexé dans la zone de commentaires de l’éditeur de message de commitUne de mes commandes préférées, qui n’est pas dans la liste, est
git log -LstartLine,endLine:fileNameComme un
git blameétendu, elle montre comment les lignes indiquées ont changé au fil du temps et qui les a modifiées. Elle les suit même si les numéros de ligne changent ou si le fichier est déplacéElle répond à des questions comme « qui a fait ça, quand et pourquoi ? » ou « depuis quand est-ce comme ça ? »
Ça me rappelle la citation de Phil Karlton : « Il n’y a que deux choses difficiles en informatique : l’invalidation de cache et le nommage. »
De ce point de vue, le fait qu’une commande Git s’appelle
blamem’a toujours semblé assez étrange, et je ne suis pas le seul à le penserWhat does 'git blame' do? https://stackoverflow.com/questions/31203001/what-does-git-blame-do
Blame someone else for your bad code https://news.ycombinator.com/item?id=27963868
Git blame should be called git credit https://dev.to/damcosset/git-blame-should-be-called-git-credit-27h5
Does Git Blame sound too negative? https://www.reddit.com/r/ProgrammerHumor/comments/r5lzyo/does_git_blame_sound_too_negative_just_look_up/
git,blamesemble être un nom cohérent avec la marqueblameparwho. En fait, comme je suis un utilisateur pur et dur de Vim, j’utilise simplementwJ’ai bien aimé la façon dont j’ai appris Git. Au début, j’ai commencé avec Sourcetree, une GUI Git tierce, et c’était très facile à utiliser et à comprendre
Ensuite je suis passé à
git gui, mais on peut sauter cette étape. Puis lancer une interface graphique est devenu pénible, alors j’ai appris les commandes du terminalJe le recommande aux débutants Git, mais ce n’est que mon expérience n=1
clone,pull,commit,push, et jusqu’ici ça m’a suffi. Git peut être aussi simple que ça. Bien sûr, on peut apprendre des usages plus complexes si nécessaireC’est au moment où j’ai commencé à utiliser Magit que Git a commencé à avoir du sens pour moi
Je n’ai que des compliments à faire à Sublime Merge
Je me demande s’il y a des raisons historiques au fait que Git soit inutilement compliqué
En voyant cette antisèche, cette complexité devient encore plus palpable
Le fait qu’il soit devenu aussi largement utilisé est peut-être un « heureux accident », ou un malheur. GitHub a largement contribué à populariser Git avec son « hébergement Git gratuit », mais je ne pense pas que Git soit le système de gestion de versions idéal pour beaucoup de projets
Comme il a été créé pour Linus et Linux, sa terminologie et ses workflows peuvent parfois sembler inversés par rapport aux systèmes de gestion de versions ordinaires. Le nom
Pull Requestvient aussi du développement de Linux, où Linus ou les mainteneurs tirent les changements dans l’arbre du noyau. Dans d’autres systèmes, on parle généralement deMerge Request, ce qui est bien plus logique dans la mesure où il s’agit de fusionner dans l’arbre des changements quelle que soit leur provenanceGit était quasiment le seul système de gestion de versions distribué open source capable de traiter rapidement d’énormes bases de code, et c’est pour cela que l’inertie est devenue forte aussi dans les grandes entreprises
Pour les projets personnels, je préfère largement Mercurial et je l’utilise effectivement, mais si l’on essaie Hg sur une grosse base de code comme Android AOSP, il se met à ramer sévèrement. Mercurial a une meilleure interface utilisateur et une meilleure organisation des commandes, ainsi qu’une fonction permettant de lancer à la volée un serveur web pour visualiser l’arbre des changements, mais comme il est écrit en Python, ses performances et sa scalabilité ne sont pas idéales
git checkout, ce qui a rendu l’expérience utilisateur plus confuseDans les versions récentes de Git, le coût d’ajout de nouvelles sous-commandes a diminué, et ils ont commencé à ajouter des commandes plus spécifiques comme
git switchlog,add,commit,pulletpush. Il existe aussi des outils GUIHonnêtement, pour les tâches courantes, je ne trouve pas Git si compliqué. Il a simplement beaucoup de fonctionnalités puissantes disponibles quand on en a besoin
Les développeurs du noyau devaient communiquer entre eux de manière décentralisée et retravailler par-dessus le travail des autres. Comment travailler sur un projet où 15 000 personnes écrivent du code ? Git a été créé pour cet objectif
Il est aussi complexe que nécessaire pour prendre en charge le workflow pour lequel il a été conçu. Créer un outil plus simple est facile, mais il ne pourrait alors pas prendre en charge des workflows complexes comme le développement du noyau Linux. Donc il n’est pas inutilement compliqué, mais il est vrai qu’il est plus complexe que nécessaire pour des usages simples
Si l’on a besoin d’un frontend moins complexe, il existe beaucoup d’outils qui facilitent l’utilisation de Git. Si vous n’êtes pas développeur logiciel à plein temps, je ne recommande pas d’utiliser Git directement. Mais si vous êtes développeur à plein temps, cela vaut la peine de prendre le temps de comprendre ses concepts internes ; une fois qu’on les comprend, Git est assez élégant au regard de ce qu’il fait
Je ne dirais pas que connaître Git détermine si quelqu’un est qualifié comme développeur logiciel, mais si comprendre par soi-même le fonctionnement de systèmes fondamentaux comme celui-ci ne vous procure aucune dopamine, ce domaine n’est peut-être pas fait pour vous. Ce n’est pas grave : il y a des choses qui conviennent à chacun, et d’autres non
Pour apprendre à se déplacer dans Git, je recommande https://learngitbranching.js.org. Bien sûr, https://xkcd.com/1597/ s’applique aussi
Je ne connaissais pas
git add -p, mais c’est vraiment utile-p,--patchpermet de choisir de manière interactive les hunks de patch entre l’index et l’arbre de travail, et de les ajouter à l’index. Cela donne l’occasion de revoir les différences avant d’ajouter les modifications à l’indexCe que j’aimerais ajouter ici, c’est la combinaison
git commit --fixup $COMMIT_IDetgit rebase -i upstream/master --autosquashC’est devenu indispensable dans mon workflow récent. Dans l’exemple de Julia, elle utilise
HEAD^^^^^pour rebaser les 5 commits précédents, mais jusqu’à récemment j’utilisaisHEAD~5. Or je viens de comprendre qu’on peut simplement rebaser tous les commits jusqu’auHEADupstreamgit commit --fixup $COMMIT_ID. Je fais toujours de petits commits de correction du genre “oops GET users/me”, puis je les déplace manuellement lors du rebase interactif suivant pour les fixer, mais cette méthode est bien meilleure« Fusionner les 5 derniers commits en un seul :
git rebase -i HEAD^^^^^^» devrait plutôt êtregit rebase -i HEAD~5, non ?En supposant qu’on veuille seulement rebaser un historique linéaire
https://stackoverflow.com/questions/2221658/whats-the-difference-between-head-and-head-in-git
La plus grande prise de conscience, ça a été le moment où j’ai compris que tous les commits étaient encore là, en interne. Les tags et les branches ne font que pointer vers des commits, et les commits vers lesquels une branche pointait auparavant n’ont pas disparu
Beaucoup de commandes, peut-être même presque toutes, sont non destructrices, ce qui permet de référencer facilement l’ancien état d’une branche
J’avais déjà vu
git reflog, mais je m’en servais surtout pour me rappeler « c’était quoi déjà, cette branche sur laquelle je travaillais avant ? »J’avais développé une crainte à moitié saine des opérations qui peuvent vous entraîner au milieu d’une résolution de conflits non désirée. En général, les conflits arrivaient parce que je référençais le mauvais commit ou la mauvaise branche
Cette peur n’a pas complètement disparu, mais je suis au moins devenu assez à l’aise pour récupérer d’anciens travaux au milieu d’opérations comme un rebase
Si je ne sais pas si une opération va provoquer des conflits, je la fais simplement et je regarde. S’il y a un conflit, soit je le résous, soit j’annule l’opération qui l’a créé, soit je crée un nouveau commit ailleurs et je laisse le conflit pour plus tard
Si je sais qu’il va y avoir un conflit, je clone les branches concernées puis j’essaie de les aligner à l’avance, ou bien j’exécute l’opération conflictuelle et je suis le processus de résolution. Si la résolution devient trop brouillonne, je peux annuler une partie seulement de la résolution et continuer à essayer, la mettre de côté un moment pour faire autre chose, ou jeter tout l’arbre
Pour le dire franchement, il faut lâcher Git et regarder JJ
https://martinvonz.github.io/jj/v0.17.1/
Même Linus trouverait probablement que l’UI de Git est atroce. JJ propose un excellent workflow
Cela dit, à part l’avoir un peu manipulé, je ne l’ai pas vraiment utilisé en profondeur dans un vrai contexte de travail, donc difficile d’être catégorique