DanLevy.net

Deathmatch : rebase Git vs merge

Une question intemporelle…

Hero image for Deathmatch : rebase Git vs merge

Deathmatch : Git Rebase vs. (Squash) Merge !

Dois‑je faire un rebase ? Ou un squash‑merge ?

Pourquoi ce sujet suscite‑t‑il une ferveur religieuse ?

Certains ingénieurs utilisent leur connaissance de git (et du terminal) comme un signal de leur niveau de compétence relatif. Et toute pratique liée à notre identité/ego devient impossible à analyser de façon impartiale, sans parler du changement.

D’autres facteurs, comme la familiarité et le biais de survivant, viennent souvent compliquer notre propre évaluation et nos hypothèses.

Question clé : Quel est le but d’un commit git ?

  1. Commitez‑vous tôt et souvent ? En adoptant une mentalité de « point de contrôle » ou de sauvegarde ?
    • Où tout est enregistré, même les faux départs et les expérimentations ? (par ex. git commit -am "Updated deps" && git push, répéter régulièrement)
    • Peut‑être les messages de commit sont moins importants que le code pour vous ?
  2. Ou bien vos commits sont‑ils une œuvre d’art soigneusement sélectionnée et sculptée ?
    • Peut‑être chaque commit est une unité de travail autonome et atomique ? (par ex. git add package.json && git commit -m "Updated deps")
    • Ou bien vous ne supportez tout simplement pas les journaux de commit « désordonnés » ?
    • Vos revues de PR impliquent‑elles souvent une analyse commit par commit ?

| 💡 Quels autres modèles mentaux définissent votre vision des commits ? Faites‑le moi savoir @justsml !

Pensez‑vous à git d’une manière qui apporte le plus de valeur à vous, votre équipe et votre organisation ?

Étant donné la grande diversité de mentalités autour de la stratégie de commit, il n’est pas surprenant qu’il y ait tant de confusion quant à la « bonne » façon d’utiliser git.

Scénario : Créer un tag de version révisé

Comparons le processus de création d’un tag de version en excluant certains commits récents de main.

Git Tag Releasing from main with 2 feature branches

La méthode Rebase

Modèle mental : « Je veux créer une version alternative d’un historique existant. (par ex. j’ai fait une boulette il y a 16 merges, et j’ai besoin d’un contrôle fin pour la corriger. De plus, je risque de me retrouver dans un cycle apparemment sans fin de conflits et de --continue). »

  1. Récupérez la dernière version : git checkout main && git pull
  2. Créez une nouvelle branche : git checkout -b release/hot-newness-and-stuff
  3. Lancez un rebase interactif en indiquant la référence git du point où remonter. git rebase -i HEAD~6 (Note : HEAD~6 est le raccourci git pour « il y a 6 commits »)
  4. Supprimez le(s) commit(s) souhaité(s) en changeant leur préfixe en drop. Enregistrez et fermez l’éditeur.
  5. Résolvez les conflits de fusion, git add . && git rebase --continue (NE PAS faire git commit).
  6. Répétez l’étape précédente jusqu’à la fin.
  7. Taggez/poussez en suivant le processus habituel. Exemple git tag -a v1.2.3 -m 'Release v1.2.3' && git push --tags

Avantages

Inconvénients

La méthode (Squash) Merge

Modèle mental : « Je veux un livrable personnalisé, à partir d’un point donné, en incluant les branche(s) souhaitées. »

  1. Récupérer la dernière version : git checkout main && git pull
  2. Créer une nouvelle branche : git checkout -b release/hot-newness-and-stuff
  3. Fusionner les branches et/ou commits désirés : git merge --no-ff feature/hot-newness bug/fix-123 (utilisez le drapeau --no-ff quand c’est possible.)
  4. Résoudre les conflits de fusion éventuels.
  5. Taguer/pousser selon le processus habituel. Exemple git tag -a v1.2.3 -m 'Release v1.2.3' && git push --tags

Avantages

Inconvénients

Conclusion

En fin de compte, un processus plus simple avec moins de risque doit l’emporter.

Même si les Rebasers disposent de méthodes pour résoudre (ou éviter) leurs problèmes, le fait demeure : vous finirez par devoir obtenir une ceinture noire en git fu. (par ex. même un simple git push peut devenir plus complexe : était‑ce git push --force ou git push --force-with-lease ? Pourquoi s’en occuper du tout ?)

Il y a une autre raison pour laquelle rebaser pour créer un historique révisé sera toujours désavantagé par rapport à git merge …. Un git merge permet à l’interface git d’appliquer des algorithmes avancés afin d’éviter les conflits en analysant le HEAD de chaque branche.

Cela peut être plus intelligent parce que chaque fusion ne se préoccupe que de l’état le plus récent de chaque branche ciblée, alors que le rebasage doit rejouer (ou supprimer) l’historique des commits dans l’ordre indiqué. Cela limite la capacité de git à optimiser la fusion puisqu’il ne compare que 2 commits à la fois.

En fin de compte, le rebasage vous fera parfois revivre des commits et des conflits obsolètes – même si vous savez qu’ils ont depuis été supprimés ou résolus.

Résumé