Éviter
les conflits
Un conflit n’est pas une erreur : c’est Git qui demande de choisir. Bien organisé, on en rencontre peu, et on les résout vite.
Mettre sa branche à jour sans abîmer l’historique, et résoudre un conflit sans perdre le travail de personne.
D’où vient un conflit
Pour fusionner deux branches, Git compare chacune à leur ancêtre commun. Une ligne modifiée d’un seul côté est reprise automatiquement. Une ligne modifiée des deux côtés produit un conflit : Git ne sait pas quelle version garder.
Plus une branche vit longtemps et touche de fichiers partagés, plus le risque augmente.
Prévenir
- Des branches courtes, qui partent du dernier
origin/develop. - Se mettre à jour chaque jour, plutôt qu’une seule fois avant la merge request.
- Des commits et des MR ciblés : moins de fichiers touchés, moins de conflits possibles.
- Un formateur commun (Prettier côté Angular, Spotless côté Java), lancé par toute l’équipe. Un reformatage massif mérite sa propre MR, annoncée à l’équipe.
- Prévenir l’équipe avant de modifier un fichier très partagé :
pom.xml,package.json, routes Angular, configuration Spring. - Des migrations de base horodatées (Flyway, Liquibase) plutôt que numérotées à la suite, pour éviter que deux branches créent la même version.
- Un
.gitattributesqui fixe les fins de ligne (voir Configuration du poste) : sinon, des fichiers entiers apparaissent modifiés.
Se mettre à jour correctement
La procédure de référence, sur sa branche de travail :
git switch feature/CMA-142-export-ordonnances
git fetch origin
git rebase --autostash origin/develop
# en cas de conflit : résoudre, git add, git rebase --continue
./mvnw verify # ou npm test : retester AVANT de pousser
git push --force-with-lease
:::warning Rebaser sur origin/develop, pas sur develop
git fetch met à jour origin/develop, pas votre branche locale develop. Un git rebase develop après un simple fetch rebase sur une base périmée, et les conflits réapparaissent dans la merge request.
:::
--autostashmet de côté le travail non commité puis le restaure, sansgit stashmanuel.--force-with-leaseest nécessaire parce que le rebase a créé de nouveaux commits. Il refuse d’écraser un travail poussé entre-temps par quelqu’un d’autre.
Si la branche est partagée par plusieurs développeurs, ne la rebasez pas : fusionnez la cible dedans, ce qui ne réécrit rien.
git fetch origin
git merge origin/develop
:::danger Ne jamais pousser --force sur une branche commune
Sur develop, recette, main, preprod ou prod, un force push efface le travail des autres et désynchronise ArgoCD. Ces branches sont protégées pour l’empêcher.
:::
Résoudre un conflit pas à pas
1. Identifier les fichiers en conflit
git status
# both modified: src/app/vente/vente.service.ts
2. Lire les marqueurs. Avec merge.conflictStyle zdiff3, Git affiche aussi la version de l’ancêtre commun, ce qui aide à comprendre ce que chaque côté a voulu faire :
<<<<<<< HEAD
const total = arrondir(sousTotal * (1 + tva), 0);
||||||| ancêtre commun
const total = sousTotal * (1 + tva);
=======
const total = sousTotal * (1 + tva) - remise;
>>>>>>> fix(vente): appliquer la remise fidélité
3. Écrire la bonne version, qui combine souvent les deux intentions, puis supprimer les marqueurs :
const total = arrondir(sousTotal * (1 + tva) - remise, 0);
4. Marquer le fichier comme résolu et continuer
git add src/app/vente/vente.service.ts
git rebase --continue # ou git merge --continue
5. Retester. Un code qui a fusionné sans conflit textuel peut quand même ne plus compiler ou ne plus fonctionner.
Les éditeurs d’IntelliJ IDEA et de VS Code proposent une vue à trois colonnes très pratique, accessible aussi par git mergetool.
:::warning --ours et --theirs s’inversent pendant un rebase
Pendant un merge, --ours désigne votre branche. Pendant un rebase, c’est l’inverse : --ours désigne la branche sur laquelle vous rejouez vos commits (origin/develop) et --theirs vos propres commits.
:::
Cas particuliers
| Fichier | Résolution |
|---|---|
package-lock.json | Reprendre la version de la cible, puis npm install pour réintégrer vos dépendances |
| Migration de base en double | Renommer votre migration avec un horodatage postérieur, ne jamais modifier une migration déjà appliquée |
| Fichier généré | Régénérer à partir de la source, ne pas l’éditer à la main |
| Conflit répété à chaque rebase | Activer rerere : Git rejoue automatiquement la résolution déjà faite |
Abandonner ou annuler
Rien n’est perdu tant qu’on ne panique pas :
git rebase --abort # annule le rebase en cours, retour à l'état de départ
git merge --abort # annule le merge en cours
git reset --merge ORIG_HEAD # annule un git pull (merge) terminé par erreur
Pour retrouver un travail après une fausse manœuvre, voir la section Récupérer un travail « perdu » de Git avancé.