Les branches multiplient les fonctionnalités de base offertes par les commits en permettant aux utilisateurs de parcourir leur historique. Créer une nouvelle branche revient à demander un nouvel environnement de développement, avec un répertoire de travail isolé, une zone de stockage intermédiaire et l'historique du projet..
Cela vous donne la même tranquillité d'esprit que de créer une copie "sûre" de votre projet, mais vous disposez désormais de la capacité supplémentaire pour travailler sur plusieurs versions en même temps. Les branches permettent une flux de travail non linéaire-la capacité à développer des fonctionnalités non liées en parallèle. Comme nous le verrons plus tard, un flux de travail non linéaire est un précurseur important de la nature distribuée du modèle de collaboration de Git..
Contrairement à SVN ou à CVS, l'implémentation de la branche de Git est incroyablement efficace. SVN active les branches en copiant l'intégralité du projet dans un nouveau dossier, comme vous le feriez sans logiciel de contrôle de révision. Cela rend les fusions maladroites, sujettes aux erreurs et lentes. En revanche, les branches Git sont simplement un pointeur sur un commit. Comme elles fonctionnent au niveau de la validation plutôt que directement au niveau du fichier, les branches Git facilitent beaucoup la fusion des historiques divergents. Cela a un impact dramatique sur les flux de travail de branchement.
Git sépare les fonctionnalités des branches en quelques commandes différentes. le branche de git
Cette commande est utilisée pour lister, créer ou supprimer des branches.
Avant tout, vous devez pouvoir visualiser vos succursales existantes:
branche de git
Cela affichera toutes vos branches actuelles, avec un astérisque à côté de celui qui est actuellement "extrait" (plus sur cela plus tard):
* maîtriser certaines corrections rapides de bogues
le maîtriser
branch est la branche par défaut de Git, qui est créée avec le premier commit dans un référentiel. De nombreux développeurs utilisent cette branche comme l'historique "principal" du projet - une branche permanente contenant tous les changements majeurs qu'il subit..
Vous pouvez créer une nouvelle branche en transmettant son nom à la même branche de git
commander:
branche de git
Cela crée un pointeur sur le courant TÊTE
, mais fait ne pas passez à la nouvelle succursale (vous aurez besoin git checkout
pour ça). Immédiatement après avoir demandé une nouvelle branche, votre référentiel ressemblera à ce qui suit.
Votre branche actuelle (maîtriser
) et la nouvelle branche (quelque chose
) font tous deux référence au même commit, mais tout nouveau commit que vous enregistrez sera exclusif à la branche actuelle. Encore une fois, cela vous permet de travailler sur des fonctionnalités non liées en parallèle, tout en conservant des historiques sensibles. Par exemple, si votre branche actuelle était quelque chose
, votre historique ressemblerait à ce qui suit après avoir pris un instantané.
quelque chose
branche Le nouveau TÊTE
(indiqué par la validation surlignée) n'existe que dans le quelque chose
branche. Il n'apparaîtra pas dans la sortie du journal de maîtriser
, ses modifications n'apparaîtront pas non plus dans le répertoire de travail après votre extraction. maîtriser
.
Vous pouvez voir la nouvelle branche dans la base de données interne en ouvrant le fichier. .git / refs / têtes /
. Le fichier contient l'ID de la validation référencée et constitue la seule définition d'une branche Git. C’est la raison pour laquelle les branches sont si légères et faciles à gérer.
Enfin, vous pouvez supprimer des branches via le -ré
drapeau:
git branch -d
Mais le dévouement de Git à ne jamais perdre votre travail l’empêche de supprimer les branches avec des commits non fusionnés. Pour forcer la suppression, utilisez le -ré
drapeau à la place:
branche git -D
Les modifications non fusionnées seront perdues, donc Soyez très prudent avec cette commande.
Bien sûr, créer des branches est inutile sans la possibilité de basculer entre elles. Git appelle cela "vérifier" une branche:
git checkout
Après avoir extrait la branche spécifiée, votre répertoire de travail est mis à jour pour correspondre à la validation de la branche spécifiée. De plus, le TÊTE
est mis à jour pour pointer vers la nouvelle branche et tous les nouveaux commits seront stockés sur la nouvelle branche. Vous pouvez penser à extraire une branche comme basculer vers un nouveau dossier de projet, mais il sera beaucoup plus facile de récupérer les modifications dans le projet..
Dans cet esprit, c’est généralement une bonne idée d’avoir un nettoyer répertoire de travail avant de vérifier une branche. Un répertoire vierge existe lorsqu'il n'y a pas de modifications non validées. Si ce n'est pas le cas, git checkout
a le potentiel d'écraser vos modifications.
Comme pour la révision "sûre", vous êtes libre d'expérimenter une nouvelle branche sans craindre de détruire les fonctionnalités existantes. Mais vous avez maintenant une histoire dédiée à utiliser, vous pouvez donc enregistrer la progression d’une expérience en utilisant exactement la même chose. git ajouter
et git commit
commandes de plus tôt dans le livre.
Cette fonctionnalité deviendra encore plus puissante une fois que nous aurons appris à fusionner des historiques divergents dans la branche "principale" (par exemple,., maîtriser
). Nous y reviendrons dans un instant, mais d’abord, il existe un cas d’utilisation important de git checkout
cela doit être considéré…
Git vous permet également d'utiliser git checkout
avec des balises et des ID de validation, mais cela vous place dans une état HEAD détaché. Cela signifie que vous n'êtes plus sur une branche, vous visualisez directement un commit..
Vous pouvez regarder autour et ajouter de nouveaux commits comme d'habitude, mais comme aucune branche ne pointe vers les ajouts, vous perdrez tout votre travail dès que vous revenez à une vraie branche. Heureusement, créer une nouvelle succursale dans un détaché TÊTE
l'état est assez facile:
git checkout -b
Ceci est un raccourci pour branche de git
suivi par git checkout
. Après quoi, vous aurez une nouvelle référence à l’ancien détaché. TÊTE
. C'est une procédure très pratique pour retirer des expériences d'anciennes révisions.
La fusion est le processus consistant à extraire des commits d’une branche à une autre. Il existe de nombreuses façons de combiner des branches, mais l’objectif est toujours de partager des informations entre les branches. Cela fait de la fusion une des fonctionnalités les plus importantes de Git. Les deux méthodes de fusion les plus courantes sont les suivantes:
Ils utilisent tous les deux la même commande, fusionner
, mais la méthode est automatiquement déterminée en fonction de la structure de votre historique. Dans chaque cas, la branche dans laquelle vous souhaitez fusionner doit être extraite, et la branche cible restera inchangée. Les deux sections suivantes présentent deux scénarios de fusion possibles pour les commandes suivantes:
git checkout master git fusionne une fonctionnalité
Encore une fois, cela fusionne les quelque chose
branche dans le maîtriser
branche, laissant l'ancien intact. Vous exécuterez généralement ces commandes une fois que vous aurez terminé une fonctionnalité et que vous souhaitez l'intégrer au projet stable..
Le premier scénario ressemble à ceci:
Nous avons créé une branche pour développer une nouvelle fonctionnalité, ajouté deux commits, qui sont maintenant prêts à être intégrés dans la base de code principale. Au lieu de réécrire les deux commits manquants de maîtriser
, Git peut "avancer rapidement" le maîtriser
Le pointeur de la branche pour correspondre à l'emplacement de quelque chose
.
Après la fusion, le maîtriser
branch contient tout l'historique souhaité, et la branche de fonctionnalité peut être supprimée (sauf si vous souhaitez continuer à développer dessus). C'est le type de fusion le plus simple.
Bien sûr, nous aurions pu faire les deux commits directement sur le maîtriser
branche; Cependant, l'utilisation d'une branche de fonctionnalités dédiée nous a fourni un environnement sûr pour expérimenter un nouveau code. Si cela ne s'était pas bien passé, nous aurions pu simplement supprimer la branche (par opposition à la réinitialisation / la réinitialisation). Ou, si nous ajoutions un groupe de commits intermédiaires contenant du code erroné, nous pourrions le nettoyer avant de le fusionner. maîtriser
(voir Rebasing ci-dessous). Au fur et à mesure que les projets deviennent plus compliqués et attirent de plus en plus de collaborateurs, ce type de développement en branches fait de Git un outil organisationnel fantastique.
Cependant, toutes les situations ne sont pas assez simples pour permettre une validation rapide. N'oubliez pas que le principal avantage des branches est la possibilité d'explorer simultanément plusieurs axes de développement indépendants. Par conséquent, vous rencontrerez souvent un scénario ressemblant à ce qui suit:
Cela a commencé comme une fusion rapide, mais nous avons ajouté un commit à la maîtriser
branche pendant que nous développions encore quelque chose
. Par exemple, nous aurions pu arrêter de travailler sur la fonctionnalité pour corriger un bogue sensible au temps. Bien sûr, le correctif doit être ajouté au référentiel principal dès que possible, nous nous retrouvons donc dans le scénario présenté ci-dessus..
Fusion de la branche de fonctionnalité dans maîtriser
dans ce contexte, il en résulte une fusion "à 3 voies". Ceci est accompli en utilisant exactement les mêmes commandes que la fusion d'avance rapide de la section précédente.
Git ne peut pas avancer rapidement le maîtriser
pointeur vers quelque chose
sans revenir en arrière. Au lieu de cela, il génère un nouveau fusionner cela représente l'instantané combiné des deux branches. Notez que ce nouveau commit a deux parent s’engage, lui donnant accès aux deux historiques (en fait, journal git
après la fusion à 3, les émissions sont validées des deux branches).
Le nom de cet algorithme de fusion provient de la méthode interne utilisée pour créer le commit de fusion. Git regarde Trois s'engage à générer l'état final de la fusion.
Si vous essayez de combiner deux branches qui apportent des modifications différentes à la même partie de code, Git ne saura pas quelle version utiliser. Ceci s'appelle un conflit de fusion. Évidemment, cela ne peut jamais arriver lors d'une fusion à avance rapide. Lorsque Git rencontre un conflit de fusion, le message suivant s'affiche:
Fusion automatique index.html CONFLICT (contenu): Conflit de fusion dansLa fusion automatique a échoué; résoudre les conflits puis commettre le résultat.
Au lieu d’ajouter automatiquement le commit de fusion, Git s’arrête et vous demande quoi faire. Fonctionnement statut git
dans cette situation retournera quelque chose comme ce qui suit:
# Sur le maître de branche # Chemins non fusionnés: # # tous deux modifiés:
Chaque fichier en conflit est stocké dans la section "Chemins non fusionnés". Git annote ces fichiers pour vous montrer le contenu des deux versions:
<<<<<<< HEAD This content is from the current branch. ======= This is a conflicting change from another branch. >>>>>>> quelques fonctionnalités
La partie avant la =======
est de la maîtriser
branche, et le reste provient de la branche que vous essayez d'intégrer.
Pour résoudre le conflit, supprimez le <<<<<<
, =======
, et >>>>>>>
notation, et changez le code en ce que vous voulez garder. Ensuite, dites à Git que vous avez terminé de résoudre le conflit avec le git ajouter
commander:
git ajouter
C'est vrai; tout ce que vous avez à faire est d’organiser le fichier en conflit pour le marquer comme résolu. Enfin, terminez la fusion à trois en générant le commit de fusion:
git commit
Le message de journal contient une notification de fusion, ainsi qu'une liste de "conflits", ce qui peut s'avérer particulièrement utile lorsque vous essayez de déterminer où un projet a mal tourné..
Et c'est tout ce qu'il y a à fusionner dans Git. Maintenant que nous comprenons les mécanismes des branches Git, nous pouvons examiner en détail comment les utilisateurs expérimentés de Git exploitent les branches dans leur flux de travail quotidien..
Les flux de travail présentés dans cette section sont la marque du contrôle de révision basé sur Git. La nature légère et facile à fusionner de l'implémentation de branches de Git en fait l'un des outils les plus productifs de votre arsenal de développement logiciel..
Tous les workflows de branchement s’articulent autour de la branche de git
, git checkout
, et fusionner
commandes présentées précédemment dans ce chapitre.
Il est souvent utile d'attribuer une signification particulière à différentes branches dans le but d'organiser un projet. Cette section présente les types de branches les plus courants, mais gardez à l’esprit que ces distinctions sont purement superficielles: pour Git, une branche est une branche.
Toutes les branches peuvent être classées comme permanent branches ou branches de sujet. Les premiers contiennent l’histoire principale d’un projet (par exemple., maîtriser
), tandis que ces dernières sont des branches temporaires utilisées pour mettre en œuvre un programme spécifique. sujet, puis jeté (par exemple., quelque chose
).
Les branches permanentes sont la pierre angulaire de tout référentiel. Ils contiennent tous les principaux points de cheminement d'un projet logiciel. La plupart des développeurs utilisent maîtriser
exclusivement pour le code stable. Dans ces flux de travail, vous jamais commettre directement sur maîtriser
-il ne s'agit que d'une branche d'intégration pour les fonctionnalités terminées intégrées dans des branches de sujet dédiées.
De plus, de nombreux utilisateurs ajoutent une seconde couche d’abstraction dans une autre branche d’intégration (appelée classiquement développer
, si n'importe quel nom suffira). Cela libère le maîtriser
branche pour vraiment code stable (par exemple, public commit), et utilise développer
en tant que branche d’intégration interne pour préparer une version publique. Par exemple, le diagramme suivant montre plusieurs fonctionnalités en cours d’intégration dans développer
, puis une seule et dernière fusion dans maîtriser
, qui symbolise une sortie publique.
maîtriser
branche exclusivement pour les sorties publiques Les branches thématiques se répartissent généralement en deux catégories: branches caractéristiques et branches de correctif. Les branches de fonctionnalités sont des branches temporaires qui encapsulent une nouvelle fonctionnalité ou un refactor, protégeant le projet principal du code non testé. Ils proviennent généralement d'une autre branche de fonctionnalité ou d'une branche d'intégration, mais pas de la branche "super stable"..
Les branches de Hotfix sont de nature similaire, mais elles proviennent de la branche des versions publiques (par exemple,., maîtriser
). Au lieu de développer de nouvelles fonctionnalités, elles permettent de corriger rapidement la principale ligne de développement. En règle générale, cela signifie des corrections de bogues et autres mises à jour importantes qui ne peuvent attendre la prochaine version majeure..
maîtriser
avec une branche de correctif De nouveau, les significations assignées à chacune de ces branches sont purement conventionnelles. Git ne voit aucune différence entre maîtriser
, développer
, fonctionnalités et correctifs. Dans cet esprit, n’ayez pas peur de les adapter à vos propres fins. La beauté de Git est sa flexibilité. Lorsque vous comprenez la mécanique qui se cache derrière les branches Git, il est facile de concevoir de nouveaux flux de travail qui correspondent à votre projet et à votre personnalité..
Le changement de base est le processus de déplacement d’une branche vers une nouvelle base. Les capacités de rebasement de Git rendent les branches encore plus flexibles en permettant aux utilisateurs d'organiser manuellement leurs branches. Comme fusionner, git rebase
nécessite que la branche soit extraite et prend la nouvelle base comme argument:
git checkout maitresse de base rebase git
Cela déplace la totalité quelque chose
branche sur le bout de maîtriser
:
quelque chose
sur la maîtriser
branche Après la refonte, la branche de fonctionnalité est un extension linéaire de maîtriser
, ce qui est un moyen beaucoup plus simple d'intégrer les changements d'une branche à une autre. Comparez cette histoire linéaire avec une fusion de maîtriser
dans quelque chose
, ce qui donne exactement la même base de code dans l'instantané final:
maîtriser
dans quelque chose
avec une fusion à 3 Puisque l'historique a divergé, Git doit utiliser un engagement de fusion supplémentaire pour combiner les branches. Faire cela plusieurs fois au cours du développement d'une fonctionnalité longue peut entraîner une histoire très compliquée.
Ces commits de fusion supplémentaires sont superflus. Ils existent uniquement pour extraire les modifications de maîtriser
dans quelque chose
. En règle générale, vous voudrez que votre fusion s’engage à signifier quelque chose, comme l'achèvement d'une nouvelle fonctionnalité. C’est pourquoi de nombreux développeurs choisissent d’insérer des modifications avec git rebase
, car il en résulte un historique complètement linéaire dans la branche de fonctionnalité.
Le rebasage interactif va encore plus loin et vous permet de changement engage lorsque vous les déplacez vers la nouvelle base. Vous pouvez spécifier une base interactive avec le -je
drapeau:
git rebase -i maître
Ceci renseigne un éditeur de texte avec un résumé de chaque validation dans la branche de fonctionnalité, ainsi qu'une commande qui détermine Comment il devrait être transféré à la nouvelle base. Par exemple, si vous avez deux validations sur une branche, vous pouvez spécifier une base interactive comme celle-ci:
pick 58dec2a Premier commit pour une nouvelle fonctionnalité squash 6ac8a9f Second commit pour une nouvelle fonctionnalité
Le défaut choisir
commande déplace le premier commit vers la nouvelle base, tout comme la normale git rebase
, mais alors le écraser
La commande dit à Git de combiner le deuxième commit avec le précédent, vous obtenez donc un commit contenant toutes vos modifications:
quelque chose
branche Git fournit plusieurs commandes de rebasage interactives, chacune d’elles étant résumée dans la section commentaires de la liste de configuration. Le point est le rebasement interactif vous permet complètement réécrivez l'historique d'une branche en fonction de vos spécifications exactes. Cela signifie que vous pouvez ajouter autant de validations intermédiaires que nécessaire dans une branche, puis revenir en arrière et les corriger en une progression significative après coup..
D’autres développeurs penseront que vous êtes un brillant programmeur et savent exactement comment mettre en œuvre l’ensemble de la fonctionnalité en une seule fois. Ce type d’organisation est très important pour garantir que les grands projets ont une histoire navigable..
La redistribution est un outil puissant, mais vous devez être judicieux dans votre réécriture de l'histoire. Les deux types de rebasement ne font pas réellement bouge toi les commits existants créer les toutes nouvelles (indiquées par un astérisque dans le diagramme ci-dessus). Si vous inspectez les commits qui ont été soumis à une nouvelle base, vous remarquerez qu'ils ont des identifiants différents, même s'ils représentent le même contenu. Cela signifie rebaser détruit les commits existants en train de les "déplacer".
Comme vous pouvez l'imaginer, cela a des conséquences dramatiques sur les flux de travail collaboratifs. Détruire un commit public (par exemple, tout ce qui se trouve sur le maîtriser
branche) revient à déchirer la base du travail de tous les autres. Git n'aura aucune idée de la façon de combiner les modifications apportées par tout le monde, et vous aurez beaucoup d'excuses à faire. Nous examinerons plus en détail ce scénario après avoir appris à communiquer avec des référentiels distants..
Pour l'instant, il suffit de respecter la règle d'or du rebasement: ne jamais rebaser une branche qui a été poussée dans un référentiel public.
Cette leçon représente un chapitre de Git Succinctly, un eBook gratuit de l'équipe de Syncfusion.