Résolution des historiques divergés : Stratégies Git Merge vs Rebase

Comparez git merge et git rebase pour les branches divergées, la gestion des conflits, l'historique partagé et le choix d'un workflow sûr en équipe.

Résolution des historiques divergés : Stratégies Git Merge vs Rebase

Git merge et rebase aident tous deux lorsque votre branche a divergé d'une autre branche. La différence réside dans la manière dont ils préservent l'historique, et choisir le mauvais peut rendre la collaboration plus difficile qu'elle ne devrait l'être.

Vous n'avez pas besoin d'un historique parfait pour chaque modification. Vous avez besoin d'une stratégie que votre équipe comprend et qui maintient la stabilité des branches partagées.

Ce que signifie un historique divergé

Un historique divergé se produit lorsque deux branches ont des commits différents après un point de départ commun. Par exemple, vous avez créé feature/log-cleanup à partir de main lundi. Mardi, quelqu'un a fusionné un correctif de sécurité dans main. Maintenant, votre branche et main ont chacune des commits que l'autre n'a pas.

Vous pouvez le voir avec :

git log --oneline --graph --decorate --all

Vous pouvez également voir Git vous dire que votre branche et la branche distante ont divergé. Cela signifie que les deux côtés ont des commits uniques. Git a besoin que vous décidiez comment les combiner.

Les deux outils normaux sont merge et rebase :

git merge main

ou :

git rebase main

Les deux peuvent produire le même contenu final de fichier. L'historique sera différent.

Comment fonctionne Git Merge

Merge combine les historiques sans réécrire les commits existants. Si votre branche et main ont toutes deux avancé, Git crée un commit de fusion qui relie les deux lignes de travail.

Un flux typique ressemble à ceci :

git switch feature/log-cleanup
git fetch origin
git merge origin/main

S'il n'y a pas de conflits, Git crée un commit de fusion ou avance rapidement lorsque c'est possible. S'il y a des conflits, Git s'arrête et vous demande de les résoudre.

Merge est bon lorsque vous souhaitez préserver la forme réelle de la collaboration. Il montre que le travail s'est déroulé en parallèle et a été combiné plus tard. Cela peut être utile pour les branches de longue durée, les branches de version et les branches de fonctionnalités partagées.

L'inconvénient est que les fusions fréquentes peuvent ajouter du bruit. Une branche avec de nombreux commits "merge main into feature" peut être plus difficile à parcourir. Cela ne signifie pas que c'est faux, mais cela peut rendre l'historique moins ordonné.

Utilisez merge lorsque :

  • La branche est partagée avec d'autres développeurs.
  • Vous voulez éviter de réécrire l'historique des commits.
  • Votre équipe valorise un enregistrement exact des points d'intégration.
  • Vous mettez à jour une branche de version ou une branche protégée.

Pour une branche déjà poussée et utilisée par d'autres, merge est généralement le choix par défaut le plus sûr.

Comment fonctionne Git Rebase

Rebase déplace vos commits de branche pour qu'ils apparaissent au-dessus d'un nouveau commit de base. Au lieu de montrer deux lignes divergées reliées par un commit de fusion, l'historique de la branche devient linéaire.

Un flux typique ressemble à ceci :

git switch feature/log-cleanup
git fetch origin
git rebase origin/main

Git rejoue vos commits un par un au-dessus du dernier main. Si un conflit apparaît, Git s'arrête au commit qui ne peut pas être rejoué. Après avoir résolu le conflit, continuez avec :

git add <fichiers-corrigés>
git rebase --continue

Si le rebase devient confus, vous pouvez revenir en arrière :

git rebase --abort

Rebase est utile pour les branches locales et privées car il garde l'historique facile à lire. Les relecteurs peuvent voir vos commits comme s'ils avaient été construits sur le dernier main depuis le début.

Utilisez rebase lorsque :

  • La branche est la vôtre et n'est pas partagée.
  • Vous voulez un historique de commits propre et linéaire.
  • Vous préparez une branche avant d'ouvrir une pull request.
  • Votre équipe préfère explicitement les branches de fonctionnalités rebasées.

La règle principale est simple : ne rebasez pas les commits publics à moins que votre équipe ne s'y attende. Rebase réécrit les hachages de commits. Si quelqu'un d'autre a basé son travail sur vos anciens commits, votre réécriture peut créer de la confusion pour eux.

Pour plus d'outils d'historique Git quotidiens, voir explorer l'historique du projet.

Gestion des conflits lors d'un merge ou d'un rebase

Les conflits surviennent lorsque Git ne peut pas combiner automatiquement les modifications. Ils sont courants dans les fichiers très sollicités tels que les manifestes de déploiement, les fichiers de verrouillage des dépendances et les fichiers de configuration partagés.

Commencez par vérifier le statut :

git status

Ouvrez les fichiers en conflit et recherchez les marqueurs de conflit :

<<<<<<< HEAD
version de la branche actuelle
=======
version entrante
>>>>>>> nom-de-la-branche

Votre travail consiste à remplacer le bloc marqué par le contenu final que vous souhaitez réellement. Ne conservez pas les marqueurs.

Après modification, indexez le fichier :

git add chemin/vers/fichier

Pour un merge, terminez par :

git commit

Pour un rebase, continuez avec :

git rebase --continue

Exécutez des tests ou au moins la commande de validation pertinente après avoir résolu les conflits. Un fichier peut être syntaxiquement correct mais logiquement erroné. Par exemple, deux modifications YAML Kubernetes peuvent fusionner sans conflit tout en définissant des ports en double ou des étiquettes incompatibles.

Choisir une stratégie d'équipe

La meilleure stratégie est celle qui crée un historique prévisible pour votre projet. De nombreuses équipes utilisent rebase pour les branches de fonctionnalités privées et les commits de fusion pour les pull requests. D'autres regroupent tout le travail d'une fonctionnalité en un seul commit. Certaines équipes d'infrastructure préfèrent les commits de fusion car ils montrent exactement quand les branches ont été intégrées.

Choisissez une règle et documentez-la. Une politique simple pourrait être :

  • Rebasez votre propre branche de fonctionnalité avant la relecture.
  • Ne rebasez jamais main, les branches de version ou les branches partagées.
  • Utilisez les commits de fusion pour les pull requests approuvées.
  • Utilisez squash merge pour les petites corrections à but unique.

Cela évite les débats sur le style Git lors de travaux urgents. Cela facilite également l'automatisation car l'IC, les notes de version et les outils de déploiement peuvent compter sur un historique cohérent.

Quand demander de l'aide

Demandez avant de forcer un push après un rebase sur une branche que d'autres pourraient utiliser. Demandez également lorsqu'un conflit touche les paramètres de sécurité, les migrations de base de données, les fichiers de déploiement de production ou les fichiers de verrouillage générés que vous ne comprenez pas.

Si un merge ou un rebase devient emmêlé, arrêtez-vous et inspectez l'état avec git status. Vous pouvez généralement annuler et revenir à l'état précédent avec git merge --abort ou git rebase --abort. C'est mieux que d'essayer des commandes aléatoires jusqu'à ce que l'arbre de travail semble propre.

Merge et rebase résolvent le même problème général, mais ils racontent des histoires différentes. Merge préserve la façon dont le travail s'est réuni. Rebase crée une ligne de commits plus propre. Utilisez chacun là où il convient, et votre historique Git restera utile au lieu de devenir une source de risque.