Ce mémo rassemble les commandes Git que j’utilise (ou que tout le monde finit par chercher un jour) : du git init de base jusqu’au workflow de branches que j’utilise sur mes projets homelab. Pensé pour être copié-collé directement dans un terminal, que vous débutez ou que vous ayez juste besoin de chercher une simple commande.

Sommaire


Configuration initiale

Commande Explication
git config --global user.name "Noé" Définit votre nom pour tous les dépôts
git config --global user.email "noe@example.com" Définit votre email pour tous les dépôts
git config --global core.editor "vim" Définit l’éditeur utilisé par Git (messages de commit, rebase interactif…)
git config --global init.defaultBranch main Renomme la branche par défaut créée par git init
git config --list Affiche toute la configuration active
git config --list --show-origin Affiche la config avec le fichier d’origine de chaque valeur
git config user.email "..." Change la config uniquement pour le dépôt courant (sans --global)
git config --global alias.st status Crée un alias de commande (ici git st)

Créer / cloner un dépôt

Commande Explication
git init mon-projet Crée un nouveau dépôt local dans un dossier
git clone <url> Clone un dépôt distant en local
git clone <url> mon-dossier Clone dans un dossier au nom choisi
git clone -b develop --single-branch <url> Clone uniquement la branche develop
git clone --depth 1 <url> Clone superficiel : ne récupère que le dernier commit (plus rapide)

Le cycle de base

Commande Explication
git status Affiche l’état du dépôt (fichiers modifiés, indexés, etc.)
git status -s Version courte du statut
git add fichier.py Ajoute un fichier précis à l’index (staging)
git add . Ajoute tous les fichiers du dossier courant
git add -A Ajoute tout le dépôt, y compris les suppressions
git add -p Ajout interactif, hunk par hunk
git commit -m "message" Crée un commit avec un message
git commit -am "message" Ajoute (fichiers déjà suivis) et committe en une commande
git commit --amend Modifie le dernier commit (message et/ou contenu)
git diff Différences non indexées vs dernier commit
git diff --staged Différences indexées vs dernier commit
git diff HEAD~1 HEAD Différences entre deux commits

Branches

Commande Explication
git branch Liste les branches locales
git branch -a Liste aussi les branches distantes
git branch feature/dark-mode Crée une nouvelle branche
git checkout -b feature/dark-mode Crée une branche et bascule dessus
git switch -c feature/dark-mode Équivalent moderne de la commande ci-dessus
git checkout main Bascule sur la branche main
git switch main Équivalent moderne pour basculer de branche
git branch -m nouveau-nom Renomme la branche courante
git branch -d feature/dark-mode Supprime une branche locale déjà fusionnée
git branch -D feature/dark-mode Force la suppression, même non fusionnée
git push origin --delete feature/dark-mode Supprime la branche sur le dépôt distant
git branch --contains <hash> Liste les branches contenant un commit donné

Stratégie de branches : unstable/development & stable

Un modèle simple et robuste, adapté à un projet solo ou petite équipe : une branche stable qui reflète toujours un état fonctionnel/déployable, et une branche unstable/development où le travail actif se fait.

Mise en place initiale

Commande Explication
git branch -m main stable Renomme la branche main existante en stable
git push -u origin stable Pousse et lie la branche stable au dépôt distant
git checkout stable Se place sur stable avant de créer la branche de dev
git checkout -b unstable/development Crée la branche de développement à partir de stable
git push -u origin unstable/development Pousse et lie la branche unstable/development

Workflow quotidien

On travaille toujours sur unstable/development (ou une sous-branche)

git checkout unstable/development
git pull origin unstable/development

Option A : commit direct sur unstable/development

git add .
git commit -m "Ajout d'une fonction de téléchargement en arrière-plan"
git push origin unstable/development

Il est toujours bon de faire des messages de commit en anglais. Dans cet exemple il est en français, c’est faisable aussi mais il faut toujours le faire en anglais.

Option B (recommandée) : une branche de feature par sujet,

# Fusionnée dans unstable/development
git checkout unstable/development
git checkout -b feature/background-download

