la commandegit rebase a la réputation d’être magique git voodoo que les débutants devraient éviter, mais elle peut en fait rendre la vie beaucoup plus facile pour une équipe de développement lorsqu’elle est utilisée avec soin. Dans cet article, nous allons comparer git rebase avec la commande associée git merge et identifier toutes les opportunités potentielles d’intégrer le rebasage dans le flux de travail Git typique.,

Présentation Conceptuelle

La première chose à comprendre au sujet de git rebase est qu’il résout le même problème git merge. Ces deux commandes sont conçues pour intégrer les modifications d’une branche à une autre branche—elles le font simplement de manières très différentes.

considérez ce qui se passe lorsque vous commencez à travailler sur une nouvelle fonctionnalité dans une branche dédiée, puis un autre membre de l’équipe met à jour la branchemaster avec de nouveaux commits. Il en résulte un historique fourchu, qui devrait être familier à tous ceux qui ont utilisé Git comme outil de collaboration.,

Maintenant, imaginons que la nouvelle s’engage dans master sont pertinentes à la fonction pour laquelle vous travaillez. Pour incorporer les nouveaux commits dans votre branchefeature, vous avez deux options: fusionner ou rebaser.,

L’Option de fusion

l’option la plus simple consiste à fusionner la branche master dans la branche feature en utilisant quelque chose comme ceci:

git checkout feature git merge master

ou, vous pouvez condenser cela en une seule ligne:

 git merge feature master

cela crée un nouveau « commit de fusion” dans la branche feature qui relie les historiques des deux branches, vous donnant une structure de branche qui ressemble à ceci:

la fusion est agréable car c’est une opération non destructive. Les branches existantes ne sont en aucun cas modifiées., Cela évite tous les pièges potentiels du rebasage (discutés ci-dessous).

d’autre part, cela signifie également que la branchefeature aura une validation de fusion étrangère chaque fois que vous aurez besoin d’incorporer des modifications en amont. Si master est très actif, cela peut polluer un peu l’historique de votre branche de fonctionnalités. Bien qu’il soit possible d’atténuer ce problème avec les options avancées git log, il peut être difficile pour les autres développeurs de comprendre l’historique du projet.,

Le Rebase Option

Comme une alternative à la fusion, vous pouvez rebase la balise feature branche sur master branche en utilisant les commandes suivantes:

git checkout feature git rebase master

Cela déplace l’ensemble de la feature branche pour commencer sur le bout de la balise master succursale, de manière efficace en intégrant toutes les nouvelles s’engage dans master. Mais, au lieu d’utiliser un commit de fusion, rebasing réécrit l’historique du projet en créant de nouveaux commits pour chaque commit dans la branche d’origine.,

le principal avantage du rebasage est que vous obtenez un historique de projet beaucoup plus propre. Tout d’abord, il élimine les commits de fusion inutiles requis par git merge. Deuxièmement, comme vous pouvez le voir dans le diagramme ci—dessus, le rebasage entraîne également un historique de projet parfaitement linéaire-vous pouvez suivre la pointe de feature jusqu’au début du projet sans aucune fourche. Cela rend plus facile de naviguer dans votre projet avec des commandes comme git log, git bisect et gitk.,

Mais, il y a deux compromis pour cette histoire de commit vierge: la sécurité et la traçabilité. Si vous ne suivez pas la règle d’or du rebasage, la réécriture de l’historique du projet peut être potentiellement catastrophique pour votre flux de travail de collaboration. Et, chose moins importante, le rebasage perd le contexte fourni par un commit de fusion—vous ne pouvez pas voir quand les modifications en amont ont été intégrées à la fonctionnalité.

Interactif Complet

Interactif complet vous donne la possibilité de modifier l’engage comme ils sont déplacés vers la nouvelle branche., C’est encore plus puissant qu’un rebase automatisé, car il offre un contrôle complet sur l’historique des commits de la branche. Typiquement, ceci est utilisé pour nettoyer un historique désordonné avant de fusionner une branche de fonctionnalité dans master.,

pour commencer une session de rebasage interactive, passez l’option i à la commande git rebase:

git checkout feature git rebase -i master

cela ouvrira un éditeur de texte listant tous les commits sur le point d’être déplacés:

pick 33d5b7a Message for commit #1 pick 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3

cette liste définit exactement à quoi ressemblera la branche après le rebase. En modifiant la commandepick et/ou en réorganisant les entrées, vous pouvez faire ressembler l’historique de la branche à ce que vous voulez., Par exemple, si le 2ème commit corrige un petit problème dans le 1er commit, vous pouvez les condenser en un seul commit avec la commande fixup:

pick 33d5b7a Message for commit #1 fixup 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3

