Lorsque je travaille avec git dans une équipe utilisant des branches de fonctionnalités, j'ai souvent du mal à comprendre la structure des branches dans l'histoire.
Exemple:
Supposons qu'il y ait une fonctionnalité / préparation de branche de fonctionnalité , et la correction de bogues se poursuit sur le maître en parallèle à la branche de fonctionnalité.
L'histoire pourrait ressembler à ceci:
* merge feature/make-coffee
|\
| * small bugfix
| |
* | fix bug #1234
| |
| * add milk and sugar
| |
* | improve comments
| |
* | fix bug #9434
| |
| * make coffe (without milk or sugar)
| |
* | improve comments
|/
*
Problème
À première vue, je trouve difficile de dire de quel côté se trouve la branche de fonctionnalité. J'ai généralement besoin de parcourir plusieurs commentaires des deux côtés pour avoir une idée de qui est lequel. Cela devient plus compliqué s'il y a plusieurs branches d'entités en parallèle (en particulier si elles concernent des entités étroitement liées), ou s'il y a fusion dans les deux sens entre la branche d'entités et le maître.
En revanche, dans Subversion, c'est beaucoup plus facile car le nom de la branche fait partie de l'historique - je peux donc dire tout de suite qu'un commit a été initialement fait sur "feature / make-coffee".
Git pourrait faciliter cela en incluant le nom de la branche actuelle dans les métadonnées de validation lors de la création d'une validation (avec l'auteur, la date, etc.). Cependant, git ne fait pas cela.
Y a-t-il une raison fondamentale pour laquelle cela n'est pas fait? Ou est-ce juste que personne ne voulait la fonctionnalité? Si c'est le dernier, existe-t-il d'autres façons de comprendre le but des branches historiques sans voir le nom?
Réponses:
Probablement parce que les noms de branche n'ont de sens que dans un seul référentiel. Si je fais partie de l'
make-coffee
équipe et que je soumets toutes mes modifications via un portier, mamaster
branche peut être attirée sur lamake-coffee-gui
branche du portier , qu'il fusionnera avec samake-coffee-backend
branche, avant de rebaser sur unemake-coffee
branche qui sera fusionnée dans lamaster
branche centrale .Même au sein d'un même référentiel, les noms de branche peuvent changer et changent à mesure que votre flux de travail évolue.
master
pourrait changer plus tard pour être appelédevelopment
, par exemple.Comme CodeGnome l'a fait allusion, git a une philosophie de conception forte de ne pas incorporer quelque chose dans les données s'il n'est pas nécessaire. Les utilisateurs sont censés utiliser les options
git log
etgit diff
produire les données à leur convenance après coup. Je recommande d'en essayer jusqu'à ce que vous trouviez un format qui vous convient mieux.git log --first-parent
, par exemple, n'affichera pas les validations d'une branche en cours de fusion.la source
Suivez l'historique des succursales avec
--no-ff
Dans Git, un commit a des ancêtres, mais une "branche" n'est vraiment que la tête actuelle d'une ligne de développement. En d'autres termes, une validation est un instantané de l'arborescence de travail à un moment donné et peut appartenir à n'importe quel nombre de branches à la fois. Cela fait partie de ce qui rend la branche Git si légère par rapport aux autres DVCS.
Les validations Git ne contiennent pas les informations de branche car elles ne sont pas nécessaires pour l'historique Git. Cependant, les fusions qui ne sont pas rapides peuvent certainement contenir des informations supplémentaires sur la branche qui a été fusionnée. Vous pouvez vous assurer que votre historique contient ces informations en passant toujours le
--no-ff
drapeau à vos fusions. git-merge (1) dit:Cela créera généralement un message de fusion similaire à
Merge branch 'foo'
, donc vous pouvez généralement trouver des informations sur les "branches ancêtres" avec une ligne similaire à la suivante:la source
git log --merges
.La réponse la plus simple est que les noms des branches sont éphémères. Et si vous deviez, par exemple, renommer une branche (
git branch -m <oldname> <newname>
)? Qu'arriverait-il à tous les commits contre cette branche? Ou que se passe-t-il si deux personnes ont des succursales portant le même nom sur différents référentiels locaux?La seule chose qui a un sens dans git est la somme de contrôle du commit lui-même. Il s'agit de l'unité de base du suivi.
L'information est là, vous ne la demandez tout simplement pas, et ce n'est pas exactement là.
Git stocke la somme de contrôle du chef de chaque branche dans
.git/refs/heads
. Par exemple:(oui, je fais trembler mes sommes de contrôle git, ce n'est pas spécial, mais ce sont des référentiels privés que je regarde au moment où il n'y a pas besoin de fuite accidentelle).
En regardant cela et en retraçant chaque commit qui a ceci comme parent, ou le parent des parents ou le parent des parents ... vous pouvez découvrir dans quelles branches se trouve un commit donné. C'est juste un gros graphique à rendre.
Stocker où spécifiquement le nom d'une branche (qui peut changer comme mentionné ci-dessus) un commit est dans le commit lui-même est une surcharge supplémentaire sur le commit qui ne l'aide pas. Stockez le (s) parent (s) du commit et son bien.
Vous pouvez voir les branches en exécutant la commande git log avec l'indicateur approprié.
Il existe de nombreuses façons de choisir ce que vous voulez pour cela - consultez la documentation du journal git - le
-all
section et les quelques options qui suivent.Ce «test», «test1» et «test2» sont les branches sur lesquelles ils se sont engagés.
Notez que la documentation du journal git est énorme et qu'il est tout à fait possible d'en tirer presque tout ce que vous voulez.
la source
Pourquoi les validations git ne contiennent pas le nom de la branche sur laquelle elles ont été créées?
Juste une décision de conception. Si vous avez besoin de ces informations, vous pouvez ajouter un hook prepare-commit-msg ou commit-msg pour l'imposer sur un seul référentiel.
Après la catastrophe de BitKeeper, Linus Torvalds a développé git pour correspondre au processus de développement du noyau Linux. Là, jusqu'à ce qu'un patch soit accepté, il est révisé, édité, poli plusieurs fois (tout au long de Mail), signé (= éditer un commit), choisi par les cerises, errant vers les branches du lieutenant peut-être souvent rebasé, plus de modifications, cerise -picks et ainsi de suite jusqu'à ce qu'ils soient finalement fusionnés en amont par Linus.
Dans un tel flux de travail, il peut n'y avoir aucune origine spécifique d'une validation, et souvent une validation est juste créée dans une branche de débogage temporaire dans un référentiel aléatoire privé sans importance avec des noms de branche drôles, car git est distribué.
Peut-être que cette décision de conception est arrivée par hasard, mais elle correspond exactement au processus de développement du noyau Linux.
la source
Parce que dans Git, les commits comme "faire du café" sont considérés comme faisant partie des deux branches lorsque la branche de fonction est fusionnée. Il y a même une commande pour vérifier que:
De plus, les branches sont bon marché, locales et éthérées; ils peuvent être facilement ajoutés, supprimés, renommés, poussés et supprimés du serveur.
Git suit le principe que tout peut être fait, c'est pourquoi vous pouvez facilement supprimer une branche d'un serveur distant, et vous pouvez facilement réécrire l'historique.
Disons que j'étais dans la branche «master», et j'ai fait deux commits: «faire du café» et «ajouter du lait et du sucre», puis je décide d'utiliser une nouvelle branche pour cela, donc je remets «master» à «origine» /Maître'. Ce n'est pas un problème, toute l'histoire est toujours propre: «faire du café» et «ajouter du lait et du sucre» ne font pas partie du maître, seulement une fonction / faire du café.
Mercurial est le contraire; il ne veut pas changer les choses. Les branches sont permanentes, l'historique de réécriture est mal vu, vous ne pouvez pas simplement supprimer une branche du serveur.
En bref: Git vous permet de tout faire, Mercurial veut rendre les choses faciles (et rend vraiment difficile de vous laisser faire ce que vous voulez).
la source