DevGuide

Antiseche Git : commandes du quotidien et sauvetages

Sur cette page
  1. Voir où vous en êtes : statut et diff
  2. Indexer et committer
  3. Branches et changement de branche
  4. Annuler et se sortir d'affaire
  5. Distants et synchronisation
  6. Et après

Vous arrivez ici avec un bazar git à l'écran et une commande à moitié tapée dans la tête. Peut-être un commit sur la mauvaise branche, ou cette histoire d'indexé contre non indexé qui ne rentre toujours pas. On garde ici les commandes du quotidien, celles qu'on lance toute la journée, regroupées selon ce que vous cherchez à faire. Le statut, indexer et committer d'abord, puis les branches et le changement de branche, puis les sauvetages : reset, restore, revert, stash, reflog. Un truc à régler avant de scroller : reset, restore et revert se ressemblent et font des choses très différentes, donc le côté sûr contre destructeur est signalé sur chaque recette.

The short answer

Les commandes qu'on lance toute la journée, regroupées par objectif : git status -sb pour voir où vous en êtes, git add -p puis git commit pour indexer par morceaux, git switch -c feature pour une nouvelle branche, git reset --soft HEAD~1 pour annuler le dernier commit en gardant les modifications, git stash pour mettre du travail de côté, et git reflog quand un mauvais reset avale un commit. restore pour les fichiers, reset pour l'historique local, revert pour tout ce qui est déjà poussé.

5 sauvetagesreset, restore, revert, stash, reflog
--softannuler un commit, garder le travail
reflogpresque rien ne se perd vraiment
Fiche reponse : voir le statut, indexer avec git add -p, committer, creer une branche avec git switch -c, annuler avec git reset --soft, jeter avec git restore, annuler un commit pousse avec git revert, mettre de cote avec git stash, et recuperer avec git reflog.
Chaque geste qu'on utilise, regroupe selon ce que vous cherchez vraiment a faire. PNG

Vous arrivez ici avec un bazar git à l'écran et une commande à moitié tapée dans la tête. Peut-être un commit sur la mauvaise branche, ou cette histoire d'indexé contre non indexé qui n'est jamais bien rentrée. Les commandes ci-dessous sont celles qu'on lance vraiment toute la journée, regroupées selon ce que vous cherchez à faire, pour que vous puissiez copier, changer la branche ou le chemin, et retourner travailler.

Un truc à régler avant de scroller. reset, restore et revert se ressemblent presque et font des choses très différentes. restore touche aux fichiers, reset déplace votre branche, revert écrit un nouveau commit d'annulation. On signale les destructeurs, ceux sans retour en arrière, sur chaque recette. Dans le doute, lancez d'abord la commande en lecture seule et regardez avant de sauter.

Voir où vous en êtes : statut et diff

Avant de changer quoi que ce soit, regardez. git status vous dit ce qui est indexé, ce qui est modifié, et sur quelle branche vous êtes. Les options -sb donnent la version courte et lisible qui tient sur un écran. git diff montre les vraies modifications de lignes, et la séparation indexé contre copie de travail est ce que la plupart des gens ratent.

RecetteCe qu'elle fait
git status -sbLe statut court plus la ligne de branche, celui qu'on lance sans arrêt
git diffLes modifications de la copie de travail pas encore indexées
git diff --stagedLes modifications déjà indexées, celles qu'un commit capturerait
git log --oneline -10Les 10 derniers commits, un par ligne, pour s'orienter vite
git log --oneline --graph --allLe graphe des branches, pour voir comment ça a divergé

La séparation qui piège tout le monde : git diff sans option ne montre que ce qui n'est pas indexé. Dès que vous faites git add sur une modification, elle disparaît de cette vue et passe dans git diff --staged. Donc un git diff vide ne veut pas dire que rien n'a changé, ça peut vouloir dire que tout est déjà indexé.

Indexer et committer

L'indexation est l'étape qui fait le plus galérer. git add déplace les modifications dans l'index, la zone d'indexation qui deviendra votre prochain commit. L'astuce à apprendre, c'est -p, qui vous fait passer en revue chaque modification pour committer un bloc propre et logique au lieu de tout balancer d'un coup.

RecetteCe qu'elle fait
git add file.jsIndexer un fichier pour le prochain commit
git add -pIndexer morceau par morceau, en relisant chaque modification
git add -ATout indexer, y compris les fichiers nouveaux et supprimés
git commit -m "message"Committer les modifications indexées avec un message
git commit --amendReplier les modifications indexées dans le dernier commit, ou corriger son message

git commit --amend est le correctif du quotidien pour une faute dans votre dernier message ou un fichier oublié. Un avertissement : amender réécrit le dernier commit, donc ne le faites qu'avant de pousser. Amendez quelque chose déjà sur le distant et vous devrez forcer le push et embrouiller quiconque l'avait récupéré.