lorsque vous Enregistrez et fermez le fichier, Git effectue le rebase selon vos instructions, ce qui donne un historique de projet qui ressemble à d8e38838f6″>

l’élimination de commits insignifiants comme celui-ci rend l’historique de votre fonctionnalité beaucoup plus facile à comprendre. C’est quelque chose que git merge ne peut tout simplement pas faire.,

la règle d’or du rebasage

Une fois que vous comprenez ce qu’est le rebasage, la chose la plus importante à apprendre est de ne pas le faire. La règle d’or de git rebase est de ne jamais l’utiliser sur les branches publiques.

Par exemple, de penser à ce qui pourrait arriver si vous relocalisée master dans votre feature branche:

Le rebase se déplace tous les commits dans master sur la pointe du feature. Le problème est que cela ne s’est passé dans votre référentiel., Tous les autres développeurs travaillent toujours avec l’original master. Étant donné que le rebasage entraîne de nouveaux commits, Git pensera que l’historique de votre branche master a divergé de celui de tous les autres.

la seule façon de synchroniser les deux branches master est de les fusionner ensemble, ce qui entraîne un commit de fusion supplémentaire et deux ensembles de commits contenant les mêmes modifications (celles d’origine et celles de votre branche rebasée). Inutile de dire que c’est une situation très confuse.,

donc, avant d’exécutergit rebase, demandez-vous toujours: « est-ce que quelqu’un d’autre regarde cette branche? »Si la réponse est oui, retirez vos mains du clavier et commencez à penser à un moyen non destructif d’apporter vos modifications (par exemple, la commande git revert). Sinon, vous pouvez réécrire l’histoire autant que vous le souhaitez.

forcer

Si vous essayez de renvoyer la branchemaster rebasée vers un dépôt distant, Git vous en empêchera car elle est en conflit avec la branchemaster distante., Mais, vous pouvez forcer le push à passer en passant l’indicateur--force, comme ceci:

# Be very careful with this command! git push --force

cela écrase la branche distantemaster pour correspondre à celle rebasée de votre référentiel et rend les choses très déroutantes pour le reste de Alors, soyez très prudent d’utiliser cette commande uniquement lorsque vous savez exactement ce que vous faites.

l’une des seules fois où vous devez forcer est lorsque vous avez effectué un nettoyage local après avoir poussé une branche de fonctionnalité privée vers un référentiel distant (par exemple, à des fins de sauvegarde)., C’est comme dire: « Oups, je ne voulais pas vraiment pousser cette version originale de la branche de fonctionnalités. Prenez le courant à la place. »Encore une fois, il est important que personne ne travaille sur les commits de la version originale de la branche de fonctionnalité.

procédure pas à pas du Workflow

le rebasage peut être intégré à votre workflow git existant autant ou aussi peu que votre équipe est à l’aise avec. Dans cette section, nous examinerons les avantages que le rebasage peut offrir aux différentes étapes du développement d’une fonctionnalité.,

la première étape de tout workflow qui exploite git rebase consiste à créer une branche dédiée pour chaque fonctionnalité. Cela vous donne la structure de branche nécessaire pour utiliser le rebasage en toute sécurité:

Nettoyage Local

l’une des meilleures façons d’intégrer le rebasage dans votre flux de travail est de nettoyer les fonctionnalités locales en cours. En effectuant périodiquement un rebase interactif, vous pouvez vous assurer que chaque validation de votre fonctionnalité est ciblée et significative., Cela vous permet d’écrire votre code sans vous soucier de le diviser en commits isolés—vous pouvez le réparer après coup.

lorsque vous appelezgit rebase, vous avez deux options pour la nouvelle base: la branche parent de la fonctionnalité (par exemple,master), ou un commit antérieur dans votre fonctionnalité. Nous avons vu un exemple de la première option dans la section rebasage interactif. La dernière option est agréable quand vous avez seulement besoin de corriger les derniers commits. Par exemple, la commande suivante commence un rebase interactif de seulement les 3 derniers commits.,

git checkout feature git rebase -i HEAD~3

en spécifiantHEAD~3 comme nouvelle base, vous ne déplacez pas réellement la branche—vous réécrivez simplement interactivement les 3 commits qui la suivent. Notez que cela n’intégrera pas les modifications en amont dans la branchefeature.

Si vous souhaitez réécrire l’intégralité de la fonctionnalité en utilisant cette méthode, la commandegit merge-base peut être utile pour trouver la base d’origine de la branchefeature., Ce qui suit renvoie l’ID de validation de la base d’origine, que vous pouvez ensuite passer à git rebase:

git merge-base feature master

