Workflows Git avancés
Maîtrisez les techniques Git avancées pour maintenir un historique propre, collaborer efficacement et récupérer de n'importe quelle situation en toute confiance.
Quand utiliser cette compétence
- Nettoyer l'historique des commits avant de fusionner
- Appliquer des commits spécifiques sur plusieurs branches
- Trouver les commits qui ont introduit des bugs
- Travailler sur plusieurs fonctionnalités simultanément
- Récupérer après des erreurs Git ou des commits perdus
- Gérer des workflows de branches complexes
- Préparer des pull requests propres pour la revue
- Synchroniser des branches divergées
Concepts fondamentaux
1. Interactive Rebase
Interactive rebase est le couteau suisse de l'édition d'historique Git.
Opérations courantes :
pick: Conserver le commit tel quelreword: Modifier le message du commitedit: Modifier le contenu du commitsquash: Fusionner avec le commit précédentfixup: Comme squash mais ignorer le messagedrop: Supprimer le commit entièrement
Utilisation basique :
# Rebase des 5 derniers commits
git rebase -i HEAD~5
# Rebase de tous les commits de la branche actuelle
git rebase -i $(git merge-base HEAD main)
# Rebase sur un commit spécifique
git rebase -i abc123
2. Cherry-Picking
Appliquer des commits spécifiques d'une branche à une autre sans fusionner les branches entières.
# Cherry-pick d'un seul commit
git cherry-pick abc123
# Cherry-pick d'une plage de commits (début exclusif)
git cherry-pick abc123..def456
# Cherry-pick sans committer (stage les changements seulement)
git cherry-pick -n abc123
# Cherry-pick et éditer le message du commit
git cherry-pick -e abc123
3. Git Bisect
Recherche binaire dans l'historique des commits pour trouver le commit qui a introduit un bug.
# Démarrer bisect
git bisect start
# Marquer le commit actuel comme mauvais
git bisect bad
# Marquer un commit connu comme bon
git bisect good v1.0.0
# Git checkout le commit du milieu - le tester
# Puis marquer comme bon ou mauvais
git bisect good # ou : git bisect bad
# Continuer jusqu'à trouver le bug
# Quand c'est fait
git bisect reset
Bisect automatisé :
# Utiliser un script pour tester automatiquement
git bisect start HEAD v1.0.0
git bisect run ./test.sh
# test.sh doit renvoyer 0 pour bon, 1-127 (sauf 125) pour mauvais
4. Worktrees
Travailler sur plusieurs branches simultanément sans stasher ou changer de branche.
# Lister les worktrees existants
git worktree list
# Ajouter un nouveau worktree pour une branche de feature
git worktree add ../project-feature feature/new-feature
# Ajouter un worktree et créer une nouvelle branche
git worktree add -b bugfix/urgent ../project-hotfix main
# Supprimer un worktree
git worktree remove ../project-feature
# Nettoyer les worktrees obsolètes
git worktree prune
5. Reflog
Votre filet de sécurité - suivi tous les mouvements de ref, même les commits supprimés.
# Afficher le reflog
git reflog
# Afficher le reflog d'une branche spécifique
git reflog show feature/branch
# Restaurer un commit supprimé
git reflog
# Trouver le hash du commit
git checkout abc123
git branch recovered-branch
# Restaurer une branche supprimée
git reflog
git branch deleted-branch abc123
Workflows pratiques
Workflow 1 : Nettoyer une branche de feature avant une PR
# Commencer avec la branche de feature
git checkout feature/user-auth
# Interactive rebase pour nettoyer l'historique
git rebase -i main
# Exemple d'opérations rebase :
# - Squasher les commits "fix typo"
# - Reword des messages de commit pour plus de clarté
# - Réordonner les commits logiquement
# - Supprimer les commits inutiles
# Force push de la branche nettoyée (sûr si personne d'autre ne l'utilise)
git push --force-with-lease origin feature/user-auth
Workflow 2 : Appliquer un hotfix sur plusieurs releases
# Créer le fix sur main
git checkout main
git commit -m "fix: critical security patch"
# Appliquer sur les branches de release
git checkout release/2.0
git cherry-pick abc123
git checkout release/1.9
git cherry-pick abc123
# Gérer les conflits s'ils surviennent
git cherry-pick --continue
# ou
git cherry-pick --abort
Workflow 3 : Trouver l'introduction d'un bug
# Démarrer bisect
git bisect start
git bisect bad HEAD
git bisect good v2.1.0
# Git checkout le commit du milieu - lancer les tests
npm test
# Si les tests échouent
git bisect bad
# Si les tests passent
git bisect good
# Git checkout automatiquement le commit suivant à tester
# Répéter jusqu'à trouver le bug
# Version automatisée
git bisect start HEAD v2.1.0
git bisect run npm test
Workflow 4 : Développement sur plusieurs branches
# Répertoire principal du projet
cd ~/projects/myapp
# Créer un worktree pour un bugfix urgent
git worktree add ../myapp-hotfix hotfix/critical-bug
# Travailler sur le hotfix dans un répertoire séparé
cd ../myapp-hotfix
# Faire des changements, committer
git commit -m "fix: resolve critical bug"
git push origin hotfix/critical-bug
# Revenir au travail principal sans interruption
cd ~/projects/myapp
git fetch origin
git cherry-pick hotfix/critical-bug
# Nettoyer quand c'est fait
git worktree remove ../myapp-hotfix
Workflow 5 : Récupérer après des erreurs
# Reset accidentel sur le mauvais commit
git reset --hard HEAD~5 # Oh non !
# Utiliser le reflog pour trouver les commits perdus
git reflog
# Le résultat montre :
# abc123 HEAD@{0}: reset: moving to HEAD~5
# def456 HEAD@{1}: commit: my important changes
# Récupérer les commits perdus
git reset --hard def456
# Ou créer une branche à partir du commit perdu
git branch recovery def456
Techniques avancées
Stratégie Rebase vs Merge
Quand faire un rebase :
- Nettoyer les commits locaux avant de pousser
- Tenir à jour une branche de feature avec main
- Créer un historique linéaire pour une revue plus facile
Quand fusionner :
- Intégrer les features complètes dans main
- Préserver l'historique exact de la collaboration
- Branches publiques utilisées par d'autres
# Mettre à jour la branche de feature avec les changements de main (rebase)
git checkout feature/my-feature
git fetch origin
git rebase origin/main
# Gérer les conflits
git status
# Corriger les conflits dans les fichiers
git add .
git rebase --continue
# Ou fusionner à la place
git merge origin/main
Workflow Autosquash
Squasher automatiquement les commits fixup pendant le rebase.
# Faire le commit initial
git commit -m "feat: add user authentication"
# Plus tard, corriger quelque chose dans ce commit
# Stage les changements
git commit --fixup HEAD # ou spécifier le hash du commit
# Faire plus de changements
git commit --fixup abc123
# Rebase avec autosquash
git rebase -i --autosquash main
# Git marque automatiquement les commits fixup
Split Commit
Diviser un commit en plusieurs commits logiques.
# Démarrer interactive rebase
git rebase -i HEAD~3
# Marquer le commit à diviser avec 'edit'
# Git s'arrêtera à ce commit
# Reset le commit mais garder les changements
git reset HEAD^
# Stage et committer par chunks logiques
git add file1.py
git commit -m "feat: add validation"
git add file2.py
git commit -m "feat: add error handling"
# Continuer le rebase
git rebase --continue
Partial Cherry-Pick
Cherry-pick seulement des fichiers spécifiques d'un commit.
# Afficher les fichiers dans le commit
git show --name-only abc123
# Checkout des fichiers spécifiques du commit
git checkout abc123 -- path/to/file1.py path/to/file2.py
# Stage et committer
git commit -m "cherry-pick: apply specific changes from abc123"
Bonnes pratiques
- Toujours utiliser --force-with-lease : Plus sûr que --force, empêche d'écraser le travail d'autres
- Rebase seulement les commits locaux : Ne pas faire rebase des commits qui ont été pushés et partagés
- Messages de commit descriptifs : Vous futur vous remerciera
- Commits atomiques : Chaque commit doit être un seul changement logique
- Tester avant force push : S'assurer que la réécriture d'historique n'a rien cassé
- Rester conscient du reflog : Rappelez-vous que le reflog est votre filet de sécurité pendant 90 jours
- Créer une branche avant les opérations risquées : Créer une branche de secours avant des rebases complexes
# Force push sûr
git push --force-with-lease origin feature/branch
# Créer une sauvegarde avant une opération risquée
git branch backup-branch
git rebase -i main
# Si quelque chose se passe mal
git reset --hard backup-branch
Pièges courants
- Faire rebase des branches publiques : Cause des conflits d'historique pour les collaborateurs
- Force push sans lease : Peut écraser le travail d'un coéquipier
- Perdre du travail pendant un rebase : Résoudre les conflits soigneusement, tester après le rebase
- Oublier de nettoyer les worktrees : Les worktrees orphelins consomment de l'espace disque
- Ne pas faire de sauvegarde avant une expérience : Toujours créer une branche de sécurité
- Bisect sur un répertoire de travail sale : Committer ou stasher avant de faire bisect
Commandes de récupération
# Abandonner les opérations en cours
git rebase --abort
git merge --abort
git cherry-pick --abort
git bisect reset
# Restaurer un fichier à partir d'une version spécifique d'un commit
git restore --source=abc123 path/to/file
# Annuler le dernier commit mais garder les changements
git reset --soft HEAD^
# Annuler le dernier commit et ignorer les changements
git reset --hard HEAD^
# Récupérer une branche supprimée (dans les 90 jours)
git reflog
git branch recovered-branch abc123