# Commit de ma fonctionnalité
git add .
git commit -m "Ajout d'une fonction de téléchargement en arrière-plan"
git checkout unstable/development
git merge --no-ff feature/background-download
git push origin unstable/development
git branch -d feature/background-download

Promotion vers stable

# Une fois que unstable/development est testée et jugée fiable :
git checkout stable
git pull origin stable
git merge --no-ff unstable/development -m "Merge unstable/development into stable"
git push origin stable

# Marquer la version stable avec un tag (bonne pratique)
git tag -a v1.4.0 -m "Version stable 1.4.0"
git push origin v1.4.0

Correctif urgent sur stable (hotfix)

git checkout stable
git checkout -b hotfix/fix-buffer-overflow
# ... correctif ...
git commit -am "Fix d'un dépassement de mémoire tempon"

# On merge le hotfix dans stable ET dans unstable/development
git checkout stable
git merge --no-ff hotfix/fix-buffer-overflow
git push origin stable

git checkout unstable/development
git merge --no-ff hotfix/fix-buffer-overflow
git push origin unstable/development

git branch -d hotfix/fix-buffer-overflow

Variante GitFlow-like : ajouter des branches feature/*, release/* et hotfix/* autour des deux branches principales si le projet grossit. Pour un projet en solo, le schéma stable + unstable/development + branches de feature courtes suffit largement.


Fusion et rebase

Commande Explication
git merge unstable/development Fusion classique, garde l’historique des deux branches
git merge --no-ff unstable/development Fusion sans fast-forward, force un commit de merge (traçabilité)
git rebase unstable/development Rejoue les commits de la branche courante sur une autre base
git rebase -i HEAD~5 Rebase interactif : réécrire, squasher, réordonner des commits
git rebase --abort Annule un rebase en cours si les conflits sont ingérables
git rebase --continue Continue le rebase après résolution d’un conflit

Merge vs rebase, en bref :

  • merge : préserve l’historique réel, crée un commit de fusion. Sûr sur des branches partagées comme stable.
  • rebase : historique linéaire et propre, mais réécrit les commits (hash différents). À éviter sur des branches déjà partagées/publiées.

Remote (dépôts distants)

Commande Explication
git remote -v Affiche les remotes configurés
git remote add origin <url> Ajoute un remote nommé origin
git remote set-url origin <url> Change l’URL d’un remote existant
git fetch origin Récupère les changements sans les fusionner
git pull origin unstable/development Récupère et fusionne (fetch + merge)
git pull --rebase origin unstable/development Pull avec rebase au lieu de merge
git push -u origin unstable/development Pousse une branche et lie le suivi (upstream)
git push --force Pousse en forçant (danger : réécrit l’historique distant)
git push --force-with-lease Force-push plus sûr, échoue si quelqu’un d’autre a poussé entre-temps

Historique et inspection

Commande Explication
git log Historique complet des commits
git log --oneline Historique compact, une ligne par commit
git log --oneline --graph --all --decorate Historique graphique avec toutes les branches
git blame fichier.py Voir qui a modifié quoi, ligne par ligne
git show <hash> Affiche le détail d’un commit précis
git log -S "texte" Recherche un texte dans les diffs des commits
git log --grep="firewall" Recherche dans les messages de commit
git show --stat HEAD Fichiers modifiés dans le dernier commit

Annuler des changements

Commande Explication
git restore --staged fichier.py Retire un fichier de la zone de staging (sans perdre les modifs)
git restore fichier.py Annule les modifications locales d’un fichier (perte définitive)
git reset --soft HEAD~1 Revient un commit en arrière, modifs gardées en staging
git reset --mixed HEAD~1 Revient un commit en arrière, modifs remises en non-indexé (par défaut)
git reset --hard HEAD~1 Revient un commit en arrière, tout est perdu (attention)
git revert <hash> Crée un nouveau commit qui annule un commit existant (sûr sur branche partagée)

Stash

Il arrive régulièrement qu’on ait besoin de mettre du travail de côté le temps de traiter une tâche prioritaire sur notre projet ou de récupérer les nouveautés produites par nos collègues qui sont nécessaires à notre travail courant. Plutôt que de créer un commit dont les contenus seront mal finis, nous préférerons isoler ce travail dans la remise Git, appelée stash en anglais.

Source : https://comprendre-git.com/fr/commandes/git-stash/

Commande Explication
git stash Met de côté les modifications en cours
git stash push -m "message" Stash avec un message descriptif
git stash list Liste les stash existants
git stash pop Réapplique le dernier stash et le retire de la liste
git stash apply Réapplique sans le retirer de la liste
git stash apply stash@{2} Réapplique un stash précis
git stash drop stash@{2} Supprime un stash précis
git stash clear Vide tous les stash

Tags

Commande Explication
git tag v1.0.0 Crée un tag léger
git tag -a v1.0.0 -m "message" Crée un tag annoté (recommandé, contient auteur/date/message)
git tag Liste tous les tags
git push origin v1.0.0 Pousse un tag précis
git push origin --tags Pousse tous les tags
git tag -d v1.0.0 Supprime un tag localement
git push origin --delete v1.0.0 Supprime un tag sur le dépôt distant

Cherry-pick

Le Git Cherry Pick permet de copier un commit d’une branche à une autre.

Source : https://dev.to/aurelievache/git-par-lexemple-cherie-ca-va-cherry-picker--37c8

Commande Explication
git cherry-pick <hash> Applique un commit précis d’une autre branche sur la branche courante
git cherry-pick <hash1> <hash2> Cherry-pick plusieurs commits
git cherry-pick --no-commit <hash> Applique sans committer directement (pour ajuster avant)

Utile typiquement pour porter un correctif de hotfix/* vers unstable/development sans tout fusionner.


Submodules

Les submodule permet d’ajouter directement un module à son dépôt sans à devoir cloner manuellement le module entier. Par exemple, pour ajouter un thème dans Hugo ça fonctionne par un système de submodules.

Commande Explication
git submodule add <url> chemin/ Ajoute un submodule dans le dépôt
git clone --recurse-submodules <url> Clone un dépôt avec ses submodules
git submodule update --init --recursive Initialise les submodules après un clone classique
git submodule update --remote --merge Met à jour tous les submodules

.gitignore & fichiers ignorés

Commande Explication
git status --ignored Affiche quels fichiers sont ignorés
git rm --cached fichier-secret.env Arrête de suivre un fichier sans le supprimer du disque
git check-ignore -v chemin/fichier Vérifie pourquoi un fichier est ignoré

Exemple de .gitignore :

__pycache__/
*.pyc
.env
node_modules/
.DS_Store
*.log

git bisect : trouver un commit fautif

Très utile pour retrouver quel commit a introduit un bug, par recherche dichotomique automatique.

Commande Explication
git bisect start Démarre une session de recherche
git bisect bad Marque le commit actuel comme mauvais (bug présent)
git bisect good v1.2.0 Marque un ancien commit connu comme bon (bug absent)
git bisect good / git bisect bad Indique le résultat du test sur le commit proposé par Git
git bisect reset Termine la session une fois le commit fautif trouvé
git bisect run ./test-script.sh Automatise la recherche avec un script qui retourne 0 (bon) ou 1 (mauvais)

git worktree : plusieurs branches en parallèle

Permet d’avoir plusieurs branches “checkout” en même temps, chacune dans son propre dossier, sans avoir à cloner le dépôt plusieurs fois ni à stash sans arrêt.

Commande Explication
git worktree add ../projet-dev unstable/development Ajoute un worktree pour une branche donnée dans un autre dossier
git worktree list Liste les worktrees actifs
git worktree remove ../projet-dev Supprime un worktree
git worktree prune Nettoie les références obsolètes

Exemple concret : garder ~/block-asn-noise sur stable en prod, et travailler dans ~/block-asn-noise-dev sur unstable/development sans changer de branche à répétition.


Sparse checkout : ne cloner qu’une partie du dépôt

Commande Explication
git clone --no-checkout --filter=blob:none <url> Clone sans checkout initial, sans télécharger tous les blobs
git sparse-checkout init --cone Active le mode sparse checkout
git sparse-checkout set scripts/ docs/ Choisit les dossiers à réellement récupérer
git checkout unstable/development Effectue le checkout une fois la config posée

Pratique sur un monorepo volumineux quand on n’a besoin que d’un sous-dossier (par exemple juste scripts/ d’un dépôt).


Signer ses commits (GPG / SSH)

Commande Explication
gpg --full-generate-key Génère une nouvelle clé GPG
gpg --list-secret-keys --keyid-format=long Liste les clés GPG disponibles
git config --global user.signingkey <ID_CLE> Associe une clé de signature à ta config Git
git config --global commit.gpgsign true Signe automatiquement tous les commits
git commit -S -m "message" Signe un commit ponctuellement
git log --show-signature -1 Vérifie la signature du dernier commit
git config --global gpg.format ssh Passe en mode signature via clé SSH (alternative moderne à GPG)

Signer ses dépôts garantissent que les commits poussés sur GitHub proviennent bien de vous.


Git hooks

Scripts exécutés automatiquement à certains moments du cycle de vie Git, stockés dans .git/hooks/. L’objectif des hooks est simple : il s’agit de fournir des enrobages à certaines commandes pour permettre l’injection de scripts (Bash, Node.js, Perl, Python, PHP…). De cette manière nous pouvons automatiser et donc fiabiliser une partie du travail côté client (machine de l’utilisateur) mais aussi côté serveur.

Source : https://comprendre-git.com/fr/automatisation/git-hooks/

Hook Quand il se déclenche
pre-commit Juste avant la création d’un commit (ex : lancer des tests)
commit-msg Pour valider/formater le message de commit
pre-push Avant un git push
post-checkout Après un changement de branche

Exemple : hook pre-commit qui bloque le commit si un test échoue

cat <<'EOF' > .git/hooks/pre-commit
#!/bin/sh
./run-tests.sh
EOF
chmod +x .git/hooks/pre-commit

Les hooks ne sont pas versionnés par défaut (ils vivent dans .git/, non suivi). Pour les partager avec une équipe, utiliser un outil comme Husky (Node) ou configurer core.hooksPath vers un dossier versionné : git config core.hooksPath .githooks


.gitattributes

Exemple de fichier .gitattributes :

# Normaliser les fins de ligne
* text=auto eol=lf

# Traiter certains fichiers comme binaires (pas de diff texte)
*.png binary
*.jpg binary

# Fichiers à exclure des exports (git archive)
docs/internal.md export-ignore

# Forcer un diff spécifique pour certains types
*.ipynb diff=jupyternotebook

Git LFS (gros fichiers)

Pour versionner de gros binaires (images, audio, ISOs) sans alourdir l’historique Git.

Commande Explication
git lfs install Installe Git LFS dans le dépôt
git lfs track "*.iso" Suit un type de fichier via LFS
git add .gitattributes Committe la config LFS générée
git lfs ls-files Liste les fichiers suivis par LFS
git lfs pull Récupère les fichiers LFS après un clone

rerere : réutiliser la résolution de conflits

rerere (reuse recorded resolution) mémorise comment un conflit a été résolu, pour l’appliquer automatiquement s’il revient (typique lors de rebases répétés).

Commande Explication
git config rerere.enabled true Active rerere pour le dépôt
git rerere status Affiche l’état des résolutions enregistrées
git rerere diff Montre le diff de la résolution enregistrée

Alias utiles

Commande de config Résultat
git config --global alias.st status git stgit status
git config --global alias.co checkout git cogit checkout
git config --global alias.br branch git brgit branch
git config --global alias.cm "commit -m" git cm "msg"git commit -m "msg"
git config --global alias.lg "log --oneline --graph --all --decorate" git lg → historique graphique compact
git config --global alias.last "log -1 HEAD" git last → détail du dernier commit
git config --global alias.unstage "restore --staged" git unstage fichier → retire du staging

Bonnes pratiques de messages de commit

<type>(<scope>): <résumé court à l'impératif>

<corps optionnel expliquant le pourquoi, pas juste le quoi>

<footer optionnel : issues liées, breaking changes>
Exemple Type
fix(firewall): ajoute la règle ESTABLISHED,RELATED avant les DROP ipset fix
feat(dashboard): ajoute l'affichage de l'uptime dans 00-custom-dashboard feat
docs(readme): met à jour les instructions d'installation curl | bash docs
chore(deps): met à jour mutagen vers la dernière version chore

Types courants : feat, fix, docs, style, refactor, perf, test, chore.


Dépannage courant

Problème / Commande Explication
git pull origin main --allow-unrelated-histories Corrige “fatal: refusing to merge unrelated histories”
git status Voir les fichiers en conflit après un merge/rebase raté
git diff --name-only --diff-filter=U Liste uniquement les fichiers en conflit
git checkout <hash-avant-suppression> -- chemin/fichier Récupère un fichier supprimé par erreur (encore dans l’historique)
git reflog Retrouve un commit “perdu” après un reset --hard
git clean -n Dry-run : montre ce qui serait supprimé par un nettoyage
git clean -fd Supprime les fichiers + dossiers non suivis (irréversible)
git gc Nettoie et optimise le dépôt
git count-objects -vH Vérifie la taille du dépôt

Pour résoudre un conflit manuellement : ouvrir les fichiers marqués <<<<<<< ======= >>>>>>>, éditer pour garder la bonne version, puis :

git add fichier-en-conflit.py
git commit

Schéma récapitulatif du workflow stable / unstable

feature/xyz ──┐
              ├─▶ unstable/development ──▶ (tests OK) ──▶ merge --no-ff ──▶ stable ──▶ tag vX.Y.Z
hotfix/xyz ───┘         ▲                                                      │
                         └──────────────── merge hotfix également ─────────────┘

Aide-mémoire express

Les 20 commandes qui couvrent 90% des besoins au quotidien :

Commande Explication
git status Où j’en suis
git add . Tout indexer
git commit -m "message" Committer
git push Envoyer
git pull Récupérer + fusionner
git log --oneline --graph --all Voir l’historique
git checkout -b nom-branche Nouvelle branche
git switch autre-branche Changer de branche
git merge autre-branche Fusionner
git branch -d nom-branche Supprimer une branche
git diff Voir les changements
git stash / git stash pop Mettre de côté / récupérer
git reset --soft HEAD~1 Annuler le dernier commit (garder les modifs)
git revert <hash> Annuler proprement un commit publié
git tag -a vX.Y.Z -m "message" Tagger une version
git remote -v Voir les remotes
git fetch Récupérer sans fusionner
git cherry-pick <hash> Reprendre un commit précis
git clone <url> Cloner un dépôt
git reflog Retrouver un commit “perdu”

Bonus : créer des templates d’issues dans GitHub

Structure de base

Le dossier ISSUE_TEMPLATE doit se trouver à l’intérieur du dossier .github. Donc tous les fichiers iront dans .github/ISSUE_TEMPLATE

GitHub propose deux systèmes :

  • Markdown classique (.md) : un simple texte pré-rempli que l’utilisateur édite librement. Facile à écrire, mais rien n’oblige personne à respecter la structure.
  • YAML forms (.yml) : un vrai formulaire avec champs typés, validations, menus déroulants. C’est le format recommandé depuis que GitHub l’a stabilisé.

Sauf contrainte particulière, préférez toujours le YAML. La contrainte imposée au moment de la saisie vaut largement l’effort de configuration initial.


Structure d’un template YML

name: Bug Report
description: Signaler un dysfonctionnement
title: "[Bug]: "
labels: ["bug", "triage"]
assignees: []
body:
  - type: markdown
    attributes:
      value: |
        Merci de prendre le temps de remplir ce formulaire.
        Avant tout, vérifiez qu'une issue similaire n'existe pas déjà.

  - type: input
    id: version
    attributes:
      label: Version concernée
      placeholder: "ex : v2.1.0"
    validations:
      required: true

  - type: dropdown
    id: environnement
    attributes:
      label: Environnement
      options:
        - Debian
        - Ubuntu
        - Fedora
        - Autre (préciser ci-dessous)
    validations:
      required: true

  - type: textarea
    id: repro
    attributes:
      label: Étapes de reproduction
      description: Le plus précisément possible, étape par étape
      placeholder: |
        1. Lancer le script avec...
        2. Observer...
    validations:
      required: true

  - type: textarea
    id: attendu
    attributes:
      label: Comportement attendu vs observé
    validations:
      required: true

  - type: textarea
    id: logs
    attributes:
      label: Logs pertinents
      render: shell
    validations:
      required: false

  - type: checkboxes
    id: checklist
    attributes:
      label: Vérifications préalables
      options:
        - label: J'ai cherché si une issue similaire existe déjà
          required: true

Quelques points utiles :

  • title pré-remplit le préfixe, ça uniformise le tri visuel dans la liste des issues.
  • labels appliqués automatiquement évitent d’y penser à chaque fois.
  • validations: required doit être réservé aux champs vraiment indispensables. Trop de champs obligatoires = abandon du formulaire.
  • render: shell (ou bash, text…) sur un textarea affiche le contenu dans un bloc de code, très utile pour des logs ou des sorties de commande.

Les templates à avoir au minimum

Bug report Version, environnement, étapes de reproduction, comportement attendu/observé, logs. C’est le template qui a le plus besoin d’être cadré, car c’est celui qu’on remplit à moitié frustré.

Feature request Quel problème ça résout, solution envisagée, alternatives déjà considérées. Ici on veut plutôt de la réflexion que des cases à cocher — du texte libre bien guidé fonctionne mieux qu’un formulaire trop rigide.

Question / Support (optionnel) Sur beaucoup de projets, mieux vaut rediriger vers les Discussions GitHub plutôt que de polluer le tracker d’issues avec des questions. Le config.yml (point suivant) permet de faire ce renvoi proprement.


Le fichier de configuration

Un fichier .github/ISSUE_TEMPLATE/config.yml complète le dispositif :

blank_issues_enabled: false
contact_links:
  - name: Question générale
    url: https://github.com/votre-repo/discussions
    about: Pour toute question qui n'est pas un bug ou une feature request
  - name: Documentation
    url: https://votre-doc.example.com
    about: Consultez d'abord la documentation

blank_issues_enabled: false est le réglage le plus sous-estimé : il désactive l’option “ouvrir une issue vierge” et force à passer par un template. Sans ça, une bonne partie des gens prendra le chemin le plus court et vos templates soigneusement conçus resteront ignorés.


Bonnes pratiques de rédaction

  • Des placeholders concrets, pas des instructions abstraites. "ex : v2.1.0" est plus utile que "indiquez la version".
  • Limitez-vous à 4-6 champs pour un bug report. Au-delà, le taux d’abandon grimpe. Si vous avez besoin de plus d’infos, envisagez un champ “environnement” unique qui regroupe OS + versions plutôt que trois champs séparés.
  • Une checkbox de pré-vérification (“j’ai cherché une issue existante”) réduit sensiblement les doublons, pour un coût de mise en place nul.
  • Pensez à l’environnement technique propre à votre projet. Sur un outil qui touche à iptables, Docker ou des services réseau, un champ dédié à la version du noyau, de Docker ou de la distribution évite des allers-retours quasi systématiques.
  • Testez le formulaire vous-même en ouvrant une fausse issue avant de le considérer terminé. On repère tout de suite les champs mal libellés ou les options de dropdown manquantes.

Le piège principal

Le sur-cadrage. Un formulaire trop long ou trop strict pousse les contributeurs occasionnels à laisser tomber, ou à remplir n’importe quoi juste pour passer l’étape. Le bon réglage, c’est le minimum de champs obligatoires qui permet de trier et reproduire un bug sans repasser par l’auteur. Tout le reste peut être optionnel ou demandé après coup en commentaire.


Entretien dans le temps

Un template n’est jamais figé. Si vous constatez que la moitié des issues laissent le champ “logs” vide, ou que tout le monde répond pareil à une question, c’est un signal pour ajuster le formulaire. Revoir ses templates tous les quelques mois, à la lumière des issues réellement reçues, est plus efficace que de vouloir tout anticiper dès le départ.