Cette Utilisation du rebasage interactif est un excellent moyen d’introduire git rebase dans votre flux de travail, car La seule chose que les autres développeurs verront est votre produit fini, qui devrait être un historique de branche propre et facile à suivre.

Mais encore une fois, cela ne fonctionne que pour la branche privées., Si vous collaborez avec d’autres développeurs via la même branche de fonctionnalités, cette branche est publique et vous n’êtes pas autorisé à réécrire son historique.

il n’y a pas d’alternativegit merge pour nettoyer les commits locaux avec un rebase interactif.

intégration des modifications en amont dans une fonctionnalité

dans la section Aperçu conceptuel, nous avons vu comment une branche de fonctionnalité peut intégrer des modifications en amont à partir demaster en utilisant soitgit merge ougit rebase., La fusion est une option sûre qui préserve l’historique complet de votre référentiel, tandis que le rebasage crée un historique linéaire en déplaçant votre branche de fonctionnalité sur la pointe de master.

cette utilisation degit rebaseest similaire à un nettoyage local (et peut être effectuée simultanément), mais dans le processus, elle intègre les commits amont demaster.

Gardez à l’esprit qu’il est parfaitement légal de rebase sur une branche distante au lieu de master., Cela peut se produire lorsque vous collaborez sur la même fonctionnalité avec un autre développeur et que vous devez intégrer leurs modifications dans votre référentiel.,

par exemple, si vous et un autre développeur nommé John avez ajouté des commits à la branche feature, votre référentiel pourrait ressembler à ce qui suit après avoir récupéré la branche distante feature à partir du référentiel de John:

Vous pouvez résoudre ce modifications de master: soit fusionner votre feature avec john/feature, soit rebaser votre feature local sur la pointe de john/feature.,

notez que ce rebase ne viole pas la règle d’or du rebasage car seuls vos commits locauxfeature sont déplacés—tout ce qui précède est intact. C’est comme dire: « ajoutez mes changements à ce que John a déjà fait.” Dans la plupart des cas, c’est plus intuitif que de synchroniser avec la branche distante via un commit de fusion.

par défaut, la commande git pulleffectue une fusion, mais vous pouvez la forcer à intégrer la branche distante avec un rebase en lui passant l’option --rebase.,

révision D’une fonctionnalité avec une Pull Request

Si vous utilisez des pull requests dans le cadre de votre processus de révision de code, vous devez éviter d’utilisergit rebase après avoir créé la pull request. Dès que vous effectuez la pull request, d’autres développeurs examineront vos commits, ce qui signifie qu’il s’agit d’une branche publique. En réécrivant son historique, il sera impossible pour Git et vos coéquipiers de suivre les commits de suivi ajoutés à la fonctionnalité.

toute modification d’autres développeurs doit être incorporée avecgit mergeau lieu degit rebase.,

Pour cette raison, il est généralement une bonne idée de nettoyer votre code avec un rebase interactif avant de soumettre votre demande d’extraction.

intégration d’une fonctionnalité approuvée

Une fois qu’une fonctionnalité a été approuvée par votre équipe, vous avez la possibilité de rebaser la fonctionnalité sur la pointe de la branchemaster avant d’utilisergit merge pour intégrer la fonctionnalité,

c’est une situation similaire à l’intégration de modifications en amont dans une branche de fonctionnalité, mais comme vous n’êtes pas autorisé à réécrire les commits dans la branchemaster, vous devez éventuellement utilisergit merge pour intégrer la fonctionnalité. Cependant, en effectuant un rebase avant la fusion, vous êtes assuré que la fusion sera expédiée rapidement, ce qui donne un historique parfaitement linéaire. Cela vous donne également la possibilité d’écraser tous les commits de suivi ajoutés lors d’une pull request.,

Si vous n’êtes pas totalement à l’aise avec git rebase, vous pouvez toujours effectuer le rebase temporaire de la branche. De cette façon, si vous gâchez accidentellement l’historique de votre fonctionnalité, vous pouvez vérifier la branche d’origine et réessayer. Par exemple:

git checkout feature git checkout -b temporary-branch git rebase -i master # git checkout master git merge temporary-branch

résumé

et c’est tout ce que vous devez vraiment savoir pour commencer à rebaser vos branches., Si vous préférez un historique propre et linéaire exempt de commits de fusion inutiles, vous devez atteindre git rebase au lieu de git merge lors de l’intégration des modifications d’une autre branche.

en revanche, si vous souhaitez conserver l’historique complet de votre projet et éviter le risque de ré-écriture publique s’engage, vous pouvez coller avec des git merge. L’une ou l’autre option est parfaitement valide, mais au moins maintenant vous avez la possibilité de tirer parti des avantages de git rebase.