# RĂšgles de vol pour Git 🌍 *[English](README.md) ∙ [Español](README_es.md) ∙ [РуссĐșĐžĐč](README_ru.md) ∙ [çčé«”äž­æ–‡](README_zh-TW.md) ∙ [çź€äœ“äž­æ–‡](README_zh-CN.md) ∙ [한ꔭ얎](README_kr.md) ∙ [Tiáșżng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [æ—„æœŹèȘž](README_ja.md)* #### C'est quoi des "rĂšgles de vol" ? Un guide pour les astronautes (pour les dĂ©veloppeur·euse·s utilisant Git, dans le cas prĂ©sent) sur quoi faire quand les choses se passent mal. > *Les rĂšgles de vol* reprĂ©sentent l'ensemble des connaissances durement acquises consignĂ©es dans des manuels rĂ©pertoriant, Ă©tape par Ă©tape, la procĂ©dure Ă  suivre si telle chose se produit et pourquoi. Il s'agit essentiellement de procĂ©dures d'exploitation standard extrĂȘmement dĂ©taillĂ©es et spĂ©cifiques Ă  chaque scĂ©nario. [...] > La NASA a recueilli nos faux pas, nos dĂ©sastres et nos solutions depuis le dĂ©but des annĂ©es 60, lorsque les Ă©quipes terrestres de l'Ăšre Mercury ont commencĂ© Ă  rassembler les "leçons tirĂ©es" dans un recueil qui rĂ©pertorie dĂ©sormais des milliers de situations problĂ©matiques, des pannes de moteur aux poignĂ©es de trappes cassĂ©es en passant par les bugs informatiques, et leurs solutions. — Chris Hadfield, *Guide d'un astronaute pour la vie sur Terre*. #### Conventions pour ce document Pour des raisons de clartĂ© tous les exemples dans ce document utilisent une invite de commande bash personnalisĂ©e dans le but d'indiquer la branche actuelle et s'il y a des modifications indexĂ©es ou non. La branche se trouve entre parenthĂšses, et un `*` aprĂšs le nom de la branche indique des modifications indexĂ©es. Toutes les commandes devraient fonctionner pour les versions de Git au moins supĂ©rieures Ă  la 2.13.0. Visitez le [site de Git](https://www.git-scm.com/) pour mettre Ă  jour votre version de git locale. [![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - [DĂ©pĂŽts](#d%C3%A9p%C3%B4ts) - [Je veux initialiser un dĂ©pĂŽt local](#je-veux-initialiser-un-d%C3%A9p%C3%B4t-local) - [Je veux cloner un dĂ©pĂŽt distant](#je-veux-cloner-un-d%C3%A9p%C3%B4t-distant) - [Éditer des Commits](#%C3%89diter-des-commits) - [Qu'est-ce que je viens de commiter ?](#quest-ce-que-je-viens-de-commiter-) - [J'ai commis une erreur dans un message de commit](#jai-commis-une-erreur-dans-un-message-de-commit) - [J'ai commit avec le mauvais nom et email dans les configurations](#jai-commit-avec-le-mauvais-nom-et-email-dans-les-configurations) - [Je veux retirer un fichier du commit prĂ©cĂ©dent](#je-veux-retirer-un-fichier-du-commit-pr%C3%A9c%C3%A9dent) - [Je veux supprimer ou retirer mon dernier commit](#je-veux-supprimer-ou-retirer-mon-dernier-commit) - [Supprimer/retirer un commit arbitraire](#supprimerretirer-un-commit-arbitraire) - [J'ai essayĂ© de pousser un commit modifiĂ© vers le dĂ©pĂŽt distant, mais j'ai eu un message d'erreur](#jai-essay%C3%A9-de-pousser-un-commit-modifi%C3%A9-vers-le-d%C3%A9p%C3%B4t-distant-mais-jai-eu-un-message-derreur) - [J'ai fait un hard reset par accident, et je veux retrouver mes changements](#jai-fait-un-hard-reset-par-accident-et-je-veux-retrouver-mes-changements) - [J'ai commitĂ© et poussĂ© une fusion par accident](#jai-commit%C3%A9-et-pouss%C3%A9-une-fusion-par-accident) - [J'ai commitĂ© et poussĂ© des fichiers contenant des donnĂ©es sensibles par accident](#jai-commit%C3%A9-et-pouss%C3%A9-des-fichiers-contenant-des-donn%C3%A9es-sensibles-par-accident) - [Indexation](#indexation) - [J'ai besoin d'ajouter des modifications indexĂ©es sur le commit prĂ©cĂ©dent](#jai-besoin-dajouter-des-modifications-index%C3%A9es-sur-le-commit-pr%C3%A9c%C3%A9dent) - [Je veux indexer une partie d'un fichier, mais pas tout le fichier](#je-veux-indexer-une-partie-dun-fichier-mais-pas-tout-le-fichier) - [Je veux ajouter les changements d'un fichier dans deux commits diffĂ©rents](#je-veux-ajouter-les-changements-dun-fichier-dans-deux-commits-diff%C3%A9rents) - [Je veux indexer mes modifications indexĂ©es, et dĂ©sindexer mes modifications indexĂ©es](#je-veux-indexer-mes-modifications-index%C3%A9es-et-d%C3%A9sindexer-mes-modifications-index%C3%A9es) - [Modifications non indexĂ©es](#modifications-non-index%C3%A9es) - [Je veux dĂ©placer mes modifications non indexĂ©es vers une nouvelle branche](#je-veux-d%C3%A9placer-mes-modifications-non-index%C3%A9es-vers-une-nouvelle-branche) - [Je veux dĂ©placer mes modifications non indexĂ©es vers une branche diffĂ©rente existante](#je-veux-d%C3%A9placer-mes-modifications-non-index%C3%A9es-vers-une-branche-diff%C3%A9rente-existante) - [Je veux me dĂ©barrasser de mes modifications locales non commitĂ©es (indexĂ©es et non-indexĂ©es)](#je-veux-me-d%C3%A9barrasser-de-mes-modifications-locales-non-commit%C3%A9es-index%C3%A9es-et-non-index%C3%A9es) - [Je veux me dĂ©barrasser de modifications non-indexĂ©es spĂ©cifiques](#je-veux-me-d%C3%A9barrasser-de-modifications-non-index%C3%A9es-sp%C3%A9cifiques) - [Je veux me dĂ©barrasser de fichiers non-indexĂ©s spĂ©cifiques](#je-veux-me-d%C3%A9barrasser-de-fichiers-non-index%C3%A9s-sp%C3%A9cifiques) - [Je veux me dĂ©barrasser de mes modifications locales non-indexĂ©es uniquement](#je-veux-me-d%C3%A9barrasser-de-mes-modifications-locales-non-index%C3%A9es-uniquement) - [Je veux me dĂ©barrasser de tous mes fichiers non suivis](#je-veux-me-d%C3%A9barrasser-de-tous-mes-fichiers-non-suivis) - [Je veux dĂ©sindexer un fichier indexĂ© spĂ©cifique](#je-veux-d%C3%A9sindexer-un-fichier-index%C3%A9-sp%C3%A9cifique) - [Branches](#branches) - [Je veux lister toutes les branches](#je-veux-lister-toutes-les-branches) - [CrĂ©er une branche Ă  partir d'un commit](#cr%C3%A9er-une-branche-%C3%A0-partir-dun-commit) - [J'ai pull depuis/vers la mauvaise branche](#jai-pull-depuisvers-la-mauvaise-branche) - [Je veux supprimer mes commits locaux afin que ma branche soit pareille Ă  celle sur le serveur](#je-veux-supprimer-mes-commits-locaux-afin-que-ma-branche-soit-pareille-%C3%A0-celle-sur-le-serveur) - [J'ai commitĂ© sur main au lieu d'une nouvelle branche](#jai-commit%C3%A9-sur-main-au-lieu-dune-nouvelle-branche) - [Je veux sĂ©parer tout un fichier d'un autre ref-ish](#je-veux-s%C3%A9parer-tout-un-fichier-dun-autre-ref-ish) - [J'ai fait plusieurs commits sur une mĂȘme branche qui auraient dĂ» ĂȘtre sur plusieurs branches](#jai-fait-plusieurs-commits-sur-une-m%C3%AAme-branche-qui-auraient-d%C3%BB-%C3%AAtre-sur-plusieurs-branches) - [Je veux supprimer mes branches locales qui ont Ă©tĂ© supprimĂ©e sur le dĂ©pĂŽt distant](#je-veux-supprimer-mes-branches-locales-qui-ont-%C3%A9t%C3%A9-supprim%C3%A9e-sur-le-d%C3%A9p%C3%B4t-distant) - [J'ai supprimĂ© ma branche par accident](#jai-supprim%C3%A9-ma-branche-par-accident) - [Je veux supprimer une branche](#je-veux-supprimer-une-branche) - [Je veux supprimer plusieurs branches](#je-veux-supprimer-plusieurs-branches) - [Je veux renommer une branche](#je-veux-renommer-une-branche) - [Je veux me dĂ©placer sur une branche distante sur laquelle quelqu'un est en train de travailler](#je-veux-me-d%C3%A9placer-sur-une-branche-distante-sur-laquelle-quelquun-est-en-train-de-travailler) - [Je veux crĂ©er une nouvelle branche distante Ă  partir de celle en locale](#je-veux-cr%C3%A9er-une-nouvelle-branche-distante-%C3%A0-partir-de-celle-en-locale) - [Je veux configurer une branche distante en tant qu'upstream pour une branche locale](#je-veux-configurer-une-branche-distante-en-tant-quupstream-pour-une-branche-locale) - [Je veux configurer mon HEAD pour suivre la branche distante par dĂ©faut](#je-veux-configurer-mon-head-pour-suivre-la-branche-distante-par-d%C3%A9faut) - [J'ai fait des modifications sur la mauvaise branche](#jai-fait-des-modifications-sur-la-mauvaise-branche) - [Rebaser et fusionner](#rebaser-et-fusionner) - [Je veux annuler un rebase/merge](#je-veux-annuler-un-rebasemerge) - [J'ai rebase, mais je ne veux pas pousser de force](#jai-rebase-mais-je-ne-veux-pas-pousser-de-force) - [J'ai besoin de combiner des commits](#jai-besoin-de-combiner-des-commits) - [StratĂ©gie de fusion sĂ»re](#strat%C3%A9gie-de-fusion-s%C3%BBre) - [J'ai besoin de fusionner deux branches en un seul commit](#jai-besoin-de-fusionner-deux-branches-en-un-seul-commit) - [Je veux combiner les commits non poussĂ©s uniquement](#je-veux-combiner-les-commits-non-pouss%C3%A9s-uniquement) - [J'ai besoin d'annuler la fusion](#jai-besoin-dannuler-la-fusion) - [J'ai besoin de mettre Ă  jour le commit parent de ma branche](#jai-besoin-de-mettre-%C3%A0-jour-le-commit-parent-de-ma-branche) - [VĂ©rifier si tous les commits d'une branche sont fusionnĂ©s](#v%C3%A9rifier-si-tous-les-commits-dune-branche-sont-fusionn%C3%A9s) - [ProblĂšmes possibles avec les rebase interactifs](#probl%C3%A8mes-possibles-avec-les-rebase-interactifs) - [L'Ă©cran d'Ă©dition du rebase affiche 'noop'](#l%C3%A9cran-d%C3%A9dition-du-rebase-affiche-noop) - [Il y a eu des conflits](#il-y-a-eu-des-conflits) - [Remisage](#remisage) - [Remiser toutes les modifications](#remiser-toutes-les-modifications) - [Remiser des fichiers spĂ©cifiques](#remiser-des-fichiers-sp%C3%A9cifiques) - [Remiser avec un message](#remiser-avec-un-message) - [Appliquer un remisage spĂ©cifique de la liste](#appliquer-un-remisage-sp%C3%A9cifique-de-la-liste) - [Rechercher](#rechercher) - [Je veux rechercher une chaĂźne de caractĂšres dans un commit](#je-veux-rechercher-une-cha%C3%AEne-de-caract%C3%A8res-dans-un-commit) - [Je veux rechercher par auteur·trice/validateur·trice](#je-veux-rechercher-par-auteur%C2%B7tricevalidateur%C2%B7trice) - [Je veux lister les commits ayant des fichiers spĂ©cifiques](#je-veux-lister-les-commits-ayant-des-fichiers-sp%C3%A9cifiques) - [Trouver un tag oĂč un commit est rĂ©fĂ©rencĂ©](#trouver-un-tag-o%C3%B9-un-commit-est-r%C3%A9f%C3%A9renc%C3%A9) - [Sous-modules](#sous-modules) - [Cloner tous les sous-modules](#cloner-tous-les-sous-modules) - [Retirer un sous-module](#retirer-un-sous-module) - [Objets divers](#objets-divers) - [RĂ©cupĂ©rer un fichier supprimĂ©](#r%C3%A9cup%C3%A9rer-un-fichier-supprim%C3%A9) - [Supprimer un tag](#supprimer-un-tag) - [RĂ©cupĂ©rer un tag supprimĂ©](#r%C3%A9cup%C3%A9rer-un-tag-supprim%C3%A9) - [Patch supprimĂ©](#patch-supprim%C3%A9) - [Exporter un dĂ©pĂŽt comme fichier Zip](#exporter-un-d%C3%A9p%C3%B4t-comme-fichier-zip) - [Pousser une branche et un tag qui ont le mĂȘme nom](#pousser-une-branche-et-un-tag-qui-ont-le-m%C3%AAme-nom) - [Suivre des fichiers](#suivre-des-fichiers) - [Je veux changer la capitalisation du nom d'un fichier, sans changer son contenu](#je-veux-changer-la-capitalisation-du-nom-dun-fichier-sans-changer-son-contenu) - [Je veux Ă©craser des fichiers locaux en faisant un git pull](#je-veux-%C3%A9craser-des-fichiers-locaux-en-faisant-un-git-pull) - [Je veux retirer un fichier de Git mais garder le fichier](#je-veux-retirer-un-fichier-de-git-mais-garder-le-fichier) - [Je veux rĂ©tablir un fichier Ă  une version spĂ©cifique](#je-veux-r%C3%A9tablir-un-fichier-%C3%A0-une-version-sp%C3%A9cifique) - [Je veux lister les changements d'un fichier spĂ©cifique entre deux commits ou branches](#je-veux-lister-les-changements-dun-fichier-sp%C3%A9cifique-entre-deux-commits-ou-branches) - [Je veux que Git ignore les changements d'un fichier spĂ©cifique](#je-veux-que-git-ignore-les-changements-dun-fichier-sp%C3%A9cifique) - [ParamĂ©trage](#param%C3%A9trage) - [Je veux ajouter des alias pour certaines commandes Git](#je-veux-ajouter-des-alias-pour-certaines-commandes-git) - [Je veux ajouter un rĂ©pertoire vide Ă  mon dĂ©pĂŽt](#je-veux-ajouter-un-r%C3%A9pertoire-vide-%C3%A0-mon-d%C3%A9p%C3%B4t) - [Je veux mettre en cache un nom d'utilisateur et mot de passe pour un dĂ©pĂŽt](#je-veux-mettre-en-cache-un-nom-dutilisateur-et-mot-de-passe-pour-un-d%C3%A9p%C3%B4t) - [Je veux que Git ignore les changements de permissions et de filemode](#je-veux-que-git-ignore-les-changements-de-permissions-et-de-filemode) - [Je veux dĂ©finir un utilisateur global](#je-veux-d%C3%A9finir-un-utilisateur-global) - [Je n'ai aucune idĂ©e de ce que j'ai mal fait](#je-nai-aucune-id%C3%A9e-de-ce-que-jai-mal-fait) - [Autres Ressources](#autres-ressources) - [Livres](#livres) - [Tutoriels](#tutoriels) - [Scripts et Outils](#scripts-et-outils) - [Clients graphiques](#clients-graphiques) ## DĂ©pĂŽts ### Je veux initialiser un dĂ©pĂŽt local Pour initialiser un rĂ©pertoire existant comme dĂ©pĂŽt Git : ```sh (mon-dossier) $ git init ``` ### Je veux cloner un dĂ©pĂŽt distant Pour cloner (copier) un dĂ©pĂŽt distant, copiez l'url de ce dernier, et lancez : ```sh $ git clone [url] ``` Ceci le sauvegardera dans un dossier nommĂ© d'aprĂšs le nom du dĂ©pĂŽt. Assurez-vous d'avoir une connexion avec le serveur distant que vous essayez de cloner (dans la plupart des cas ceci revient Ă  s'assurer d'ĂȘtre connecté·e Ă  Internet). Pour le cloner vers un dossier ayant un nom diffĂ©rent de celui du dĂ©pĂŽt distant : ```sh $ git clone [url] nom-du-nouveau-dossier ``` ## Éditer des Commits ### Qu'est-ce que je viens de commiter ? Imaginons que vous venez tout juste d'enregistrer des changements Ă  l'aveugle avec {code0}git commit -a{/code0} et que vous n'ĂȘtes pas sĂ»r·e du contenu rĂ©el du commit que vous venez d'effectuer. Vous pouvez visualiser le dernier commit sur votre HEAD actuel avec : ```sh (main)$ git show ``` Ou : ```sh $ git log -n1 -p ``` Si vous voulez voir un fichier Ă  un commit spĂ©cifique, vous pouvez aussi faire (oĂč `` est le commit qui vous intĂ©resse). ```sh $ git show :nomdufichier ``` ### J'ai commis une erreur dans un message de commit Si vous vous ĂȘtes trompé·e et que le commit n'a pas encore Ă©tĂ© poussĂ©, vous pouvez appliquer la commande suivante afin de changer le message du commit sans affecter les changements de ce mĂȘme commit : ```sh $ git commit --amend --only ``` Cela ouvrira votre Ă©diteur de texte par dĂ©faut, oĂč vous pourrez Ă©diter le message. Vous pouvez Ă©galement effectuer la mĂȘme chose en une seule commande : ```sh $ git commit --amend --only -m 'xxxxxxx' ``` Si vous avez dĂ©jĂ  poussĂ© le message, vous pouvez modifier le commit et pousser de force, mais cela n'est pas recommandĂ©. ### J'ai commit avec le mauvais nom et email dans les configurations Si c'est un commit unique, modifiez-le : ```sh $ git commit --amend --no-edit --author "Nouvel Auteur·trice " ``` Une alternative est de configurer correctement vos paramĂštres d'auteur·trice avec `git config --global author.(name|email)` puis de lancer : ```sh $ git commit --amend --reset-author --no-edit ``` Si vous avez besoin de changer tout l'historique, veuillez vous rĂ©fĂ©rer Ă  la page man pour `git filter-branch`. ### Je veux retirer un fichier du commit prĂ©cĂ©dent Pour retirer les changements effectuĂ©s sur un fichier lors du prĂ©cĂ©dent commit, faites la chose suivante : ```sh $ git checkout HEAD^ monfichier $ git add monfichier $ git commit --amend --no-edit ``` Dans le cas oĂč le fichier fut introduit dans le commit et que vous voulez le retirer (de Git seul), faites : ```sh $ git rm --cached monfichier $ git commit --amend --no-edit ``` Cela est particuliĂšrement utile quand vous avez un patch d'ouvert et que vous avez commitĂ© un fichier non nĂ©cessaire, et que vous avez besoin de pousser de force pour mettre Ă  jour le patch sur le dĂ©pĂŽt distant. L'option `--no-edit` est utilisĂ©e pour garder le message de commit existant. ### Je veux supprimer ou retirer mon dernier commit Si vous avez besoin de supprimer des commits poussĂ©s, vous pouvez utiliser la commande suivante. Cependant, cela modifiera votre historique de maniĂšre irreversible, et mettra la pagaille dans l'historique de quiconque ayant dĂ©jĂ  rĂ©cupĂ©rĂ© des changements depuis le dĂ©pĂŽt distant. Pour faire court, si vous n'ĂȘtes pas sĂ»r·e, vous ne devriez pas faire ça, jamais. ```sh $ git reset HEAD^ --hard $ git push --force-with-lease [remote] [branche] ``` Si vous n'avez pas poussĂ©, pour rĂ©initialiser Git vers l'Ă©tat dans lequel il Ă©tait avant que vous ne fassiez votre dernier commit (tout en gardant vos changements) : ``` (ma-branche)$ git reset --soft HEAD^ ``` Cela ne marchera que si vous n'avez pas poussĂ©. Si vous avez poussĂ©, la seule vraie chose sĂ©curisĂ©e Ă  faire est `git revert SHAduMauvaisCommit`. Cela crĂ©era un nouveau commit qui annule tous les changements du commit en question. Ou, si la branche vers laquelle vous avez poussĂ© est "rebase-safe" (en d'autres termes, les autres dĂ©veloppeur·euse·s ne la rĂ©cupĂ©reront pas), vous pouvez juste lancer `git push --force-with-lease`. Pour plus d'informations, jetez un Ɠil [Ă  la section ci-dessus](#je-veux-supprimer-ou-retirer-mon-dernier-commit). ### Supprimer/retirer un commit arbitraire Le mĂȘme avertissement que ci-dessus s'applique. Ne faites jamais cela si possible. ```sh $ git rebase --onto SHA1_DU_MAUVAIS_COMMIT^ SHA1_DU_MAUVAIS_COMMIT $ git push --force-with-lease [remote] [branche] ``` Ou faites un [rebase interactif](#interactive-rebase) et retirez les lignes correspondantes au(x) commit(s) que vous souhaitez supprimer. ### J'ai essayĂ© de pousser un commit modifiĂ© vers le dĂ©pĂŽt distant, mais j'ai eu un message d'erreur ```sh To https://github.com/votrenomdutilisateur/repo.git ! [rejected] ma-branche -> ma-branche (non-fast-forward) error: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. ``` Notez que, tout comme avec un rebase (voir ci-dessous), le fait de modifier **remplace l'ancien commit avec un nouveau**, donc vous devez pousser de force (`--force-with-lease`) vos changements si vous avez dĂ©jĂ  poussĂ© le commit vers votre dĂ©pĂŽt distant avant sa modification. Soyez prudent·e quand vous faites cela : Assurez vous de *toujours* spĂ©cifier une branche ! ```sh (ma-branche)$ git push origin ma-branche --force-with-lease ``` En rĂšgle gĂ©nĂ©rale, **Ă©vitez de pousser de force**. Il est prĂ©fĂ©rable de crĂ©er et pousser un nouveau commit plutĂŽt que de pousser de force un commit modifiĂ© car cela causera des conflits dans l'historique pour n'importe quel dĂ©veloppeur·euse ayant dĂ©jĂ  intĂ©ragit avec la branche en question ou quelque branche fille. `--force-with-lease` Ă©chouera toujours, si quelqu'un d'autre Ă©tait dĂ©jĂ  en train de travailler sur la mĂȘme branche que vous et que votre push rĂ©Ă©crirait par-dessus ces modifications. Si vous ĂȘtes *absolument* sĂ»r·e que personne n'est en train de travailler sur la mĂȘme branche que vous ou que vous souhaitez mettre Ă  jour la branche de maniĂšre *inconditionnelle*, vous pouvez utiliser `--force` (`-f`), mais cela devrait ĂȘtre Ă©vitĂ© en gĂ©nĂ©ral. ### J'ai fait un hard reset par accident, et je veux retrouver mes changements Si vous avez accidentellement fait un `git reset --hard`, vous pouvez normalement retrouver votre commit, car Git garde un log de tout ce que vous faites pendant quelques jours. À noter : Cela n'est valide que si votre travail est sauvegardĂ©, c'est Ă  dire dans un commit ou un remisage. `git reset --hard` *supprimera* les modifications non commitĂ©es, donc utilisez cela avec prĂ©caution (une option plus sĂ»re est `git reset --keep`). ```sh (main)$ git reflog ``` Vous verrez une liste de vos prĂ©cĂ©dents commits, et un commit pour la rĂ©initialisation. Choisissez le SHA du commit vers lequel vous souhaitez retourner, et rĂ©initialisez Ă  nouveau : ```sh (main)$ git reset --hard SHA1234 ``` Et cela devrait faire l'affaire. ### J'ai commitĂ© et poussĂ© une fusion par accident Si vous avez accidentellement fusionnĂ© une branche d'une fonctionnalitĂ© avec la branche de dĂ©veloppement principale avant qu'elle ne soit prĂȘte Ă  ĂȘtre fusionnĂ©e, vous pouvez toujours annuler cette fusion. Mais il y a un piĂšge : un commit de fusion a plus d'un parent (en gĂ©nĂ©ral deux). Utilisez cette commande : ```sh (feature-branch)$ git revert -m 1 ``` oĂč l'option `-m 1` demande de sĂ©lectionner le parent numĂ©ro 1 (la branche vers laquelle la fusion a Ă©tĂ© faite) comme parent vers lequel annuler la fusion. À noter : le numĂ©ro du parent n'est pas un identifiant de commit. Un commit de fusion ressemble plus Ă  `Merge: 8e2ce2d 86ac2e7`. Le numĂ©ro du parent est l'index basĂ© sur 1 du parent souhaitĂ© sur cette ligne, le premier identifiant est le numĂ©ro 1, le second le numĂ©ro 2, et ainsi de suite. ### J'ai commitĂ© et poussĂ© des fichiers contenant des donnĂ©es sensibles par accident Si vous avez accidentellement poussĂ© des fichiers contenant des donnĂ©es sensibles (mots de passe, clĂ©s, etc.), vous pouvez modifier le commit prĂ©cĂ©dent. Gardez toutefois Ă  l'esprit qu'une fois que vous avez poussĂ© un commit, vous devez considĂ©rer n'importe quelle donnĂ©e qu'il contient comme Ă©tant compromise. Ces Ă©tapes peuvent supprimer les donnĂ©es sensibles de votre dĂ©pĂŽt public ou de votre copie locale, mais vous ne **pouvez pas** supprimer les donnĂ©es sensibles des copies clonĂ©es par d'autres personnes. Si vous avez commitĂ© un mot de passe, **changez-le immĂ©diatement**. Si vous avez commitĂ© une clĂ©, **rĂ©voquez-la et rĂ©gĂ©nĂ©rez-la immĂ©diatement**. Modifier le commit poussĂ© n'est pas suffisant, Ă©tant donnĂ© que n'importe qui aurait pu extraire le commit original contenant vos donnĂ©es sensibles pendant ce temps. Si vous souhaitez modifier le fichier et supprimer les donnĂ©es sensibles, lancez : ```sh (feature-branch)$ git add fichier_modifiĂ© (feature-branch)$ git commit --amend --no-edit (feature-branch)$ git push --force-with-lease origin [branche] ``` Si vous souhaitez supprimer tout un fichier (mais le garder en local), lancez : ```sh (feature-branch)$ git rm --cached fichier_sensible echo fichier_sensible >> .gitignore (feature-branch)$ git add .gitignore (feature-branch)$ git commit --amend --no-edit (feature-branch)$ git push --force-with-lease origin [branche] ``` Alternativement, stockez vos donnĂ©es sensibles dans des variables d'environnement locales. Si vous souhaitez supprimer tout un fichier (et ne pas le garder en local), lancez : ```sh (feature-branch)$ git rm fichier_sensible (feature-branch)$ git commit --amend --no-edit (feature-branch)$ git push --force-with-lease origin [branche] ``` Si vous avez crĂ©Ă© d'autres commits pendant ce temps (c'est Ă  dire que les donnĂ©es sensibles sont dans un commit avant le commit prĂ©cĂ©dent), vous devrez utiliser la fonction `rebase`. ## Indexation ### J'ai besoin d'ajouter des modifications indexĂ©es sur le commit prĂ©cĂ©dent ```sh (ma-branche*)$ git commit --amend ``` Si vous savez dĂ©jĂ  que vous ne souhaitez pas modifier le message du commit, vous pouvez dire Ă  Git de rĂ©utiliser ce dernier : ```sh (ma-branche*)$ git commit --amend -C HEAD ``` ### Je veux indexer une partie d'un fichier, mais pas tout le fichier Normalement, quand vous souhaitez modifier une partie d'un fichier, il faut lancer ceci : ```sh $ git add --patch nomdufichier.x ``` `-p` fonctionnera comme raccourci. Cela ouvrira le mode interactif. Vous serez en mesure d'utiliser l'option `s` pour sĂ©parer le commit. Cependant, si le fichier est nouveau, vous n'aurez pas cette option. Pour ajouter un nouveau fichier, faites comme ceci : ```sh $ git add -N nomdufichier.x ``` Ensuite, vous devrez utiliser l'option `e` afin de choisir manuellement quelles lignes ajouter. Lancer `git diff --cached` ou `git diff --staged` vous montrera quelles lignes vous avez indexĂ©es comparĂ©es Ă  celles qui sont toujours sauvegardĂ©es en local. ### Je veux ajouter les changements d'un fichier dans deux commits diffĂ©rents `git add` ajoutera le fichier entier Ă  un commit. `git add -p` vous permettra de sĂ©lectionner interactivement quels changements vous souhaitez ajouter. ### Je veux indexer mes modifications indexĂ©es, et dĂ©sindexer mes modifications indexĂ©es Cela est dĂ©licat. La meilleure chose que nous pouvons vous conseiller est que vous devriez remiser vos modifications non indexĂ©es, puis utiliser `git reset`. AprĂšs cela, utilisez `pop` pour dĂ©remiser vos modifications, puis ajoutez-les : ```sh $ git stash -k $ git reset --hard $ git stash pop $ git add -A ``` ## Modifications non indexĂ©es ### Je veux dĂ©placer mes modifications non indexĂ©es vers une nouvelle branche ```sh $ git checkout -b ma-branche ``` ### Je veux dĂ©placer mes modifications non indexĂ©es vers une branche diffĂ©rente existante ```sh $ git stash $ git checkout ma-branche $ git stash pop ``` ### Je veux me dĂ©barrasser de mes modifications locales non commitĂ©es (indexĂ©es et non-indexĂ©es) Si vous voulez vous dĂ©barrasser de toutes vos modifications locales indexĂ©es et non-indexĂ©es, vous pouvez faire ceci : ```sh (ma-branche)$ git reset --hard # ou (main)$ git checkout -f ``` Cette commande dĂ©sindexera tous les fichiers que vous avez pu indexer avec `git add` : ```sh $ git reset ``` Cette commande annulera toutes les modifications locales non commitĂ©es (elle devrait ĂȘtre exĂ©cutĂ©e Ă  la racine du dĂ©pĂŽt) : ```sh $ git checkout . ``` Vous pouvez Ă©galement annuler les changements non commitĂ©s d'un fichier ou d'un dossier en particulier : ```sh $ git checkout [un_dossier|fichier.txt] ``` Il existe Ă©galement une autre façon d'annuler toutes vos modifications non commitĂ©es (plus longue Ă  taper, mais fonctionne depuis n'importe quel sous-dossier) : ```sh $ git reset --hard HEAD ``` Cette commande supprimera tous les fichiers locaux non indexĂ©s, afin que seuls les fichiers suivis par Git ne restent : ```sh $ git clean -fd ``` `-x` supprimera Ă©galement tous les fichiers ignorĂ©s. ### Je veux me dĂ©barrasser de modifications non-indexĂ©es spĂ©cifiques Quand vous souhaitez vous dĂ©barrasser de quelques modifications dans votre copie de travail, mais pas toutes, faites un `checkout` sur les modifications non dĂ©sirĂ©es, et gardez les bonnes : ```sh $ git checkout -p # RĂ©pondez y Ă  tous les bouts de code que vous souhaitez jeter ``` Une autre stratĂ©gie implique d'utiliser `stash`. Remisez toutes les bonnes modifications, rĂ©initialisez votre copie locale, et rĂ©appliquez les bonnes modifications : ```sh $ git stash -p # SĂ©lectionnez tous les bouts de code que vous souhaitez garder $ git reset --hard $ git stash pop ``` Alternativement, remisez vos changements non dĂ©sirĂ©s, puis jetez le stash : ```sh $ git stash -p # SĂ©lectionnez tous les bouts de code que vous ne souhaitez pas sauvegarder $ git stash drop ``` ### Je veux me dĂ©barrasser de fichiers non-indexĂ©s spĂ©cifiques Quand vous souhaitez vous dĂ©barrasser d'un fichier en particulier de votre copie de travail : ```sh $ git checkout monFichier ``` Alternativement, pour vous dĂ©barrasser de plusieurs fichiers dans votre copie locale, listez chacun d'entre eux : ```sh $ git checkout monPremierFichier monDeuxiemeFichier ``` ### Je veux me dĂ©barrasser de mes modifications locales non-indexĂ©es uniquement Quand vous souhaitez vous dĂ©barrasser de toutes vos modifications locales non commitĂ©es : ```sh $ git checkout . ``` ### Je veux me dĂ©barrasser de tous mes fichiers non suivis Quand vous souhaitez vous dĂ©barrasser de tous vos fichiers non suivis : ```sh $ git clean -f ``` ### Je veux dĂ©sindexer un fichier indexĂ© spĂ©cifique Il arrive parfois que nous ayons un ou plusieurs fichiers qui ont Ă©tĂ© indexĂ©s par accident. Et ces fichiers n'ont pas Ă©tĂ© commitĂ©s auparavant. Pour les dĂ©sindexer : ```sh $ git reset -- ``` Cela entraĂźnera la dĂ©sindexation du fichier et le remettra Ă  son Ă©tat non suivi. ## Branches ### Je veux lister toutes les branches Pour lister les branches locales : ```sh $ git branch ``` Pour lister les branches distantes : ```sh $ git branch -r ``` Pour lister toutes les branches (Ă  la fois locales et distantes) : ```sh $ git branch -a ``` ### CrĂ©er une branche Ă  partir d'un commit ```sh $ git checkout -b ``` ### J'ai pull depuis/vers la mauvaise branche C'est une autre occasion d'utiliser `git reflog` afin de voir oĂč votre HEAD pointait avant le mauvais `pull` : ```sh (main)$ git reflog ab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward c5bc55a HEAD@{1}: checkout: checkout message goes here ``` RĂ©initialisez simplement votre branche vers le commit dĂ©sirĂ© : ```sh $ git reset --hard c5bc55a ``` Et voilĂ . ### Je veux supprimer mes commits locaux afin que ma branche soit pareille Ă  celle sur le serveur Assurez-vous que vous n'avez pas poussĂ© vos modifications sur le serveur. `git status` devrait vous indiquer combien de commits en avance vous ĂȘtes par rapport Ă  origin : ```sh (ma-branche)$ git status # On branch ma-branche # Your branch is ahead of 'origin/my-branch' by 2 commits. # (use "git push" to publish your local commits) # ``` Une des façons de faire pour rĂ©initialiser votre branche afin qu'elle corresponde Ă  origin (afin d'avoir la mĂȘme chose que le dĂ©pĂŽt distant) est de lancer ceci : ```sh (ma-branche)$ git reset --hard origin/ma-branche ``` ### J'ai commitĂ© sur main au lieu d'une nouvelle branche CrĂ©ez la nouvelle branche tout en restant sur main : ```sh (main)$ git branch ma-branche ``` RĂ©initialisez la branche main vers le commit prĂ©cĂ©dent : ```sh (main)$ git reset --hard HEAD^ ``` `HEAD^` est un raccourci pour `HEAD^1`. Cela indique le premier parent de `HEAD`, de la mĂȘme façon que `HEAD^2` indique le second parent du commit (des fusions peuvent avoir deux parents). Notez que `HEAD^2` ne signifie **pas** la mĂȘme chose que `HEAD~2` (visitez [ce lien](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde) pour plus d'informations). Alternativement, si vous ne souhaitez pas utiliser `HEAD^`, retrouvez le hash du commit vers lequel vous souhaitez remettre votre branche main (`git log` devrait faire l'affaire). Puis rĂ©initialisez vers ce hash. `git push` s'assurera que la modification est reflĂ©tĂ©e sur le serveur distant. Par exemple, si le hash du commit sur lequel votre branche main est supposĂ©e ĂȘtre est `a13b85e` : ```sh (main)$ git reset --hard a13b85e HEAD is now at a13b85e ``` DĂ©placez-vous vers la nouvelle branche pour continuer de travailler : ```sh (main)$ git checkout ma-branche ``` ### Je veux sĂ©parer tout un fichier d'un autre ref-ish Admettons que vous avez un pic de travail (voir la note), avec des centaines de changements. Tout fonctionne bien. Maintenant, vous commitez vers une autre branche pour sauvegarder ce travail : ```sh (solution)$ git add -A && git commit -m "Ajout de tous les changements de ce pic vers un gros commit." ``` Quand vous souhaitez mettre tout cela vers une branche (d'une fonctionnalitĂ© ou `develop`), ce qui vous intĂ©resse est de garder les fichiers dans leur entiĂšretĂ©. Vous voudriez Ă©galement sĂ©parer votre gros commit en plusieurs petits commits. Admettons que vous ayez : * La branche `solution`, avec la solution Ă  votre pic. En avance d'un commit par rapport Ă  `develop`. * La branche `develop`, oĂč vous souhaitez ajouter vos modifications. Vous pouvez rĂ©soudre cela en ramenant les contenus vers votre branche : ```sh (develop)$ git checkout solution -- fichier1.txt ``` Cela ramĂšnera le contenu de ce fichier dans la branche `solution` vers votre branche `develop` : ```sh # On branch develop # Your branch is up-to-date with 'origin/develop'. # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # modified: fichier1.txt ``` Puis, commitez comme d'habitude. Note: Les pics de solutions servent Ă  analyser ou rĂ©soudre un problĂšme. Ces solutions sont ensuite utilisĂ©es afin d'avoir une estimation puis jetĂ©es une fois que tout le monde a une vision claire du problĂšme. ~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices). ### J'ai fait plusieurs commits sur une mĂȘme branche qui auraient dĂ» ĂȘtre sur plusieurs branches Admettons que vous ĂȘtes sur votre branche main. En lançant `git log`, vous remarquez que vous avez fait deux commits : ```sh (main)$ git log commit e3851e817c451cc36f2e6f3049db528415e3c114 Author: Alex Lee Date: Tue Jul 22 15:39:27 2014 -0400 Bug #21 - Ajout de la protection CSRF commit 5ea51731d150f7ddc4a365437931cd8be3bf3131 Author: Alex Lee Date: Tue Jul 22 15:39:12 2014 -0400 Bug #14 - Correction de l'espacement du titre commit a13b85e984171c6e2a1729bb061994525f626d14 Author: Aki Rose Date: Tue Jul 21 01:12:48 2014 -0400 Premier commit ``` Notons dans un coin les hashes des commits pour chaque bug (`e3851e8` pour le #21, `5ea5173` pour le #14). Pour commencer, rĂ©initialisons notre branche main sur le bon commit (`a13b85e`) : ```sh (main)$ git reset --hard a13b85e HEAD is now at a13b85e ``` Maintenant, nous pouvons crĂ©er une nouvelle branche pour le bug #21 : ```sh (main)$ git checkout -b 21 (21)$ ``` Maintenant, faisons un `cherry-pick` du commit pour le bug #21 par-dessus notre branche. Cela signifie que nous appliquerons ce commit, et seulement ce commit, directement au-dessus de ce qui se trouve sur notre HEAD : ```sh (21)$ git cherry-pick e3851e8 ``` Lors de cette Ă©tape, il est possible qu'il y ait des conflits. Regardez la section [**Il y a eu des conflits**](#merge-conflict) dans la section [faire un rebase interactif](#interactive-rebase) ci-dessus pour savoir comment rĂ©soudre ces conflits. Maintenant, crĂ©ons une nouvelle branche pour le bug #14, aussi basĂ©e sur main : ```sh (21)$ git checkout main (main)$ git checkout -b 14 (14)$ ``` Et pour finir, faisons un `cherry-pick` du commit pour le bug #14 : ```sh (14)$ git cherry-pick 5ea5173 ``` ### Je veux supprimer mes branches locales qui ont Ă©tĂ© supprimĂ©e sur le dĂ©pĂŽt distant Une fois que vous avez acceptĂ© une Pull Request sur GitHub, vous avez l'option de supprimer la branche fusionnĂ©e dans votre fork. Si vous ne prĂ©voyez pas de continuer Ă  travailler sur la branche, cela est plus propre de supprimer les copies locales de la branche afin de ne pas encombrer votre copie de travail avec un tas de branches obsolĂštes. ```sh $ git fetch -p upstream ``` oĂč `upstream` est le dĂ©pĂŽt distant depuis lequel vous voulez mettre Ă  jour. ### J'ai supprimĂ© ma branche par accident Si vous poussez rĂ©guliĂšrement sur la branche distante, vous devriez ne pas avoir de problĂšme la plupart du temps. Mais il arrive parfois que vous finissez par supprimer vos branches. Admettons que nous crĂ©ons une nouvelle branche avec un nouveau fichier : ```sh (main)$ git checkout -b ma-branche (ma-branceh)$ git branch (ma-branche)$ touch foo.txt (ma-branche)$ ls README.md foo.txt ``` Ajoutons cela et commitons : ```sh (ma-branche)$ git add . (ma-branche)$ git commit -m 'ajout de foo.txt' (ma-branche)$ ajout de foo.txt 1 files changed, 1 insertions(+) create mode 100644 foo.txt (ma-branche)$ git log commit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012 Author: siemiatj Date: Wed Jul 30 00:34:10 2014 +0200 ajout de foo.txt commit 69204cdf0acbab201619d95ad8295928e7f411d5 Author: Kate Hudson Date: Tue Jul 29 13:14:46 2014 -0400 Correction #6: Push de force aprĂšs avoir Ă©ditĂ© les commits ``` Maintenant, revenons sur main et supprimons notre branche "par accident" : ```sh (ma-branche)$ git checkout main Switched to branch 'main' Your branch is up-to-date with 'origin/main'. (main)$ git branch -D my-branch Deleted branch ma-branche (was 4e3cd85). (main)$ echo oh non, j'ai supprimĂ© ma branche ! oh non, j'ai supprimĂ© ma branche ! ``` À cette Ă©tape, vous devriez devenir familier avec `reflog`, un logueur amĂ©liorĂ©. Il stocke l'historique de toutes les actions dans le dĂ©pĂŽt : ``` (main)$ git reflog 69204cd HEAD@{0}: checkout: moving from ma-branche to main 4e3cd85 HEAD@{1}: commit: ajout de foo.txt 69204cd HEAD@{2}: checkout: moving from main to ma-branche ``` Comme vous pouvez le remarquer, nous avons le hash du commit de notre branche supprimĂ©e. Voyons voir si nous pouvons restaurer notre branche supprimĂ©e. ```sh (main)$ git checkout -b ma-branche-help Switched to a new branch 'ma-branche-help' (ma-branche-help)$ git reset --hard 4e3cd85 HEAD is now at 4e3cd85 ajout de foo.txt (ma-branche-help)$ ls README.md foo.txt ``` VoilĂ  ! Nous avons rĂ©cupĂ©rĂ© notre fichier supprimĂ©. `git reflog` est aussi utile quand un rebase se passe terriblement mal. ### Je veux supprimer une branche Pour supprimer une branche distante : ```sh (main)$ git push origin --delete ma-branche ``` Vous pouvez aussi faire : ```sh (main)$ git push origin :ma-branche ``` Pour supprimer une branche locale : ```sh (main)$ git branch -d ma-branche ``` Pour supprimer une branche locale qui *n'a pas* Ă©tĂ© fusionnĂ©e vers la branche actuelle ou une branche distante : ```sh (main)$ git branch -D ma-branche ``` ### Je veux supprimer plusieurs branches Admettons que vous voulez supprimer toutes les branches qui commencent par `fix/` : ```sh (main)$ git branch | grep 'fix/' | xargs git branch -d ``` ### Je veux renommer une branche Je veux renommer la branche actuelle (locale) : ```sh (main)$ git branch -m nouveau-nom ``` Pour renommer une autre branche (locale) : ```sh (main)$ git branch -m ancien-nom nouveau-nom ``` ### Je veux me dĂ©placer sur une branche distante sur laquelle quelqu'un est en train de travailler Pour commencer, rĂ©cupĂ©rez toutes les branches depuis le dĂ©pĂŽt distant : ```sh (main)$ git fetch --all ``` Admettons que vous souhaitez vous dĂ©placer sur `daves` depuis le dĂ©pĂŽt distant : ```sh (main)$ git checkout --track origin/daves Branch daves set up to track remote branch daves from origin. Switched to a new branch 'daves' ``` (`--track` est un raccourci pour `git checkout -b [branch] [remotename]/[branch]`) Cela vous donnera une copie locale de la branche `daves`, et n'importe quelle mise Ă  jour qui y sera poussĂ©e sera aussi visible sur le dĂ©pĂŽt distant. ### Je veux crĂ©er une nouvelle branche distante Ă  partir de celle en locale ```sh $ git push HEAD ``` Si vous voulez configurer cette branche distante en tant qu'upstream pour la branche actuelle, lancez la commande suivante Ă  la place : ```sh $ git push -u HEAD ``` Avec le mode `upstream` et le mode `simple` (dĂ©faut dans Git 2.0) de la configuration de `push.default`, la commande suivante poussera la branche actuelle par rapport Ă  la branche distante qui a Ă©tĂ© prĂ©cĂ©demment enregistrĂ©e avec `-u` : ```sh $ git push ``` Le comportement des autres modes de `git push` est dĂ©taillĂ© dans la [documentation de `push.default`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault). ### Je veux configurer une branche distante en tant qu'upstream pour une branche locale Vous pouvez configurer une branche distante en tant qu'upstream pour la branche locale actuelle en utilisant : ```sh $ git branch --set-upstream-to [nomduremote]/[branche] # ou, en utilisant le raccourci : $ git branch -u [nomduremote]/[branche] ``` Pour configurer la branche distante en tant qu'upstream pour une autre branche locale : ```sh $ git branch -u [nomduremote]/[branche] [branche-locale] ``` ### Je veux configurer mon HEAD pour suivre la branche distante par dĂ©faut En vĂ©rifiant vos branches distantes, vous pouvez voir lesquelles d'entre-elles sont suivies par HEAD. Dans certains cas, ce n'est pas la branche dĂ©sirĂ©e. ```sh $ git branch -r origin/HEAD -> origin/gh-pages origin/main ``` Pour changer cela afin que `origin/HEAD` suive `origin/main`, vous pouvez lancer cette commande : ```sh $ git remote set-head origin --auto origin/HEAD set to main ``` ### J'ai fait des modifications sur la mauvaise branche Si vous avez fait des modifications non commitĂ©es et rĂ©alisez par la suite que vous ĂȘtes sur la mauvaise branche, remisez les modifications et appliquez-les sur la branche que vous voulez : ```sh (mauvaise_branche)$ git stash (mauvaise_branche)$ git checkout (bonne_branche)$ git stash apply ``` ## Rebaser et fusionner ### Je veux annuler un rebase/merge Il se peut que vous avez fait une fusion ou un rebase sur votre branche actuelle avec une mauvaise branche, ou que vous vous ĂȘtes perdus ou n'arrivez pas Ă  finir le processus de rebase ou de fusion. Git sauvegarde le pointeur de HEAD original dans une variable appelĂ©e ORIG_HEAD avant de faire des opĂ©rations dangereuses, afin qu'il soit plus facile de rĂ©initialiser votre branche dans l'Ă©tat avant le rebase ou la fusion : ```sh (ma-branche)$ git reset --hard ORIG_HEAD ``` ### J'ai rebase, mais je ne veux pas pousser de force Malheureusement, vous devez pousser de force si vous souhaitez que ces modifications soient rĂ©percutĂ©es sur la branche distante. C'est parce que vous avez changĂ© l'historique. La branche distante n'acceptera pas les modifications, sauf si vous poussez de force. C'est l'une des principales raisons pour lesquelles de nombreuses personnes utilisent un flux de travail Ă  base de fusions plutĂŽt qu'un flux de travail Ă  base de rebase : les grandes Ă©quipes peuvent avoir des problĂšmes avec les dĂ©veloppeurs qui poussent de force. Utilisez ceci avec prudence. Une façon plus sĂ»re d'utiliser rebase est de ne pas du tout reflĂ©ter vos modifications sur la branche distante, mais plutĂŽt de procĂ©der de la maniĂšre suivante : ```sh (main)$ git checkout ma-branche (ma-branche)$ git rebase -i main (ma-branche)$ git checkout main (main)$ git merge --ff-only ma-branche ``` Pour plus d'informations, visitez [ce thread de SO](https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push). ### J'ai besoin de combiner des commits Admettons que vous ĂȘtes en train de travailler sur une branche qui sera ou est dans une demande de fusion vers `main`. Dans le cas le plus simple, il suffit de combiner *tous* vos commits en un seul et vous vous fichez des timestamps des commits, vous pouvez faire un reset et recommiter. Assurez-vous que la branche main est Ă  jour et que toutes vos modifications sont commitĂ©es, puis faites : ```sh (ma-branche)$ git reset --soft main (ma-branche)$ git commit -am "Nouvelle fonctionnalitĂ© gĂ©niale" ``` Si vous voulez plus de contrĂŽle, et Ă©galement conserver les timestamps, vous devez faire ce qu'on appelle un rebase interactif : ```sh (ma-branche)$ git rebase -i main ``` Si vous ne travaillez pas par rapport Ă  une autre branche, vous allez devoir `rebase` relativement Ă  votre `HEAD`. Si vous voulez combiner les 2 derniers commits par exemple, vous allez devoir `rebase` par rapport Ă  `HEAD~2`. Pour les 3 derniers, `HEAD~3`, etc. ```sh (main)$ git rebase -i HEAD~2 ``` AprĂšs avoir lancĂ© votre commande `rebase`, vous verrez quelque chose dans le genre dans votre Ă©diteur de texte : ```vim pick a9c8a1d Un peu de refactor pick 01b2fd8 Nouvelle feature gĂ©nial pick b729ad5 fixup pick e3851e8 autre fix # Rebase 8074d12..b729ad5 onto 8074d12 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out ``` Toutes les lignes commençant par un `#` sont des commentaires, elles n'affecteront pas votre rebase. Vous devez ensuite remplacer les commandes `pick` avec n'importe laquelle parmi celles prĂ©sentes dans la liste ci-dessus, et vous pouvez Ă©galement supprimer des commits en supprimant les lignes correspondantes. Par exemple, si vous voulez **laisser le commit le plus vieux (le premier) tel quel et combiner tous les commits suivants avec le deuxiĂšme plus vieux**, vous devez remplacer les lettres Ă  cĂŽtĂ© de chaque commit sauf le premier et le deuxiĂšme par un `f` : ```vim pick a9c8a1d Un peu de refactor pick 01b2fd8 Nouvelle feature gĂ©niale f b729ad5 fixup f e3851e8 autre fix ``` Si vous voulez combiner ces commits **et renommer le commit**, il vous faudra ajouter un `r` Ă  cĂŽtĂ© du deuxiĂšme commit ou utiliser simplement `s` au lieu de `f` : ```vim pick a9c8a1d Un peu de refactor pick 01b2fd8 Nouvelle feature gĂ©niale s b729ad5 fixup s e3851e8 autre fix ``` Vous pouvez ensuite renommer le commit dans le prochain Ă©diteur de texte qui s'affiche : ```vim Nouvelles fonctionnalitĂ©s encore plus gĂ©niales # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # rebase in progress; onto 8074d12 # You are currently editing a commit while rebasing branch 'main' on '8074d12'. # # Changes to be committed: # modified: README.md # ``` Si tout se passe bien, vous devriez voir quelque chose comme ceci : ```sh (main)$ Successfully rebased and updated refs/heads/main. ``` #### StratĂ©gie de fusion sĂ»re `--no-commit` fait une fusion mais prĂ©tend que la fusion a Ă©chouĂ© et ne commit pas automatiquement, laissant la chance Ă  l'utilisateur d'inspecter plus et de bidouiller plus les rĂ©sultats de la fusion avant de commiter. `no-ff` garde une preuve qu'une branche de fonctionnalitĂ© a auparavant existĂ©, gardant ainsi l'historique du projet consistant : ```sh (main)$ git merge --no-ff --no-commit ma-branche ``` #### J'ai besoin de fusionner deux branches en un seul commit ```sh (main)$ git merge --squash ma-branche ``` #### Je veux combiner les commits non poussĂ©s uniquement Parfois, vous avez plusieurs commits en cours que vous souhaitez combiner avant de les pousser sur l'upstream. Vous ne voulez pas combiner des commits qui ont dĂ©jĂ  Ă©tĂ© poussĂ©s sur l'upstream par accident, car quelqu'un d'autre a peut-ĂȘtre dĂ©jĂ  effectuĂ© des commits qui y font rĂ©fĂ©rence : ```sh (main)$ git rebase -i @{u} ``` Cela fera un rebase interactif que liste seulement les commits que vous n'avez pas poussĂ©, afin que cela soit plus sĂ»r de rĂ©ordonner/corriger/combiner n'importe lesquels de la liste. #### J'ai besoin d'annuler la fusion Parfois, une fusion peux produire des problĂšmes pour certains fichiers. Dans ces cas lĂ , nous pouvons utiliser l'option `abort` afin d'abonner le processus de rĂ©solution de conflits en cours, afin d'essayer de reconstruire l'Ă©tat qu'on avait avant la fusion : ```sh (ma-branche)$ git merge --abort ``` Cette commande est disponible dans Git depuis les versions >= 1.7.4 ### J'ai besoin de mettre Ă  jour le commit parent de ma branche Admettons que vous avez une branche main, une branche feature-1 crĂ©Ă©e Ă  partir de main, et une branche feature-2 crĂ©Ă©e Ă  partir de feature-1, puis que le commit parent de feature-2 n'est plus le bon (il devrait ĂȘtre celui correspondant au HEAD de feature-1, Ă©tant donnĂ© que notre branche a Ă©tĂ© crĂ©Ă©e Ă  partir de celui-ci). Vous pouvez rĂ©parer ça avec `git rebase --onto` : ```sh (feature-2)$ git rebase --onto feature-1 feature-2 ``` Cela peut vous venir en aide dans les situations dĂ©licates oĂč vous avez une fonctionnalitĂ© crĂ©Ă©e sur la base d'une autre fonctionnalitĂ© qui n'a pas encore Ă©tĂ© fusionnĂ©e, et qu'une correction de bug sur la branche feature-1 a besoin d'ĂȘtre reflĂ©tĂ©e sur votre branche feature-2. ### VĂ©rifier si tous les commits d'une branche sont fusionnĂ©s Pour vĂ©rifier si tous les commits d'une branche sont fusionnĂ©s sur une autre branche, vous devriez comparer les HEAD (ou n'importe quel autre commit) de ces branches : ```sh (main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll ``` Cela vous dira si des commits sont dans l'une mais pas dans l'autre, et vous donnera une liste de tout ce qui n'est pas commun aux deux branches. Une alternative est de faire ceci : ```sh (main)$ git log main ^feature/120-on-scroll --no-merges ``` ### ProblĂšmes possibles avec les rebase interactifs #### L'Ă©cran d'Ă©dition du rebase affiche 'noop' Si vous voyez cela : ``` noop ``` Cela signifie que vous ĂȘtes en train de rebaser par rapport Ă  une branche qui a un commit identique, ou qui est *en avance* par rapport Ă  votre branche actuelle. Vous pouvez essayer : * de vous assurez que votre branche main est lĂ  oĂč elle devrait ĂȘtre * de rebaser par rapport Ă  `HEAD~2` ou plus tĂŽt Ă  la place #### Il y a eu des conflits Si vous n'ĂȘtes pas en mesure de terminer le rebase avec succĂšs, vous allez peut-ĂȘtre devoir rĂ©soudre des conflits. Pour commencer, lancez `git status` afin de voir quels fichiers ont des conflits : ```sh (ma-branche)$ git status On branch ma-branche Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) both modified: README.md ``` Dans cet exemple, `README.md` a des conflits. Ouvrez le fichier et cherchez la chose suivante : ```vim <<<<<<< HEAD some code ========= some code >>>>>>> nouveau-commit ``` Vous aurez besoin de rĂ©soudre les diffĂ©rences entre le code qui fut ajoutĂ© dans votre nouveau commit (dans cet exemple, tout ce qu'il y a entre la ligne du milieu et `nouveau-commit`) et votre `HEAD`. Si vous voulez garder la version du code d'une des branches, vous pouvez utiliser `--ours` ou `--theirs` : ```sh (main*)$ git checkout --ours README.md ``` - Quand vous *fusionnez*, utilisez `--ours` pour garder les modifications de la branche locale, ou `--theirs` pour garder les modifications de l'autre branche. - Quand vous *rebasez*, utilisez `--theirs` pour garder les modifications de la branche locale, ou `--ours` pour garder les modifications de l'autre branche. Pour des explications concernant cet Ă©change, consultez [cette note dans la documentation de Git](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge). Si les fusions sont plus complexes, vous pouvez utiliser un Ă©diteur de diff visuel : ```sh (main*)$ git mergetool -t opendiff ``` AprĂšs avoir rĂ©solu tous les conflits et testĂ© votre code, faite un `git add` sur les fichiers que vous avez modifiĂ©s, puis continuez le rebase avec `git rebase --continue` : ```sh (ma-branche)$ git add README.md (ma-branche)$ git rebase --continue ``` Si aprĂšs avoir rĂ©solu tous les conflits, vous finissez avec un arbre identique Ă  ce qu'il Ă©tait avant le commit, vous devriez faire un `git rebase --skip` Ă  la place. Si Ă  n'importe quel moment vous voulez arrĂȘter tout le rebase et revenir Ă  l'Ă©tat initial de votre branche, vous pouvez faire ceci : ```sh (ma-branche)$ git rebase --abort ``` ## Remisage ### Remiser toutes les modifications Pour remiser toutes les modifications dans votre dossier de travail : ```sh $ git stash ``` Si vous voulez Ă©galement remiser les fichiers non suivis, utilisez l'option `-u` : ```sh $ git stash -u ``` ### Remiser des fichiers spĂ©cifiques Pour remiser les modifications dans votre dossier de travail uniquement : ```sh $ git stash push chemin-du-dossier-de-travail/nomdufichier.ext ``` Pour remiser plusieurs fichiers de votre dossier de travail : ```sh $ git stash push chemin-du-dossier-de-travail/nomdufichier1.ext chemin-du-dossier-de-travail/nomdufichier2.ext ``` ### Remiser avec un message ```sh $ git stash save ``` ### Appliquer un remisage spĂ©cifique de la liste Commencez par vĂ©rifier la liste de vos remisages avec un message en utilisant : ```sh $ git stash list ``` Puis appliquez la commande suivante en choisissant un remisage de la liste : ```sh $ git stash apply "stash@{n}" ``` Ici, `n` indique la position du remisage dans la pile. Celui le plus haut sera en position 0. ## Rechercher ### Je veux rechercher une chaĂźne de caractĂšres dans un commit Pour rechercher une certaine chaĂźne de caractĂšres dans un commit, vous pouvez utiliser la commande suivante : ```sh $ git log -S "chaĂźne de caractĂšres Ă  rechercher" ``` ParamĂštres communs : * `--source` sert Ă  montrer le nom du ref en se basant sur la ligne de commande avec laquelle chaque commit a Ă©tĂ© atteint. * `--all` sert Ă  commencer depuis chaque branche. * `--reverse` retourne les rĂ©sultats dans l'ordre inverse, c'est Ă  dire que la commande affichera le premier commit qui a fait la modification. ### Je veux rechercher par auteur·trice/validateur·trice Pour rechercher des commits par auteur·trice/validateur·trice, vous pouvez utiliser : ```sh $ git log --author= $ git log --committer= ``` Gardez en tĂȘte que l'auteur·trice et la personne qui a crĂ©Ă© le commit ne sont pas les mĂȘmes personnes. L'option `--author` correspond Ă  la personne qui a Ă©crit le code, et, d'un autre cĂŽtĂ©, l'option `--committer`, correspond Ă  la personne qui a commitĂ© le code au nom de l'autreur·trice. ### Je veux lister les commits ayant des fichiers spĂ©cifiques Pour trouver tous les commits contenant un fichier spĂ©cifique, vous pouvez utiliser : ```sh $ git log -- ``` En gĂ©nĂ©ral, vous prĂ©ciseriez un chemin exact, mais vous pouvez aussi utiliser des wildcards dans le chemin et le nom du fichier : ```sh $ git log -- **/*.js ``` En utilisant des wildcards, il est utile de prĂ©ciser `--name-status` pour voir la liste des fichiers commitĂ©s : ```sh $ git log --name-status -- **/*.js ``` ### Trouver un tag oĂč un commit est rĂ©fĂ©rencĂ© Pour trouver tous les tags contenant un commit en particulier : ```sh $ git tag --contains ``` ## Sous-modules ### Cloner tous les sous-modules ```sh $ git clone --recursive git://github.com/foo/bar.git ``` Si ces derniers ont dĂ©jĂ  Ă©tĂ© clonĂ©s : ```sh $ git submodule update --init --recursive ``` ### Retirer un sous-module CrĂ©er un sous-module est assez trivial, mais le supprimer l'est moins. Les commandes dont vous avez besoin sont : ```sh $ git submodule deinit nomdusubmodule $ git rm nomdusubmodule $ git rm --cached nomdusubmodule $ rm -rf .git/modules/nomdusubmodule ``` ## Objets divers ### RĂ©cupĂ©rer un fichier supprimĂ© Trouvez le commit le plus rĂ©cent oĂč le fichier existait encore : ```sh $ git rev-list -n 1 HEAD -- nomdufichier ``` Puis faites un `checkout` sur ce fichier : ``` git checkout idducommitquiasupprimĂ©^ -- nomdufichier ``` ### Supprimer un tag ```sh $ git tag -d $ git push :refs/tags/ ``` ### RĂ©cupĂ©rer un tag supprimĂ© Si vous voulez rĂ©cupĂ©rer un tag qui a dĂ©jĂ  Ă©tĂ© supprimĂ©, vous pouvez le faire en suivant ces Ă©tapes : Tout d'abord, vous devez retrouver le tag inaccessible en question : ```sh $ git fsck --unreachable | grep tag ``` Notez le hash du tag dans un coin. Puis, restaurez le tag supprimĂ© avec la commande suivante, qui utilise [`git update-ref`](https://git-scm.com/docs/git-update-ref) : ```sh $ git update-ref refs/tags/ ``` Votre tag devrait maintenant ĂȘtre restaurĂ©. ### Patch supprimĂ© Si quelqu'un vous a envoyĂ© une Pull Request sur GitHub, mais a par la suite supprimĂ© son fork originel, vous ne serez pas en mesure de cloner son dĂ©pĂŽt ou d'utiliser `git am` Ă©tant donnĂ© que les URLs de [.diff, .patch](https://github.com/blog/967-github-secrets) sont devenues indisponibles. Mais vous pouvez vous dĂ©placer sur la PR en elle-mĂȘme en utilisant les [les refs spĂ©ciaux de GitHub](https://gist.github.com/piscisaureus/3342247). Pour rĂ©cupĂ©rer le contenu de PR#1 vers une nouvelle branche intitulĂ©e pr_1 : ```sh $ git fetch origin refs/pull/1/head:pr_1 From github.com:foo/bar * [new ref] refs/pull/1/head -> pr_1 ``` ### Exporter un dĂ©pĂŽt comme fichier Zip ```sh $ git archive --format zip --output /full/path/to/zipfile.zip main ``` ### Pousser une branche et un tag qui ont le mĂȘme nom Si un tag sur le dĂ©pĂŽt distant a le mĂȘme nom qu'une branche, vous aurez le message d'erreur suivant en essayant de pousser cette branche avec la commande standard `$ git push ` : ```sh $ git push origin error: dst refspec same matches more than one. error: failed to push some refs to '' ``` RĂ©parez cela en spĂ©cifiant que vous voulez pousser la rĂ©fĂ©rence de HEAD : ```sh $ git push origin refs/heads/ ``` Si vous voulez pousser un tag sur un dĂ©pĂŽt distant qui a le mĂȘme nom qu'une branche, vous pouvez utiliser une commande similaire : ```sh $ git push origin refs/tags/ ``` ## Suivre des fichiers ### Je veux changer la capitalisation du nom d'un fichier, sans changer son contenu ```sh (main)$ git mv --force monFichier MonFichier ``` ### Je veux Ă©craser des fichiers locaux en faisant un git pull ```sh (main)$ git fetch --all (main)$ git reset --hard origin/main ``` ### Je veux retirer un fichier de Git mais garder le fichier ```sh (main)$ git rm --cached log.txt ``` ### Je veux rĂ©tablir un fichier Ă  une version spĂ©cifique Supposons que le hash du commit que vous voulez est `c5f567` : ```sh (main)$ git checkout c5f567 -- file1/to/restore file2/to/restore ``` Si vous voulez rĂ©tablir les changements effectuĂ©s un commit avant `c5f567`, passez le hash du commit comme Ă©tant `c5f567~1` : ```sh (main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore ``` ### Je veux lister les changements d'un fichier spĂ©cifique entre deux commits ou branches Supposons que vous voulez comparer le dernier commit avec le fichier du commit `c5f567` : ```sh $ git diff HEAD:path_to_file/file c5f567:path_to_file/file # ou $ git diff HEAD c5f567 -- path_to_file/file ``` Il en est de mĂȘme pour les branches : ```sh $ git diff main:path_to_file/file staging:path_to_file/file # ou $ git diff main staging -- path_to_file/file ``` ### Je veux que Git ignore les changements d'un fichier spĂ©cifique Cela marche trĂšs bien pour le modĂšles de configurations ou d'autres fichier qui nĂ©cessitent d'ajouter des identifiants qui ne devraient pas ĂȘtre commitĂ©s : ```sh $ git update-index --assume-unchanged file-to-ignore ``` Notez que cela n'enlĂšve *pas* le fichier du suivi - il est seulement ignorĂ© localement. Pour annuler cela et dire Ă  Git de suivre les modifications Ă  nouveau, cette commande supprime le fait d'ignorer : ```sh $ git update-index --no-assume-unchanged fichier-Ă -ne-plus-ignorer ``` ## ParamĂ©trage ### Je veux ajouter des alias pour certaines commandes Git Sur macOS et Linux, votre fichier de configuration Git est stockĂ© dans `~/.gitconfig`. J'ai ajoutĂ© des exemples d'alias que j'utilise comme raccourcis (et certaines de mes fautes de frappes) dans la section `[alias]` comme ci-dessous : ```vim [alias] a = add amend = commit --amend c = commit ca = commit --amend ci = commit -a co = checkout d = diff dc = diff --changed ds = diff --staged extend = commit --amend -C HEAD f = fetch loll = log --graph --decorate --pretty=oneline --abbrev-commit m = merge one = log --pretty=oneline outstanding = rebase -i @{u} reword = commit --amend --only s = status unpushed = log @{u} wc = whatchanged wip = rebase -i @{u} zap = fetch -p ``` ### Je veux ajouter un rĂ©pertoire vide Ă  mon dĂ©pĂŽt Vous ne pouvez pas ! Git ne supporte pas cela, mais il y a une astuce. Vous pouvez crĂ©er un fichier `.gitignore` dans le dossier avec le contenu suivant : ``` # Ignorer tout dans ce dossier * # Sauf ce fichier !.gitignore ``` Une autre convention commune est de crĂ©er un fichier vide dans le dossier, intitulĂ© `.gitkeep` : ```sh $ mkdir mondossier $ touch mondossier/.gitkeep ``` Vous pouvez aussi juste appeler le fichier `.keep`, dans ce cas la commande ci-dessus serait `touch mydir/.keep`. ### Je veux mettre en cache un nom d'utilisateur et mot de passe pour un dĂ©pĂŽt Il se peut que vous ayez un dĂ©pĂŽt qui nĂ©cessite une authentification. Dans ce cas, vous pouvez mettre en cache un nom d'utilisateur et un mot de passe afin que vous n'ayez pas Ă  les rentrer Ă  chaque push / pull. Cette commande peut faire cela pour vous : ```sh $ git config --global credential.helper cache # Configure Git pour utiliser le cache mĂ©moire des identifiants ``` ```sh $ git config --global credential.helper 'cache --timeout=3600' # Configurer le cache pour expirer aprĂšs une heure (le paramĂštre est en secondes) ``` ### Je veux que Git ignore les changements de permissions et de filemode ```sh $ git config core.fileMode false ``` Si vous voulez configurer cela comme Ă©tant le comportement par dĂ©faut pour les utilisateurs connectĂ©s, utilisez : ```sh $ git config --global core.fileMode false ``` ### Je veux dĂ©finir un utilisateur global Pour configurer des informations d'utilisateur Ă  travers tous les dĂ©pĂŽts locaux, et pour configurer un nom qui est identifiable en relisant l'historique : ```sh $ git config --global user.name “[prĂ©nom nom]” ``` Pour configurer une adresse email qui sera associĂ©e Ă  chaque ligne de l'historique : ```sh git config --global user.email “[adresse-email-valide]” ``` ## Je n'ai aucune idĂ©e de ce que j'ai mal fait Donc, vous ĂȘtes fichu - vous avez `reset` quelque chose, ou vous avez fusionnĂ© la mauvaise branche, ou vous avez poussĂ© de force et maintenant vous ne pouvez plus trouver vos commits. Vous savez qu'Ă  un moment donnĂ©, tout allait bien, et vous voulez revenir Ă  un Ă©tat dans lequel vous Ă©tiez avant. C'est lĂ  qu'intervient `git reflog`. `reflog` garde trace de tous les changements du bout de la branche, mĂȘme si ce dernier n'est pas rĂ©fĂ©rencĂ© par une branche ou un tag. Fondamentalement, chaque fois que le HEAD change, une nouvelle entrĂ©e est ajoutĂ©e au reflog. Cela marche seulement pour les dĂ©pĂŽts locaux, malheureusement, et ne trace que les mouvements (pas les changements d'un fichier qui n'ont Ă©tĂ© enregistrĂ©s nulle part, par exemple). ```sh (main)$ git reflog 0a2e358 HEAD@{0}: reset: moving to HEAD~2 0254ea7 HEAD@{1}: checkout: moving from 2.2 to main c10f740 HEAD@{2}: checkout: moving from main to 2.2 ``` Le `reflog` ci-dessus indique un dĂ©placement depuis main vers la branche 2.2 et l'inverse. À partir de lĂ , il y a un hard `reset` vers un commit plus vieux. La derniĂšre activitĂ© est reprĂ©sentĂ©e en haut et intitulĂ©e `HEAD@{0}`. Si il s'avĂšre que vous ĂȘtes accidentellement revenu en arriĂšre, le reflog contiendra le commit sur lequel pointait main (0254ea7) avant que vous ne supprimiez 2 commits par accident. ```sh $ git reset --hard 0254ea7 ``` En utilisant `git reset`, il est ensuite possible de changer main vers le commit vers lequel il pointait. Cela vous donne de la sĂ»retĂ© dans le cas oĂč l'historique a Ă©tĂ© changĂ© par accident. (copiĂ© et Ă©ditĂ© depuis [Source](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)). # Autres Ressources ## Livres * [Learn Enough Git to Be Dangerous](https://www.learnenough.com/git-tutorial) - Un livre de Michael Hartl couvrant les bases de Git * [Pro Git](https://git-scm.com/book/en/v2) - L'excellent livre de Scott Chacon et Ben Straub Ă  propos de Git * [Git Internals](https://github.com/pluralsight/git-internals-pdf) - L'autre excellent livre de Scott Chacon Ă  propos de Git ## Tutoriels * [19 Git Tips For Everyday Use](https://www.alexkras.com/19-git-tips-for-everyday-use) - Une liste de commandes Git utiles qui prennent une ligne. * [Atlassian's Git tutorial](https://www.atlassian.com/git/tutorials) Comprendre Git avec des tutos Ă  partir du niveau dĂ©butant jusqu'au plus avancĂ©. * [Learn Git branching](https://learngitbranching.js.org/) Un tutoriel interfactif Ă  base de branch/merge/rebase * [Getting solid at Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa) * [Git Commands and Best Practices Cheat Sheet](https://zeroturnaround.com/rebellabs/git-commands-and-best-practices-cheat-sheet) - Un aide-mĂ©moire Git dans un article de blog avec plus d'explications * [Git from the inside out](https://codewords.recurse.com/issues/two/git-from-the-inside-out) - Un tutoriel qui plonge dans le fonctionnement interne de Git * [git-workflow](https://github.com/asmeurer/git-workflow) - Le tuto d'[Aaron Meurer](https://github.com/asmeurer) Ă  propos de l'utilisation de Git pour contribuer aux dĂ©pĂŽts open source * [GitHub as a workflow](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - Un point de vue intĂ©ressant sur l'utilisation de Github en tant que workflow, particuliĂšrement avec des demandes de fusion vides. * [Githug](https://github.com/Gazler/githug) - Un jeu pour apprendre les workflows Git les plus communs ## Scripts et Outils * [firstaidgit.io](http://firstaidgit.io/) Un sĂ©lection recherchable des questions Git les plus souvent posĂ©es * [git-extra-commands](https://github.com/unixorn/git-extra-commands) - Une collection de scripts Git supplĂ©mentaires trĂšs utiles * [git-extras](https://github.com/tj/git-extras) - utilitaires GIT -- rĂ©sumĂ© de dĂ©pĂŽts, repl, population de changelogs, pourcentage de commits par auteur·trice et plus * [git-fire](https://github.com/qw3rtman/git-fire) - git-fire est un plugin Git qui vient en aide en cas d'urgence en ajoutant tous les fichier actuels, les commitant, et les poussant vers une nouvelle branche (afin d'Ă©viter les conflits). * [git-tips](https://github.com/git-tips/tips) - Des petites astuces Git * [git-town](https://github.com/Originate/git-town) - Un support de flux de travail Git gĂ©nĂ©rique et de haut-niveau ! http://www.git-town.com ## Clients graphiques * [GitKraken](https://www.gitkraken.com/) - Le client Git de luxe pour Windows, Mac & Linux * [git-cola](https://git-cola.github.io/) - Un autre client Git pour Windows et macOS * [GitUp](https://github.com/git-up/GitUp) - Un client graphique rĂ©cent qui a une maniĂšre dogmatique de gĂ©rer les complications de Git * [gitx-dev](https://rowanj.github.io/gitx/) - un autre client Git graphique pour macOS * [Sourcetree](https://www.sourcetreeapp.com/) - La simplicitĂ© alliĂ©e Ă  la puissance dans une belle interface gratuite. Pour Windows et Mac * [Tower](https://www.git-tower.com/) - Un client graphique pour macOS (payant) * [tig](https://jonas.github.io/tig/) - terminal text-mode interface for Git * [Magit](https://magit.vc/) - Une interface pour Git implĂ©mentĂ©e en tant que paquet Emacs. * [GitExtensions](https://github.com/gitextensions/gitextensions) - Une extension du shell, un plugin Visual Studio 2010-2015 et un outil de repo Git. * [Fork](https://git-fork.com/) - Un client Git rapide et amical pour Mac (beta) * [gmaster](https://gmaster.io/) - Un client Git pour Windows qui permet les fusions Ă  3 branches, l'analyse de refactorisation, un diff et merge sĂ©mantique (beta) * [gitk](https://git-scm.com/docs/gitk) - Un client Git pour Linux qui permet d'avoir une vue simplifiĂ©e de l'Ă©tat d'un repo. * [SublimeMerge](https://www.sublimemerge.com/) - Un client ultra rapide et extensible qui donne la possibilitĂ© de faire des fusions Ă  3 branches, de la recherche avancĂ©e et de la colorisation syntaxique, en dĂ©veloppement actif.