it-swarm.dev

Quand un commit de contrôle de version est-il trop volumineux?

J'ai entendu à plusieurs endroits "Ne faites pas de gros commits" mais je n'ai jamais vraiment compris ce qu'est un "grand" commit. Est-il volumineux si vous travaillez sur un tas de fichiers même s'ils y sont liés? Sur combien de parties d'un projet devriez-vous travailler en même temps?

Pour moi, j'ai du mal à essayer de faire de "petits commits" car j'oublie ou crée quelque chose qui crée autre chose qui crée autre chose. Vous vous retrouvez alors avec des trucs comme ça:

 Création d'une file d'attente sortante personnalisée 
 
 Bot 
 - Nouveau champ msgQueue qui n'est rien de plus qu'un SingleThreadExecutor 
 - sendMsg bloque jusqu'à l'envoi du message, et ajoute une attente entre l'envoi des messages 
 
 - Appels adminExist mis à jour (voir contrôleur) 
 - Suppression des appels à sendMessage 
 
 Contrôleur 
 -Nouveau champ msgWait indique le temps d'attente entre les messages 
 - Démarrage des plugins de service déplacé vers reloadPlugins 
 - adminExists déplacé du serveur en raison d'administrateurs globaux. Vérifications au niveau du canal, du serveur 
 Et du niveau global 
 
 Admin 
 - Nouvelles méthodes getServer et getChannel qui obtiennent l'objet approprié Admin 
 Appartient à 
 
 BotEvent 
 - toString () affiche également extra et extra1 
 
 Canal 
 - champ de canal renommé en nom 
 - Correction d'une faute de frappe dans le canal (int) 
 
 Serveur 
 - Déplacement d'adminExists vers le contrôleur 
 
 PluginExecutor 
 - Tests mineurs ajoutés, seront supprimés plus tard 
 
 Plugins JS 
 - Mis à jour pour les changements de framework 
 - Remplacé InstanceTracker.getController () par Controller.instance 
 - VLC parle maintenant dans son propre fichier 
 
 Divers NB mises à jour et modifications du projet 
 
 --- 
 
 Fichiers concernés 
 Modifier /trunk/Quackbot-Core/dist/Quackbot-Core.jar[.____.[Modify /trunk/Quackbot-Core/dist/README.TXT[.____.ramedModify /trunk/Quackbot-Core/nbproject/private/private.properties▶. ____________________ Modified/trunk/Quackbot-Core/nbproject/p rivate/private.xml 
 Modifier /trunk/Quackbot-Core/src/Quackbot/Bot.Java[.____.[Modify /trunk/Quackbot-Core/src/Quackbot/Controller.Java
 Modify /trunk/Quackbot-Core/src/Quackbot/PluginExecutor.Java[.____.[Modify /trunk/Quackbot-Core/src/Quackbot/info/Admin.Java[.____. E5EModify/trunk/Quackbot-Core/src/Quackbot/info/BotEvent.Java 
 Modifier /trunk/Quackbot-Core/src/Quackbot/info/Channel.Java[.____.[Modify/trunk/Quackbot-Core/src/Quackbot/info/Server.Java 
 Modify /trunk/Quackbot-GUI/dist/Quackbot-GUI.jar[.____.[Modify /trunk/Quackbot-GUI/dist/README.TXT[.____. E5EModify/trunk/Quackbot-GUI/dist/lib/Quackbot-Core.jar 
 Modifier /trunk/Quackbot-GUI/nbproject/private/private.properties[.____.[Modify/trunk/Quackbot-GUI/nbproject/private/private.xml 
 Modify /trunk/Quackbot-GUI/src/Quackbot/GUI.Java[.____.[Modify /trunk/Quackbot-GUI/src/Quackbot/log/ControlAppender.Java
 Supprimer /trunk/Quackbot-GUI/src/Quackbot/log/WriteOutput.Java[.____.[Modify/t runk/Quackbot-Impl/dist/Quackbot-Impl.jar 
 Modifier /trunk/Quackbot-Impl/dist/README.TXT[.____. diplomatiqueModify/trunk/Quackbot-Impl/dist/lib/Quackbot- Core.jar 
 Modify /trunk/Quackbot-Impl/dist/lib/Quackbot-GUI.jar[.____.[Modify /trunk/Quackbot-Impl/dist/lib/Quackbot-Plugins.jar
 Modifiez /trunk/Quackbot-Impl/lib/javarebel.stats[.____.▶ Ajouter /trunk/Quackbot-Impl/lib/jrebel.info[.____.[Modify/trunk/Quackbot-Impl/nbproject/private/private.properties 
 Modify /trunk/Quackbot-Impl/nbproject/private/private.xml[.____.[Modify /trunk/Quackbot-Impl/nbproject/project.properties[.____. diplomatiqueModify/trunk/Quackbot-Impl/plugins/CMDs/Admin/reload.js 
 Add /trunk/Quackbot-Impl/plugins/CMDs/Operator/hostBan[.____.[Modify/trunk/Quackbot-Impl/plugins/CMDs/Operator/mute.js 
 Modify /trunk/Quackbot-Impl/plugins/CMDs/lyokofreak/curPlaying.js[.____.▶Modify /trunk/Quackbot-Impl/plugins/CMDs/lyokofreak/lfautomode.js 
 Modifier /trunk/Quackbot-Impl/plugins/listeners/onJoin.js[._ ___.] Modify /trunk/Quackbot-Impl/plugins/listeners/onQuit.js[.____.[Modify /trunk/Quackbot-Impl/plugins/testCase.js[.____. E5EAdd/trunk/Quackbot-Impl/plugins /utils/whatsPlaying.js[.____.[Modify /trunk/Quackbot-Impl/src/Quackbot/impl/SandBox.Java[.____.[Add /trunk/Quackbot-Impl/vlc_http[.____.iminalAdd/trunk /Quackbot-Impl/vlc_http/current.html[.____.[Modify /trunk/Quackbot-Plugins/dist/Quackbot-Plugins.jar[.____. E5EModify /trunk/Quackbot-Plugins/dist/README.TXT 
 Modifiez /trunk/Quackbot-Plugins/dist/lib/Quackbot-Core.jar. _______________________Modify /trunk/Quackbot-Plugins/nbproject/private/private.properties[.____. -Plugins/nbproject/private/private.xml 
 Modifiez /trunk/Quackbot-Plugins/src/Quackbot/plugins/JSPlugin.Java
 Ajoutez /trunk/global-lib/jrebel.jar

Oui....

Donc pour les questions:

  • Quels sont les facteurs pour lesquels un commit devient trop volumineux (choses non évidentes)?
  • Comment pouvez-vous empêcher de tels commits? Veuillez donner des détails
  • Qu'en est-il lorsque vous êtes à un stade de développement semi-précoce lorsque les choses évoluent rapidement? Les énormes commits sont-ils toujours corrects?
67
TheLQ

Pour moi, j'ai du mal à essayer de faire de "petits commits" car j'oublie ou crée quelque chose qui crée autre chose qui crée autre chose.

C'est un problème. Il semble que vous deviez apprendre pour diviser votre travail en morceaux plus petits et plus faciles à gérer.

Le problème avec les grands commits est:

  • Dans un projet à plusieurs personnes, les chances que vos validations provoquent des conflits pour les autres développeurs sont plus grandes.
  • Il est plus difficile de décrire avec précision ce qui a été fait dans les messages de journal.
  • Il est plus difficile de suivre l'ordre dans lequel les modifications ont été apportées et donc de comprendre la cause des problèmes.
  • Cela augmente la probabilité de perdre beaucoup de travail non engagé.

Parfois, de grands commits sont inévitables; par exemple. si vous devez changer une API majeure. Mais ce n'est normalement pas le cas. Et si vous vous trouvez dans cette situation, c'est probablement une bonne idée de créer une branche et de faire votre travail là-bas ... avec beaucoup de petits commits ... et de vous réintégrer lorsque vous avez terminé.

(Un autre cas est lorsque vous effectuez une importation initiale, mais ce n'est PAS problématique du point de vue des problèmes répertoriés ci-dessus.)

68
Stephen C

Le principe de responsabilité unique.

Chaque validation de contrôle de source ne doit servir qu’un seul objectif. Si vous devez mettre le mot "et" ou "aussi" dans votre résumé, vous devez le diviser.

Il est très courant de se retrouver avec de nombreuses modifications distinctes non liées ou semi-liées dans votre copie de travail. C'est ce qu'on appelle le "problème de copie de travail enchevêtrée", et il est en fait très difficile à éviter même pour les développeurs disciplinés. Cependant, Git et Mercurial vous donnent tous deux des outils pour le résoudre - git add -p ou sélection de morceaux et files d'attente Mercurial dans TortoiseHg respectivement.

40
jammycakes

Imaginez que le client a demandé qu'une modification particulière soit apportée - par exemple pour ajouter une règle selon laquelle quelque chose ou une autre ne peut pas être fait dans les deux jours suivant la date "quelle que soit". Ensuite, après avoir fait le changement, ils changent d'avis. Vous souhaiterez annuler votre validation. Si tout est plein de choses sur la modification de l'ordre de tri des rapports non liés, votre vie est une misère.

Un élément de travail, un ensemble de modifications. Une demande du client, un changeset. Une chose sur laquelle vous pourriez changer d'avis, un ensemble de modifications. Parfois, cela signifie qu'il s'agit d'une seule ligne de code. Parfois, il s'agit de dix fichiers différents, y compris le schéma de la base de données. C'est très bien.

26
Kate Gregory

Les gros commits sont quand vous avez des tonnes de changements qui ne vont pas tous dans le même seau. Si je change la logique du contrôleur, puis le modèle de connexion à la base de données, puis certains misc. scripts, je ne devrais pas regrouper le tout sous un seul commit.

La prévention consiste à effectuer des validations en fonction de ce que vous effectuez. Dans l'exemple ci-dessus, je m'engagerais après la logique du contrôleur, après le travail de la base de données et après les scripts. Ne tardez pas à vous engager simplement parce que vous savez ce qui a changé. D'autres personnes reviendront sur votre "Changed stuff" message de validation du journal et se demandent ce que vous fumiez.

Les importations initiales sont probablement les engagements les plus importants que vous devriez avoir. Configurer un système à partir de zéro? Bien sûr, avez quelques gros commits. Après l'avoir nivelé, il est temps de garder les choses organisées.

10
Josh K

Si vous savez que vous allez travailler sur un gros morceau de code à l'avance, je vous suggère de créer une branche pour votre fonctionnalité spécifique tout en tirant régulièrement le code de la ligne principale pour vous assurer que votre code reste synchronisé. Lorsque vous avez terminé de travailler sur la branche, fusionnez toutes vos modifications dans la ligne principale. De cette façon, les autres membres de l'équipe ne seront pas surpris et/ou ennuyés lorsqu'ils verront un énorme engagement. De plus, il y a beaucoup moins de chances de casser des choses. Continuez à pratiquer pour diviser les choses en petits commits. Avec le temps, cela deviendra une seconde nature.

7
ysolik

Cet exemple montre une validation trop grande.

En règle générale, décrivez le changement dans une phrase ou une ligne de texte. (Sur la base de cette règle, la validation doit être divisée en 10 à 15 plus petites.) Si vous ne pouvez pas commenter correctement une validation sur une seule ligne, elle est déjà trop volumineuse.

Pour pratiquer des commits plus petits, prenez des notes dans votre bloc-notes (ou dans le bloc-notes) de ce que vous avez déjà modifié ou ajouté. Validez-le avant qu'il ne devienne une longue liste ou avant d'apporter une modification de code sans rapport avec ce que vous avez déjà dans le bloc-notes.

7
azheglov

Dans mon domaine (modélisation physique), je découvre aujourd'hui un bug dans la sortie qui n'était pas dans le référentiel il y a 6 mois. Lorsque cela se produit, je ferai une recherche binaire sur les révisions:

  1. Exécuter le modèle depuis 3 mois
  2. Si le bogue est toujours en sortie, exécutez le modèle depuis 4,5 mois
  3. ... répétez jusqu'à ce que je trouve le commit qui donne une mauvaise sortie

Lorsque le bug a été introduit dans un commit monstrueux, je dois m'asseoir avec un peigne à dents fines pour trouver la source du problème. Si la validation a touché un petit nombre de fichiers, il est moins difficile de retrouver la ou les lignes de code qui ont provoqué le problème.

Je recommanderais de décomposer votre problème en une série de tâches plus petites (idéalement, mettez chaque tâche dans un outil de suivi des bogues). Faites un commit lorsque vous terminez chaque tâche (et fermez ce bogue/cette fonctionnalité dans votre outil de suivi des bogues).

6
Pete

Ce n'est pas la taille du commit qui compte vraiment, c'est le scope du changement qui devrait déterminer comment vos engagements sont organisés.

Vous pouvez, par exemple, modifier chaque instance de __macro1 à __macro2 dans une grande base de code, qui change 200 fichiers. 200 engagements ne seraient pas raisonnables dans ce cas.

Ce que vous voulez vous retrouver, c'est pouvoir extraire le référentiel à n'importe quelle révision et avoir le travail de génération. Avez-vous changé de libfoo à libbar? J'espère que le changement inclut également la mise à jour de vos scripts de construction et de vos Makefiles (ou tout ce qui est applicable).

Parfois, vous devrez peut-être effectuer une série de modifications expérimentales qui accomplissent une chose, auquel cas, vous devez déterminer quelle portée est plus importante pour vous si vous devez revenir plus tard. Est-ce que l'un dépend de l'autre? Validez-les tous en une seule révision. Sinon, dans ce cas, je suggère un commit par changement. Vous devriez faire quelque chose comme ça dans une autre branche, ou dans un autre référentiel de toute façon.

Bien que oui, vous avez le pouvoir de rétablir un seul fichier à une révision précédente (sauvegardant ainsi un fichier d'un engagement plus important), cela fout vraiment les outils comme la bissection plus tard et pollue l'historique.

Si vous vous arrêtez et pensez "Ok, les tests réussissent, je pense que cela fonctionne .. mais si ça va mal, puis-je facilement le retirer?" .. vous finirez par prendre des engagements raisonnables.

5
Tim Post

La chose à saisir ici est que "Large" dans ce contexte concerne le nombre de changements distincts et non la taille physique du commit (bien que généralement les deux vont de pair).

Ce n'est pas une question de "ne pas faire de grands commits" comme faire faire de petits commits - l'idéal étant de commettre de petits changements autonomes.

Il est clair d'après le changelog que vous avez une série de choses qui auraient pu être commises séparément (et en toute sécurité) et donc c'est assez évident que c'est trop grand.

La raison pour laquelle cela peut être un problème est que votre dernier commit est votre point de référence pour les modifications que vous effectuez actuellement et si, par exemple, vous obtenez le premier bit correctement et ensuite vous vous trompez le bit suivant, vous n'avez pas de moyen facile pour reprendre votre travail au point où vous avez commencé à faire des erreurs (BTDTGTTS).

Bien sûr, parfois, les changements sont simplement importants - refactoring à grande échelle - et comme cela est suggéré par d'autres, c'est là que vous devez créer une branche, de cette façon, bien que votre engagement individuel puisse théoriquement casser des choses, ils sont séparés du tronc de développement principal, de sorte que ce n'est pas un problème et vous pouvez continuer à vous engager tôt et souvent.

Encore une chose - si quelque chose arrive au milieu de votre travail qui nécessite une attention plus immédiate, vous devez le changer séparément (idéalement dans un ensemble de dossiers complètement distincts) et le valider séparément.

Le vrai défi dans tout cela n'est pas la mécanique, c'est l'état d'esprit - qu'un commit n'est pas seulement une copie de sauvegarde que vous faites de temps en temps, mais que chaque commit est un pouce en cours de route et qu'il n'y a rien de mal à beaucoup de petites validations et que le fait de fusionner différentes choses ensemble dans un commit de mob est aussi mauvais qu'un ensemble de fonctionnalités liées vaguement dans un bloc de code.

4
Murph

À tout le moins, entraînez-vous à vous engager chaque fois que vous pensez à vous-même "J'aime mes progrès jusqu'à présent, et je ne veux pas les perdre si les changements que je m'apprête à faire sont un désastre." Ensuite, vous avez la possibilité de profiter du VCS pour éliminer les impasses que vous avez essayées ou le code de débogage spécial que vous avez ajouté pour rechercher un problème. (par exemple avec git reset --hard ou rm -rf *; svn update)

4
Ken Bloom

Il n'y a pas de règle stricte et rapide, pas de ligne de démarcation au-delà de laquelle votre engagement est trop important.

Il y a is cependant une directive selon laquelle les petits commits sont meilleurs, dans des limites raisonnables (c'est-à-dire que la validation de chaque ligne est probablement excessive).

Je garde ces types de directives à l'esprit:

  • Un seul commit devrait inclure des changements pour une seule correction de bogue
  • Un seul commit ne doit pas inclure plus d'une demi-journée de travail
  • Un seul commit ne doit pas casser la construction

Bien sûr - c'est ce que je garde à l'esprit - YMMV. Différents développeurs privilégient différents niveaux de granularité.

2
Bevan

Plus le commit est petit, plus il sera facile de trouver d'où vient une régression potentielle.

Idéalement, un commit devrait être atomic, dans le sens de la plus petite modification cohérente de la base de code (liée à un bug, une fonctionnalité, etc.).

Quant aux conseils spécifiques pour garder la taille du commit petit, cela dépend beaucoup de votre VCS et de la façon dont il est configuré: vous devez pouvoir valider localement ou travailler dans votre propre branche sur le serveur.

La clé est de vous engager dans votre branche "privée" à chaque fois que vous effectuez un changement atomique, puis vous pouvez fusionner régulièrement votre branche, par exemple chaque semaine.

En utilisant un dvcs, votre flux de travail pourrait ressembler à ceci:

code code code
git commit       // create commit locally with meaningful message
code code code
git commit       // create commit locally with meaningful message
code code code
git commit       // create commit locally with meaningful message
...
git Push         // Push your previous commits to the team server

Utilisation d'un vcs centralisé:

svn copy trunk my_feature_branch  // create your private branch
svn co my_private_branch          //
code code code
svn commit                        // commit on your private branch with meaningful comment
code code code
svn commit                        // commit on your private branch with meaningful comment
code code code
svn commit                        // commit on your private branch with meaningful comment
...
svn merge my_feature_branch trunk  // all your previous commit are merged to main/master branch
1
Xavier T.

Dans mon cas, j'essaie de valider les fichiers d'un serveur dans le système de référentiel (SVN). Il s'agit du commit initial et je ne veux pas le télécharger car c'est un projet vraiment gros (quelques Go) et je veux faire le commit initial sur le serveur client.

Le problème est que le client est sur un serveur partagé, le client svn est tué (ou tout autre logiciel) s'il s'exécute plus d'une minute.

Une alternative serait de télécharger le projet sur mon ordinateur et de faire le commit initial à partir de là, mais je suis intéressé de savoir s'il existe une option dans SVN pour diviser le gros commit en plus, quelque chose de similaire aux méthodes de transactions.

Le développeur avant moi n'a jamais utilisé de système de contrôle de version.

0
CGeorges

Pour répondre à tes questions:

1) Pour moi, le commit standard est considéré comme gros s'il fait plus d'une chose. Par chose, je veux dire corriger un bogue ou ajouter une fonctionnalité.

2) Empêchez de tels commits en en faisant une habitude et une règle à commettre chaque fois que vous terminez quelque chose.

3) Aux stades semi-précoces du développement, j'autorise les commits à inclure la première création des fichiers qui seront utilisés ultérieurement.

Je voudrais noter que par fini, je veux dire que tous les bogues que vous pouvez identifier ont été corrigés et que vous ne romprez pas la construction en vous engageant.

Oui, cela génère un grand nombre de validations, mais cela vous permet d'annuler exactement ce qui a cassé les choses au lieu d'avoir à annuler une grande série de modifications qui ont été validées en même temps où une seule des modifications provoque un problème.

Je voudrais également souligner que les règles changent un peu pour les systèmes de contrôle de version distribués (DVCS) comme Mercurial et Git. Dans le cas où vous en utilisez un, vous vous engagez chaque fois que vous avez apporté une modification, mais vous ne l'avez pas encore testée, puis vous transmettez au référentiel central lorsque cela fonctionne. C'est préférable car cela vous permet de réviser plus de modifications de votre code sans vous soucier de casser la construction.

0
indyK1ng

Vous avez probablement entendu le dicton que la perfection, c'est quand vous ne pouvez rien enlever de plus. Cela devrait également décrire votre norme de taille de validation.

Cela dépend de votre projet où se trouve cette taille "parfaite". Si vous expédiez à des clients externes, une bonne taille peut être le plus petit incrément que vous seriez à l'aise si vous ne finissiez pas le prochain à temps. Si vous créez des applications internes fréquemment déployées, la meilleure taille peut être le plus petit incrément qui ne casse rien (et vous rapproche de l'endroit où vous voulez être).

Les systèmes de contrôle de version modernes vous aident à créer de bons commits avec un branchement facile, un rebasage interactif, une zone de transfert, etc.

0
Peter Eisentraut

Les messages de validation doivent être d'une seule ligne (et pour git max 60 caractères). La quantité de code en cours de validation doit être suffisamment petite pour maintenir le message descriptif dans cette limite.

J'ai tendance à m'engager à chaque fois (encore plus maintenant que nous sommes passés à git). J'ai un morceau fait, car cela permet de capturer le "pourquoi" les choses ont été faites de cette façon.

0
user1249

Parfois, vous avez travaillé toute la journée sur plusieurs problèmes différents logiquement distincts, et vous avez oublié de valider votre code entre les deux. En utilisant git citool peut être très utile pour diviser votre travail en morceaux de la taille d'une bouchée de Nice à la fin de la journée, même si vous n'avez pas été si prudent pendant la journée pendant que vous travailliez.

git citool peut vous permettre de sélectionner les segments spécifiques d'un fichier (ou les lignes spécifiques) à valider dans une validation particulière, de sorte que vous pouvez diviser (sans chevauchement) les modifications apportées au même fichier en plusieurs validations.

(Il semble que vous utilisiez Subversion. Je ne connais pas d'outil qui le fasse pour Subversion, mais vous pourriez envisager d'utiliser git-svn, l'adaptateur Subversion pour git, qui va changer votre vie.)

0
Ken Bloom

Plus le commit est important, plus vous risquez de casser la build et d'être payé par le reste de votre équipe. J'essaie de valider les modifications deux fois par jour. Juste avant le déjeuner et avant de rentrer chez moi. Donc à 12h et 16h30 j'essaie de tout faire fonctionner et prêt à s'engager. Je trouve que cette pratique fonctionne pour moi.

0
Nickz