Rebase Git : tout ce que vous devez savoir
Le moyen sûr de rebaser dans Git.
Points clés à retenir
La commande Git rebase déplace une branche vers un nouvel emplacement en tête d'une autre branche. Contrairement à la commande de fusion Git, le rebase implique la réécriture de l'historique de votre projet. C'est un excellent outil, mais ne rebasez pas les commits sur lesquels d'autres développeurs ont basé leur travail.
La commande Git rebase
combine deux branches de code source en une seule. La commande Git merge
fait également cela. Nous expliquons ce que fait rebase
, comment il est utilisé et quand utiliser merge
à la place.
L'explosion de Git
Frustré par les autres systèmes de contrôle de version et leurs mises à jour et validations lentes, Linus Torvalds, célèbre pour le noyau Linux, a mis de côté un mois en 2005 pour écrire le sien. Il l'a nommé Git.
Des sites comme GitHub, GitLab et BitBucket ont fait la promotion de Git et en ont bénéficié de manière symbiotique. Aujourd'hui, Git est utilisé dans le monde entier, avec 98 % des 71 000 personnes interrogées dans une enquête de 2022 utilisant Git comme système de contrôle de version.
L'une des principales décisions de conception de Git était la vitesse. En particulier, le travail avec les succursales devait être aussi rapide que possible. Les branches sont un élément fondamental des systèmes de contrôle de version. Un référentiel de projet aura une branche principale ou principale. C'est là que se trouve la base de code du projet. Le développement, comme les nouvelles fonctionnalités, a lieu dans des branches secondaires distinctes. Cela empêche le travail effectué dans les branches de gâcher la branche principale et permet un développement simultané dans différentes parties de la base de code.
Au fur et à mesure que les développements dans les branches secondaires sont terminés, les modifications sont transférées vers la branche principale en fusionnant la branche de développement dans la branche principale. Dans d'autres versions, les systèmes de contrôle travaillant avec des branches étaient difficiles et coûteux en calcul. Travailler avec des branches dans Git est très rapide et très léger. Ce qui était autrefois un exercice fastidieux et souvent évité dans d’autres systèmes est devenu trivial dans Git.
La commande Git rebase
est un autre moyen de transférer les modifications d'une branche vers une autre branche. Les commandes merge
et rebase
ont des objectifs similaires, mais elles atteignent leurs objectifs de différentes manières et donnent des résultats légèrement différents.
Qu’est-ce que la fusion Git ?
Alors, à quoi sert la commande Git merge
? Disons que vous avez créé une branche appelée dev-branch
pour travailler sur une nouvelle fonctionnalité.
Vous effectuez quelques commits et testez votre nouvelle fonctionnalité. Tout fonctionne bien. Vous souhaitez maintenant envoyer votre nouvelle fonctionnalité à la branche master
. Vous devez être dans la branche master
pour en fusionner une autre.
Nous pouvons nous assurer que nous sommes dans la branche master
en la vérifiant explicitement avant de fusionner.
git checkout master
Nous pouvons maintenant dire à Git de fusionner la branche dev-branch
dans la branche actuelle, qui est la branche master
.
git merge dev-branch
Notre fusion
est terminée pour nous. Si vous extrayez la branche master
et que vous la compilez, elle contiendra la fonctionnalité nouvellement développée. Ce que Git a réellement réalisé est une fusion à trois. il compare les commits les plus récents dans les branches master
et dev-branch
, et le commit dans la branche master
immédiatement avant le dev -branche
a été créée. Il effectue ensuite un commit sur la branche master
.
Les fusions sont considérées comme non destructives car elles ne suppriment rien et ne modifient rien à l’historique de Git. La dev-branch
existe toujours et aucun des commits précédents n'est modifié. Un nouveau commit est créé pour capturer les résultats de la fusion à trois.
Après la fusion, notre référentiel Git ressemble à une chronologie avec une ligne alternative bifurquant puis revenant à la chronologie principale.
La branche dev-branch
a été incorporée dans la branche master
.
Si vous avez beaucoup de branches dans un projet, l'historique du projet peut devenir déroutant. C'est souvent le cas si un projet compte de nombreux contributeurs. Parce que l’effort de développement se divise en de nombreuses voies différentes, l’histoire du développement n’est pas linéaire. Démêler l'historique des validations devient encore plus difficile si les branches ont leurs propres branches.
Notez que si vous avez des modifications non validées dans la branche master
, vous devrez faire quelque chose avec ces modifications avant de pouvoir y fusionner quoi que ce soit. Vous pouvez créer une nouvelle branche et y valider les modifications, puis effectuer la fusion. Vous devrez ensuite fusionner votre branche temporaire dans la branche principale.
Cela fonctionne, mais Git a une commande qui réalise la même chose, sans avoir à créer de nouvelles branches. La commande stash
stocke pour vous vos modifications non validées et vous permet de les rappeler avec stash pop
.
Vous les utiliseriez comme ceci :
stash
git merge dev-branch
stash pop
Le résultat final est une branche fusionnée, avec vos modifications non enregistrées restaurées.
Qu’est-ce que le rebasement de Git ?
La commande Git rebase
atteint ses objectifs d'une manière complètement différente. Il prend tous les commits de la branche sur laquelle vous allez rebaser et les relit à la fin de la branche sur laquelle vous allez rebaser.
En reprenant notre exemple précédent, avant d'effectuer une action, notre référentiel Git ressemble à ceci. Nous avons une branche appelée dev-branch
et nous souhaitons déplacer ces modifications vers la branche master
.
Après le rebase
, cela ressemble à une chronologie unique et complètement linéaire des modifications.
La dev-branch
a été supprimée et les commits dans la dev-branch
ont été ajoutés à la branche principale. Le résultat final est le même que si les validations dans la branche dev-branch
avaient en fait été directement validées dans la branche master
en premier lieu. Les commits ne sont pas simplement ajoutés à la branche master
, ils sont "rejoués" et ajoutés à nouveau.
C'est pourquoi la commande rebase
est considérée comme destructrice. La branche rebasée n'existe plus en tant que branche distincte et l'historique Git de votre projet a été réécrit. Vous ne pouvez pas déterminer ultérieurement quels commits ont été initialement effectués sur la dev-branch
.
Cependant, cela vous laisse avec une histoire simplifiée et linéaire. Comparé à un référentiel avec des dizaines, voire des centaines de branches et de fusions, à la lecture du journal Git ou à l'utilisation d'une interface graphique Git pour consulter un graphique du référentiel, un référentiel rebasé est un jeu d'enfant à comprendre.
Comment rebaser sur une autre branche
Essayons un exemple de git rebase
. Nous avons un projet avec une branche appelée new-feature
. Nous rebase
cette branche sur la branche master
comme ceci.
Tout d’abord, nous vérifions que la branche master
n’a aucune modification en suspens.
git status
Nous récupérons la branche new-feature
.
git checkout new-feature
Nous disons à Git de rebase
la branche actuelle sur la branche principale.
git rebase master
Nous pouvons voir que nous avons encore deux branches.
git branch
Nous revenons à la branche master
git checkout master
Nous fusionnons la branche de nouvelle fonctionnalité dans la branche actuelle, qui dans notre cas est la branche master
.
git merge new-feature
Fait intéressant, nous avons encore deux branches après la fusion finale.
La différence est que maintenant le chef de la branche new-feature
et le chef de la branche master
sont configurés pour pointer vers le même commit, et l'historique Git ne le fait pas. montre qu'il y avait une branche new-feature
distincte, en dehors de l'étiquette de branche.
Git Rebase vs Merge : lequel devriez-vous utiliser ?
Il ne s'agit pas de rebase
ou de merge
. Ce sont deux commandes puissantes et vous les utiliserez probablement toutes les deux. Cela dit, il existe des cas d'utilisation où rebase
ne fonctionne pas vraiment bien. Les erreurs de décompression causées par des erreurs d'utilisation de merge
sont désagréables, mais les erreurs de décompression causées par rebase
sont infernales.
Si vous êtes le seul développeur à utiliser un référentiel, il y a moins de chances que vous fassiez quelque chose de désastreux avec rebase
. Vous pouvez toujours rebase
dans le mauvais sens par exemple, et rebase
votre branche principale sur votre branche new-feature
. Pour récupérer votre branche master
, vous devrez à nouveau rebase
, cette fois depuis votre branche new-feature
vers votre master
branche. Cela restaurerait votre branche master
, mais avec un historique étrange.
N'utilisez pas rebase
sur des branches partagées où d'autres sont susceptibles de travailler. Vos modifications apportées à votre référentiel vont causer des problèmes à de nombreuses personnes lorsque vous transférez votre code rebasé vers votre référentiel distant.
Si votre projet a plusieurs contributeurs, la solution la plus sûre est d'utiliser uniquement rebase
sur votre référentiel local, et non sur les branches publiques. De même, si les demandes d'extraction font partie de vos révisions de code, n'utilisez pas rebase
. Ou du moins, n'utilisez pas rebase
après avoir créé la pull request. D'autres développeurs examineront probablement vos commits, ce qui signifie que ces modifications se trouvent sur une branche publique, même si elles ne se trouvent pas sur la branche master
.
Le danger est que vous allez rebase
des commits qui ont déjà été poussés vers un référentiel distant, et que d'autres développeurs pourraient déjà avoir basé leur travail sur ces commits. Votre rebase
local fera disparaître ces commits existants. Si vous transmettez ces modifications au référentiel, vous ne serez pas populaire.
Les autres contributeurs devront passer par une fusion
compliquée pour que leur travail soit renvoyé vers le référentiel. Si vous récupérez ensuite leurs modifications dans votre référentiel local, vous êtes alors confronté à un désordre de modifications dupliquées.
Rebaser ou ne pas rebaser ?
Rebase
pourrait être interdit dans votre projet. Il peut y avoir des objections locales et culturelles. Certains projets ou organisations considèrent le rebase
comme une forme d'hérésie et un acte de profanation. Certaines personnes pensent que l’historique de Git devrait être un enregistrement inviolable et permanent de ce qui s’est passé. Ainsi, rebase
pourrait être hors de propos.
Mais, utilisé localement, sur des branches privées, rebase
est un outil utile.
Poussez après avoir rebasé et limitez-le aux branches où vous êtes le seul développeur. Ou du moins, là où tout développement s'est arrêté et où personne d'autre n'a basé aucun autre travail sur les commits de votre branche.
Faites cela et vous éviterez tout problème.
Connexe : Comment vérifier et mettre à jour votre version de Git