Notre avis : apprenez git add -p et votre historique devient lisible du jour au lendemain. La plupart des historiques en bazar viennent d'un git add -A suivi d'un commit géant qui touche à huit choses sans rapport. Avec -p, git vous montre chaque bloc et demande : on indexe ça ? Vous répondez y, n, ou s pour le découper plus fin. Le bénéfice, ce sont des commits qui font chacun une seule chose, ce qui rend git log, git blame et l'inévitable git revert vraiment utiles plus tard. Ça paraît plus lent pendant une semaine environ, puis c'est juste votre façon de travailler, et la revue de code cesse d'être une corvée pour tous ceux qui lisent après vous.

Branches et changement de branche

Une branche n'est qu'une étiquette mobile qui pointe vers un commit, rien de plus lourd. Les verbes modernes sont git switch et git restore, qui scindent l'ancien git checkout surchargé en deux boulots plus clairs. switch pour passer d'une branche à l'autre, restore pour les fichiers. Utilisez-les et la moitié de l'ancienne confusion disparaît.

RecetteCe qu'elle fait
git switch mainAller sur une branche existante nommée main
git switch -c featureCréer une nouvelle branche et y aller en une étape
git branchLister vos branches locales, la courante marquée
git branch -d old-featureSupprimer une branche fusionnée (sûr, refuse si non fusionnée)
git branch -D old-featureForcer la suppression même si non fusionnée (sans filet)
git merge featureFusionner feature dans la branche où vous êtes actuellement

La distinction -d contre -D est un vrai garde-fou. Le -d minuscule refuse de supprimer une branche dont les commits ne sont fusionnés nulle part, donc il vous protège de jeter du travail. Le -D majuscule passe outre ce contrôle. Ne dégainez -D que quand vous êtes certain que la branche est morte, pas par réflexe dès que -d râle.

Annuler et se sortir d'affaire

C'est sans doute la section pour laquelle vous êtes venu. Les commandes ici se séparent nettement : restore répare les fichiers, reset déplace votre branche, revert écrit une annulation sûre, stash met du travail de côté, et reflog est le filet sous toutes. Les recettes en gras ci-dessous sont destructrices, c'est-à-dire sans retour en arrière, donc lisez la note sous le tableau avant de lancer le moindre --hard.

RecetteCe qu'elle fait
git restore file.jsJeter les modifications non indexées d'un fichier, retour au dernier commit (destructeur)
git restore --staged file.jsDésindexer un fichier en gardant les modifications (sûr)
git reset --soft HEAD~1Annuler le dernier commit, garder les modifications indexées (sûr)
git reset HEAD~1Annuler le dernier commit, garder les modifications non indexées (sûr)
git reset --hard HEAD~1Annuler le dernier commit et jeter les modifications (destructeur)
git revert HEADFaire un nouveau commit qui annule le dernier (sûr, compatible partage)
git stashMettre de côté toutes les modifications non committées et nettoyer la copie de travail
git stash popRéappliquer le stash le plus récent et le retirer de la liste
git reflogMontrer chaque position qu'a eue HEAD, votre bouée de récupération

Celui à intérioriser, c'est l'échelle des modes de reset. --soft déplace la branche et laisse tout indexé. Le --mixed par défaut déplace la branche et désindexe, mais garde vos fichiers. --hard déplace la branche et écrase la copie de travail pour qu'elle corresponde, sans confirmation et sans retour en arrière par les commandes normales de git. Donc « annuler mon commit mais garder le travail » est presque toujours --soft ou un reset simple, jamais --hard.

Quand vous vous plantez avec un --hard ou une branche supprimée, git reflog est la réponse presque à chaque fois. Il enregistre chaque commit qu'a pointé HEAD, même ceux qu'aucune branche ne référence plus, et les garde environ quatre-vingt-dix jours. Trouvez le hash dans la liste, puis ramenez-le :

# vous avez fait un reset hard et perdu un bon commit, recuperez-le
git reflog                      # trouvez le hash, ex. 9f3c1a2 HEAD@{2}
git reset --hard 9f3c1a2        # ramenez la branche a ce commit
# ou, pour regarder sans deplacer votre branche
git checkout 9f3c1a2

Le flux du stash est la façon propre d'emporter du travail non committé vers la bonne branche, ou de nettoyer votre copie de travail pour un correctif rapide sans committer du code à moitié fait :

git stash                       # mettez tout de cote, la copie de travail redevient propre
git switch la-bonne-branche     # allez la ou le travail doit etre
git stash pop                   # reappliquez-le ici, supprimez l entree du stash
git stash list                  # voyez tous les stashs si vous en avez empile plusieurs
annuler le dernier commit, garder le travail
git reset --soft HEAD~1

Pour un commit déjà poussé, le geste sûr est git revert, pas reset. Faire un revert écrit un tout nouveau commit qui annule l'ancien, donc l'historique reste intact et personne qui l'avait récupéré n'a de mauvaise surprise. Gardez reset pour les commits qui ne vivent que sur votre machine. La règle est simple : réécrivez l'historique local librement, ne réécrivez jamais l'historique que d'autres ont déjà.

