git merge
Réunir deux historiques de développement ou plus
La commande 'git merge' intègre dans la branche courante les modifications des commits nommés (depuis le moment où leurs historiques ont divergé de la branche courante). Git fait une fusion « fast-forward » quand c’est possible (quand la branche courante est un ancêtre de la branche fusionnée), ou crée un « commit de fusion » quand les historiques ont divergé. En cas de conflits entre les branches, Git s’arrête et vous demande de les résoudre avant de terminer la fusion.
Synopsis
git merge [--no-ff | --ff-only] [--squash] [--no-commit] [-m <msg>] [--allow-unrelated-histories] [<commit>...]
git merge (--continue | --abort | --quit)Options
Choisir la bonne option
Stratégies de fusion
Comment contrôler le type de fusion que fait Git
| Commande | Crée un commit de fusion | Préserve l’historique | Idéal pour |
|---|---|---|---|
git merge (default) | En cas de divergence | Oui | Intégration normale d’une fonctionnalité |
git merge --no-ff | Toujours | Oui | Documenter les fusions de fonctionnalités |
git merge --ff-only | Jamais | Linéaire seulement | Imposer un historique propre |
git merge --squash | Non (commit normal) | Non (aplati) | Branche main propre |
Gérer les conflits
Que faire quand une fusion a des conflits
| Commande | Action | Garde le travail | Quand l’utiliser |
|---|---|---|---|
(resolve manually) | Modifier les fichiers, git add | Oui | Besoin de parties des deux côtés |
--continue | Terminer la fusion | Oui | Après avoir résolu les conflits |
--abort | Annuler la fusion | État d’avant la fusion | Pas prêt à résoudre maintenant |
checkout --ours/--theirs | Choisir un côté | Une seule version | Un côté est clairement le bon |
merge ou rebase
Deux façons d’intégrer des modifications - des compromis différents
| Commande | Historique | Résolution des conflits | Idéal pour |
|---|---|---|---|
git merge | Préserve tous les commits | Une fois | Branches partagées, PR |
git rebase | Réécrit en linéaire | Par commit | Nettoyage local, branches privées |
git merge --squash | Un seul commit | Une fois | Fonctionnalité à l’historique désordonné |
Contrôler le commit
Options pour personnaliser le commit de fusion
| Commande | Committe automatiquement | Cas d’usage |
|---|---|---|
git merge feature | Oui (sans conflit) | Fusion standard |
git merge --no-commit | Non (indexé) | Relire avant le commit |
git merge -m "msg" | Oui (ignoré en fast-forward) | Commits de fusion descriptifs |
git merge --squash | Non (commit obligatoire) | Regrouper tous les commits en un seul |
Exemples de workflows
git checkout mainPasser sur la branche main
git pull origin mainRécupérer les dernières modifications du dépôt distant
git merge --no-ff feature-branchFusionner la fonctionnalité avec un commit de fusion pour l’historique
git push origin mainPousser les modifications fusionnées vers le dépôt distant
git branch -d feature-branchSupprimer la branche de fonctionnalité fusionnée
git merge featureTenter la fusion (des conflits apparaissent)
git statusVoir quels fichiers sont en conflit
(edit conflicted files)Chercher les marqueurs <<<<<<< et résoudre à la main
git add <resolved-files>Indexer les fichiers résolus
git merge --continueTerminer la fusion avec un commit
git checkout mainPasser sur la branche main
git merge --squash feature-branchRegrouper tous les commits en modifications indexées
git commit -m "Add feature X"Créer un seul commit propre avec toutes les modifications
git branch -D feature-branchForcer la suppression de la branche de fonctionnalité
git merge featureLancer la fusion (des problèmes surviennent)
git statusVoir l’état en conflit
git merge --abortAnnuler et revenir à l’état d’avant la fusion
git statusVérifier que vous êtes revenu à un état propre
Dépannage
CONFLICT (content): Merge conflict in file.js
Cause : Les deux branches ont modifié les mêmes lignes du fichier
Ouvrez le fichier, cherchez les marqueurs <<<<<<<, corrigez, puis git add et git merge --continue
fatal: refusing to merge unrelated histories
Cause : Les branches n’ont aucun ancêtre commun (dépôts séparés)
Utilisez git merge --allow-unrelated-histories si vous voulez vraiment réunir des projets séparés
Already up to date
Cause : La branche que vous fusionnez est déjà incluse dans votre branche courante
Rien à faire - votre branche contient déjà tous les commits de la cible
error: Your local changes to the following files would be overwritten by merge
Cause : Vous avez des modifications non committées qui entrent en conflit avec la fusion
Committez vos modifications, mettez-les dans le stash (git stash), ou jetez-les avant de fusionner
La fusion est faite mais je voulais d’abord relire
Cause : Git a committé la fusion automatiquement
La prochaine fois, utilisez --no-ff --no-commit. Pour recommencer : git reset --merge ORIG_HEAD, puis refaites la fusion avec --no-commit
Astuces et pièges
Bonnes pratiques
- ✓Faites toujours un pull des dernières modifications avant de fusionner pour limiter les conflits
- ✓Utilisez --no-ff pour les branches de fonctionnalité afin de garder le contexte de la fusion dans l’historique
- ✓Écrivez des messages de fusion descriptifs qui expliquent ce qui a été intégré
- ✓Supprimez les branches de fonctionnalité après la fusion pour garder le dépôt propre
- ✓Testez votre code après la fusion et avant de pousser, pour vérifier que rien n’est cassé
- ✓Utilisez git merge --abort si vous n’êtes pas prêt à résoudre les conflits - ne laissez pas une fusion à moitié faite
- ✓Pour les branches de longue durée, fusionnez régulièrement main dans votre branche de fonctionnalité pour réduire les conflits de la fusion finale
Erreurs fréquentes
- ✗Fusionner sans avoir d’abord récupéré les dernières modifications du dépôt distant. Faites toujours 'git pull' avant de fusionner pour éviter les conflits.
- ✗Indexer des fichiers qui contiennent encore des marqueurs de conflit. Git bloque les commits tant que des chemins ne sont pas fusionnés, mais dès que vous faites 'git add' sur un fichier, il committe les marqueurs <<<<<<< tels quels.
- ✗Utiliser des fusions fast-forward pour les branches de fonctionnalité fait perdre l’historique de la branche. Utilisez '--no-ff' pour garder le contexte.
- ✗Lancer 'git merge --abort' après avoir résolu les conflits à la main fait perdre tout ce travail de résolution.
- ✗Fusionner dans la mauvaise branche. Vérifiez toujours avec 'git branch' que vous êtes sur la bonne branche cible avant de fusionner.
FAQ
Merge préserve l’historique et crée un commit de fusion. Rebase réécrit l’historique pour le rendre linéaire. Utilisez merge pour les branches partagées, rebase pour le nettoyage local.
Utilisez --no-ff pour fusionner les branches de fonctionnalité dans main. Il crée un commit de fusion qui date l’intégration de la fonctionnalité, même si un fast-forward était possible.
Si elle n’est pas poussée : git reset --hard ORIG_HEAD (fonctionne aussi pour les fast-forwards ; jette les modifications non committées). Si elle est poussée : git revert -m 1 <merge-commit> pour créer un nouveau commit qui annule la fusion.
Un fast-forward a lieu quand votre branche n’a aucun nouveau commit depuis le point de bifurcation. Git avance simplement le pointeur au lieu de créer un commit de fusion.
Ouvrez les fichiers en conflit, cherchez les marqueurs <<<<<<<, gardez le code voulu, retirez les marqueurs, puis faites git add sur les fichiers et git merge --continue.
Une fusion normale préserve tout l’historique des commits. Une fusion squash regroupe tout en un seul commit. Utilisez squash quand la branche de fonctionnalité a des commits WIP désordonnés que vous ne voulez pas dans main.