Distants et synchronisation

Les distants ne sont que d'autres copies du dépôt, en général sur un serveur comme GitHub. fetch télécharge leurs modifications sans toucher à vos branches, pull fait un fetch plus une fusion, et push envoie vos commits. Savoir que pull fait en réalité deux étapes explique la plupart des surprises « pourquoi cette fusion ».

RecetteCe qu'elle fait
git fetchTélécharger les modifications du distant sans rien fusionner encore
git pullFetch puis fusion de la branche distante dans la vôtre
git pull --rebaseFetch, puis rejouer vos commits par-dessus, pour un historique linéaire
git pushEnvoyer vos commits sur le distant
git push -u origin featurePousser et fixer l'amont pour qu'un push simple marche ensuite
git push --force-with-leaseForcer le push sans danger, en refusant si quelqu'un a poussé avant

Un mot sur le force-push, parce qu'il dévore le travail des gens. N'utilisez jamais un git push --force brut sur une branche partagée. Préférez --force-with-lease, qui vérifie que le distant est toujours là où vous l'aviez vu et abandonne si un collègue a poussé entre-temps. Ça transforme la commande git la plus dangereuse en une commande seulement risquée, ce qui est le mieux qu'on puisse en attendre.

Terminal montrant une session git du quotidien : git status -sb, indexation avec git add -p, commit, annulation du dernier commit avec git reset --soft, et recuperation d'un commit perdu avec git reflog.
Une session normale : voir le statut, indexer par morceaux, committer, annuler, recuperer. PNG

Et après

Voilà la trousse de travail. Statut et diff pour voir où vous en êtes, add et commit pour sauvegarder, switch et merge pour passer d'une ligne de développement à l'autre, et le groupe reset, restore, revert, stash et reflog pour le moment inévitable où ça part en vrille. Quatre-vingt-dix pour cent du git réel, c'est un mélange de ça, et le reste vous le recherchez comme tout le monde.

L'instinct qui compte le plus, c'est celui du sûr contre destructeur. Lancez d'abord la commande en lecture seule, status ou diff ou un reflog tout simple, avant de dégainer quoi que ce soit avec --hard ou --force. Et rappelez-vous le filet : tant que vous avez committé quelque chose à un moment, git reflog peut en général le retrouver, même quand ça semble perdu pour de bon. Gardez une bonne antisèche à portée et arrêtez d'essayer de tout mémoriser.

Questions fréquentes

Comment annuler le dernier commit git mais garder mes modifications ?

Lancez git reset --soft HEAD~1. Ça recule la branche d un commit et laisse toutes les modifications indexées, prêtes à être recommittées avec un meilleur message ou un autre découpage. Utilisez plutôt git reset HEAD~1 (le mode mixed par défaut) si vous voulez récupérer les modifications en non indexées. Évitez git reset --hard HEAD~1 sauf si vous voulez vraiment perdre ces modifications, parce que hard efface votre copie de travail sans confirmation.

Quelle difference entre git reset, git revert et git restore ?

Ils règlent trois problèmes différents. git restore modifie des fichiers dans votre copie de travail ou les désindexe, et ne touche jamais à l historique. git reset déplace la branche courante vers un autre commit, en changeant au besoin l index et la copie de travail avec. git revert crée un nouveau commit qui annule un commit antérieur, ce qui est le choix sûr sur une branche partagée car il ne réécrit rien. Règle simple : restore pour les fichiers, reset pour l historique local, revert pour tout ce qui est déjà poussé.

Comment deplacer des modifications non committees vers une autre branche ?

Mettez-les de côté, changez de branche, puis ressortez-les. Lancez git stash, puis git switch la-bonne-branche, puis git stash pop. Le pop réapplique vos modifications sur la nouvelle branche et supprime l entrée du stash. Si vous ne voulez emporter que certains fichiers, faites d abord git stash push chemin/du/fichier. Un stash est juste un instantané sauvegardé de votre copie de travail, donc rien n est perdu pendant qu il attend.

Comment recuperer un commit perdu apres un mauvais reset ?

Utilisez git reflog. Il enregistre chaque position où HEAD a pointé, y compris des commits qu aucune branche ne référence plus, donc un reset hard ou une branche supprimée n est presque jamais la fin. Trouvez le hash dans la liste du reflog, puis git reset --hard <hash> ou git checkout <hash> pour y revenir. Les entrées du reflog restent environ quatre-vingt-dix jours par défaut, largement de quoi rattraper la plupart des accidents.

Comment annuler les modifications locales sur un seul fichier ?

Lancez git restore chemin/du/fichier pour jeter les modifications non indexées et ramener le fichier au dernier commit. Il n y a pas de retour en arrière là-dessus, donc soyez sûr de ne plus vouloir ces modifications. Pour seulement désindexer un fichier en gardant les modifications, lancez plutôt git restore --staged chemin/du/fichier, qui remplace l ancienne forme git reset HEAD fichier.