Que dois-je faire quand j'ai déjà trop attendu entre les commits?

100

J'étais méchant ... Trop de "codage cow-boy", pas assez engagé. Maintenant, me voilà avec un engagement énorme. Oui, j'aurais dû m'engager depuis le début, mais c'est trop tard maintenant.

Qu'est-ce qui est mieux?

  1. Faites un très grand commit listant tout ce que j'ai changé
  2. Essayez de diviser le fichier en plusieurs commits qui ne seront probablement pas compilés, car les fichiers contiennent plusieurs correctifs, modifications, noms de méthodes supplémentaires, etc.
  3. Essayez de faire des réversions partielles de fichiers uniquement pour les commits appropriés, puis annulez les nouvelles modifications.

Remarque: pour le moment, je suis le seul programmeur à travailler sur ce projet. La seule personne qui se penchera sur l'un de ces commentaires de validation est moi, du moins jusqu'à ce que nous embauchions plus de programmeurs.

Au fait: j'utilise SVN et Subclipse. J'ai créé une nouvelle branche avant de faire ces changements.

Plus d'informations : J'ai posé une question distincte sur la manière dont je suis entré dans cette situation: Comment se préparer à la réécriture de la colle d'une application

durron597
la source
2
Quel programme de contrôle de version utilisez-vous? Beaucoup ont des modules qui vous permettent de diviser vos modifications en "morceaux", c'est-à-dire des groupes de lignes modifiées, ce qui vous permettrait de regrouper vos modifications comme vous le souhaitez et de distribuer les mods d'un fichier à plusieurs ensembles de modifications. Par exemple, mercurial a l'extension "shelve". Bien sûr, vous devez toujours vérifier si chaque lot de modifications est compilé, si cela compte pour votre processus. Que cela vaille la peine, c'est à vous et à votre magasin de décider.
alexis
6
Au moins, enregistrez-le sur une branche pour ne pas perdre vos modifications.
Rory Hunter
2
Vous pouvez continuer à vous poser la question et attendre encore plus longtemps, ou bien vous engager et régler tout désordre qui crée ... Et alors ... ne recommencez pas!
haylem
40
# 1, priez pour le pardon, puis allez de l'avant et ne péchez plus :)
Peteris
5
La question la plus importante que vous devriez vous poser est la suivante: "Comment puis-je changer mes mauvaises habitudes pour que cela ne se reproduise plus". Il ne devrait y avoir aucune raison de s’engager pas au moins une fois par jour, mieux, plus souvent.
Doc Brown

Réponses:

52

Pour répondre, vous devez vous demander comment vous comptez utiliser les résultats de ces commits à l'avenir. Les raisons les plus courantes sont:

  • Pour voir quelle version un bogue a été introduit.
  • Pour voir pourquoi une certaine ligne de code est présente.
  • Pour fusionner dans une autre branche.
  • Pour pouvoir consulter une version précédente afin de résoudre un problème rencontré par un client ou un testeur dans cette version.
  • Pour pouvoir inclure ou exclure certaines parties d'une version.

Les deux premières raisons peuvent tout aussi bien être servies avec un seul enregistrement important, en supposant que vous puissiez créer un message d’enregistrement qui s’applique également à chaque ligne de code modifié. Si vous êtes le seul programmeur, les plus petites mises à jour ne vous faciliteront pas la fusion. Si vous ne prévoyez pas de publier ou de tester une partie seulement de vos modifications non soumises, les deux dernières raisons ne s'appliquent pas.

Il y a d'autres raisons pour faire de petits commits, mais elles sont valables tant que vous êtes au milieu des changements, et que le temps est passé. Ces raisons facilitent la sauvegarde d'une erreur ou d'un changement expérimental, et facilitent la synchronisation avec vos collègues sans pour autant que des fusions effrayantes se produisent.

D'après ce que je comprends de votre situation, comme vous l'avez décrite, il semble peu avantageux de diviser votre engagement à ce stade-ci.

Karl Bielefeldt
la source
Excellente réponse! Bien que je ne regrette pas moins de ne pas faire les petits gestes, je me sens beaucoup mieux quant à ce que je devrais faire pour retrouver un bon comportement le plus efficacement possible.
durron597
1
L'autre chose à propos des points 3 et 5 est que tout travail que vous effectuez maintenant pour le permettre, vous pouvez attendre jusqu'à ce que vous en ayez réellement besoin et ensuite faire le même travail. Ce sera probablement un peu plus difficile à l'avenir parce que votre souvenir de ce que vous avez fait a disparu. Mais là encore, vous n'en aurez probablement jamais besoin.
Steve Jessop
Selon mon expérience, il est difficile et fragile de s’appuyer sur les commentaires du contrôle de version pour raconter une histoire sur la raison pour laquelle le code existe (raisons 1 et 2). Si vous utilisez SVN avec une branche, l'historique de validation est perdu lors de la fusion, de toute façon (vous ferez mieux avec des éléments plus modernes tels que git). Donc, ces commentaires sont mieux servis à mon humble avis.
Hans-Peter Störr
1
@hstoerr - si vous utilisez Subversion 1.5 ou une version ultérieure, vous pouvez conserver l'historique avec l'option --reintegrate lors de la fusion.
Dustin Kendall
1
git add -p est votre meilleur ami ici. Je suis tombé amoureux de cette fonctionnalité. De cette façon, je peux valider mes modifications de normes de codage dans des commits distincts et garder les modifications de code pertinentes isolées.
Spidey
39

Je pense que quoi que vous fassiez, essayez d’éviter d’archiver du code que vous savez ne pas compiler.

Si vous pensez que votre troisième option est réalisable, cela pourrait être un bon moyen de le faire, à condition que vous puissiez vous assurer que votre séquence de validations ne créera pas un système incomparable. Sinon, il suffit de faire le gros commit. C'est moche, mais c'est simple, rapide et ça se fait. À l'avenir, commettez plus souvent .

FrustratedWithFormsDesigner
la source
La troisième option est possible , mais il serait extrêmement temps. Je pense que je vais juste faire l'option 1
durron597
3
Quels sont les inconvénients du code s’engageant à ne pas compiler ou à intégrer une branche de fonctionnalité (ou similaire) qui sont si terribles qu’ils obligent quelqu'un à éviter de le faire "quoi qu'ils fassent"? J'imagine que d'autres pourraient vraiment éviter des commits vraiment terribles, ce qui est la seule véritable raison pour laquelle je les évite en premier lieu (en supposant, bien sûr, que les commits ne sont pas publiés ).
Kenny Evitt
3
L' option "éviter l'enregistrement de code non compilé" s'applique uniquement à une base de code / une branche partagée. Sur un projet individuel ou une branche de développement individuelle, je prétends qu'il est plus important de simplement transférer vos modifications dans VC afin de ne pas perdre d'éléments.
Stephen C
3
@StephenC par exemple parce qu'il casse des outils comme git-bisect. Si le code est compilé / exécuté tout le temps et que vous avez besoin de trouver une régression, vous pouvez simplement effectuer une recherche binaire (ne mentionnez pas que s'il y a une régression dans le bloc de code, il vous reste un grand changement à lire au lieu de le réduire le bas).
Maciej Piechotka
@MaciejPiechotka - Eh bien, évidemment, si vous devez utiliser des outils spécifiques sur vos succursales privées et qu'ils nécessitent que le code soit compilable, faites-le. Mais ce n'est pas typique pour un projet / une branche.
Stephen C
19

La raison la plus importante de faire des commits fréquents, petits et significatifs est de faciliter la compréhension de l'historique du code. En particulier, il est très difficile de comprendre comment le code a changé s’il est difficile de générer des différences compréhensibles.

L'option 1 masque l'historique des modifications que vous avez apportées, mais sinon, cela ne posera aucun problème.

L’option 2 masque l’historique des modifications que vous avez apportées, peut-être un peu moins que l’option 1, mais peut poser d’autres problèmes pour vous-même ou d’autres personnes si elles supposent ou concluent autrement que les commits sont distincts, par exemple, ils peuvent être fusionnés indépendamment dans d’autres branches. À moins qu'il existe une raison pratique forte de préférer cette option à l'option 1, cette solution est moins idéale que cela.

L'option 3 est préférable, toutes choses étant égales par ailleurs, mais si, comme vous l'avez décrit ailleurs, cela nécessiterait des délais "extrêmes" ou entraînerait d'autres coûts importants, vous devrez les comparer aux avantages escomptés de créer des commets plus propres.

En fonction des informations que vous avez fournies, je choisirais l'option 1. Peut-être devriez-vous configurer des rappels vous invitant à valider vos modifications?

Prototypage et réécriture

Une autre considération à garder à l’esprit, en particulier à la lumière de votre note sur le fait qu’il est le seul programmeur, et de mon soupçon selon lequel vous travaillez sur une base de code relativement nouvelle, est qu’il est probablement bon de développer des habitudes différentes en ce qui concerne les changements à apporter. prototypez le nouveau code par rapport au maintien ou à l'extension du code existant. Il n'y a probablement pas de division très nette entre les deux, mais je pense que c'est toujours une distinction utile.

Lorsque vous prototypez un nouveau code, validez chaque fois que vous souhaitez enregistrer vos modifications, presque certainement dans une branche, mais peut-être dans un projet séparé. Ou peut-être même juste en dehors du contrôle de version. Vous pouvez plutôt vous concentrer sur la collecte de preuves sur la faisabilité de diverses hypothèses ou conceptions que vous envisagez. J'écris souvent de petits prototypes en utilisant différents outils, par exemple LINQPad au lieu de Visual Studio pour le code C #.

Une fois que vous avez validé une conception ou une hypothèse particulière, réécrivez-la dans votre projet principal, idéalement dans une branche, et effectuez les petits engagements significatifs qui aideront le mieux à comprendre les autres (y compris votre avenir) quant à la nature des changements. vous faites.

Kenny Evitt
la source
1
Bonne réponse; Kenny, avez-vous un bon article ou une autre base de connaissances à associer à des détails plus spécifiques sur le prototypage? Ma version de prototypage est "esquisse dans un cahier ou sur un tableau blanc"
durron597 27/02/2014
@ durron597, je ne peux penser à aucun lien (même à chercher) au sommet de ma tête. J'ai joué avec suffisamment de langages de programmation interprétés (et compilés dynamiquement) pour que je ne pense même pas que l'idée de «prototypage» puisse être nouvelle! Et j'ai réécrit tellement de programmes C, C ++ et Java (encore et encore) que je ne pensais pas que cela pourrait aussi être inhabituel, ou du moins nouveau pour certains.
Kenny Evitt
12

Bien que la seule solution raisonnable soit de ne jamais casser le coffre , cela n’est parfois pas possible. Par exemple, svn peut interrompre la validation si vous en commettez trop (peut-être une option ou une fonctionnalité, je ne suis pas sûr). Dans ces cas particuliers, il suffit de procéder à l'enregistrement. Étant donné que vous êtes un seul programmeur, cela ne va déranger personne.

Par conséquent, je choisirais l'option 1. Si ce n'est pas possible, alors l'option 2.

L'option 3 nécessite beaucoup d'efforts et n'en vaut simplement pas la peine.

BЈовић
la source
1
ou marquez les versions non compilantes comme "NE COMPILNEZ PAS"
freak
2
@ratchetfreak: J'imagine qu'un "tag" dans SVN n'aidera pas grand-chose, car les tags ne fonctionnent pas comme des "commentaires" sur le tronc.
Doc Brown
@DocBrown Je voulais dire l'ajouter au message de validation
Ratchet Freak
5
@ratchetfreak Je le ferais comme "PARTIE X / N: enregistrement ABC - NE COMPILIE PAS"
mercredi
L'option 3 ne nécessite pas beaucoup d'effort. Une autre réponse explique comment le faire rapidement et facilement en utilisant git add --patchet git stash. La situation ne semble difficile qu'en raison de connaissances et d'outils de contrôle de source obsolètes.
Ron MacNeil
7

Essayez de diviser le fichier en plusieurs commits qui ne seront probablement pas compilés, car les fichiers contiennent plusieurs correctifs, modifications, noms de méthodes supplémentaires, etc.

Quand je me suis retrouvé dans une situation similaire, j'ai utilisé la technique suivante:

  1. Ajoutez uniquement le code correspondant à une fonctionnalité particulière: git add --patch
  2. Cachez tous les autres changements: git stash save --keep-index
  3. Exécuter des tests / essayer de compiler
  4. Commit les modifications si tout va bien, sinon passez à 1

Je ne suis pas familier avec SVN, donc je ne sais pas si cela est applicable à votre situation particulière, mais la base devrait être la même: isolez de petites parties de code et testez-les individuellement.

Milos
la source
J'aime cela, mais malheureusement, l'une des nombreuses choses sur ma liste de tâches (il y en a beaucoup lorsque vous êtes le seul technicien dans une entreprise) est de passer de SVN à git, et je ne l'ai pas encore compris .
durron597
1
Comme je ne suis pas assez utilisé --patch, j’utilise Undo dans différents volets de l’éditeur pour accéder aux états de travail précédents et les valider. Puis je refais pour le prochain commit. En raison de la tentation de faire de petits ajouts au code en état Undone, je fais toujours une sauvegarde avant de commencer ce processus!
joeytwiddle
Avec git, vous pouvez également ajouter de manière interactive (ajoutez -i) avant la validation, puis créer une branche pour valider vos validations indépendamment.
Riezebosch
3

Que diriez-vous de l’option 4: sauvegarder l’état actuel de votre référentiel dans un emplacement temporaire, rétablir son état initial, dresser une liste de toutes les modifications apportées (vous pouvez toujours consulter la sauvegarde temporaire), puis réimplémenter manuellement (et compiler) et les tester!) en tant que commits séparés.

Cela devrait être plus facile, car vous avez déjà écrit le code, il vous suffit de savoir quelles parties copier et coller à partir de votre sauvegarde temporaire.

Lorsque vous avez ré-implémenté chaque modification proprement, et que vous vous êtes ainsi assuré que les commits sont autonomes, petits et compilés, vous pouvez supprimer la sauvegarde temporaire et tout se déroulera presque exactement de la même manière (à l'exception de l'heure et de la date des commits). aurait été si vous l'avez fait dès le début.

Superbest
la source
Ceci est juste une façon de faire l'option n ° 3. Probablement le meilleur moyen, c'est vrai, mais cela prend encore beaucoup de temps.
durron597
Il y avait 149 lignes d'ajout / suppression / envoi de messages lorsque j'ai effectué le grand commit. C'est au moins une demi-journée pour faire ça.
durron597
@ durron597 Je ne suis pas d'accord, je pense que c'est différent de # 3. En ce qui concerne 149 lignes, combien valez-vous une histoire de commit propre? Vaut-il la peine de passer une demi-journée? Quoi qu’il en soit, ce n’est pas comme si les autres méthodes ne nécessitaient pas de déterminer quelle ligne devait figurer dans le commit, vous devrez donc passer par les 149 lignes de toute façon. La différence de temps sera petite.
Superbest
Il h. Je suis assez expérimenté pour savoir utiliser le contrôle de version, mais pas assez pour l'avoir déjà économisé :) Ainsi, les raisons pratiques de procéder sont encore un peu académiques, si vous voyez ce que je veux dire.
durron597
Vous n'êtes pas obligé de sauvegarder l' intégralité de votre pension . Vous pouvez effectuer une "sauvegarde", puis restaurer la tête avec git reset HEAD~. Votre commit sera toujours actif git reflogsi vous décidez d’en avoir besoin plus tard. Vous pouvez même créer une branche (puis revenir à la branche active) avant de procéder à la réinitialisation, pour attribuer un nom à votre "sauvegarde". Supprimez la branche plus tard si vous n'en avez pas besoin. Edit: Désolé n'a pas réalisé que OP est sur svn!
Joeytwiddle
3

Tu es le seul programmeur; il suffit de faire un seul enregistrement massif détaillant les éléments importants de ce que vous avez fait.

Êtes-vous susceptible de revenir en arrière "parties" de ce que vous avez fait? Sinon, passez absolument à l'option 1.

Il existe plusieurs raisons pour insérer du code dans un système de contrôle de version. Et TOUS ceux-ci, lorsque vous êtes le seul développeur, tournent autour de la sécurité - à savoir, si vous échouez, la machine meurt ou ce que vous voulez, vous pouvez toujours revenir à ce dernier point de contrôle.

Il est peu probable qu'un programmeur intervenant plus tard dans le projet veuille revenir à une version non compilée. Donc, à mon humble avis, l'option 2 est une folie.

L'option 3 ressemble à une telle perte de temps que si j'étais votre patron et que je vous voyais perdre des heures à le faire, je vous parlerais un peu de la valeur de votre temps.

Pour itérer: en enregistrant votre code, vous couvrez / enregistrez votre cible en cas de panne de votre machine. Tout le reste, dans une équipe composée d'un seul homme, est habillé de vitrine.

Pas moi
la source
1
Revenir en arrière n'est pas la seule raison d'utiliser de petits commits. Ce n'est même pas une raison particulièrement bonne. La principale raison est de pouvoir savoir quand et pourquoi une modification a été introduite et de faciliter le dépannage lorsque vous êtes confronté à un problème d'origine inconnue. Un autre programmeur à venir dans le projet plus tard , presque certainement se rencontrer au moins occasionnellement des lignes de code qui lui font aller « WTF » et renvoyer au commit où il a été écrit ou dernière modification. Si cet engagement est un engagement de géant pour changer 500 choses, il est impossible d'obtenir des informations utiles de l'historique.
Aaronaught
C'est d'ailleurs pour cette raison que les équipes utilisant Git détestent généralement les commits de fusion et demandent / exigent des rebases. fusionner les commits bisectet autres techniques couramment utilisées pour isoler les problèmes, car de nombreux changements sont regroupés dans un même commit.
Aaronaught
1
Sur un plan personnel, je suis d’accord pour dire que vous ne devriez pas faire de gros commits à moins de changer radicalement une base de code. Cependant, nous parlons d’un seul programmeur qui a fonctionné de manière essentiellement déconnectée et qui essaie maintenant de revenir à la bonne chose. Dans ce cas, je pense qu'un seul gros engagement est préférable.
NotMe
1
@Aaronaught J'ajouterais que 3 mois plus tard, vous pouvez constituer un "autre programmeur".
Maciej Piechotka
1
Je dois également être en désaccord avec le fait de créer des branches en tant que stratégie viable pour les changements d’architecture ou d’autres changements "destructeurs". Cela mène à un cauchemar de conflits de fusion et de bogues post-fusion. À long terme, il est beaucoup moins difficile de trouver un moyen de diviser le changement majeur en changements plus petits compatibles avec les versions antérieures ou, dans le pire des cas, d'utiliser ce que Fowler, Humble et le reste d'entre eux appellent Branch Par Abstraction (qui n'est en fait pas une branche du tout). Ces deux stratégies impliquent des commits petits et ciblés.
Aaronaught
2

Ma règle est la suivante: pas d'enregistrement sans une révision sérieuse du code. Si je suis seul, je devrai examiner le code moi-même, mais il le sera . Vous semblez avoir une quantité de changements de code que quelqu'un d'autre ne pourrait pas réviser, donc vous ne pouvez pas le réviser vous-même (réviser votre propre code est plus difficile et nécessite plus de discipline, car vous faites automatiquement l'hypothèse erronée que votre propre code est correct ).

La règle absolument incassable de tout le monde est la suivante: n'effectuez jamais de vérification dans du code qui ne se construit même pas et évitez sérieusement de vérifier si le code ne fonctionne pas.

Solution: Copiez le code modifié, revenez au point d'origine. Fusionnez une modification à la fois dans le code d'origine, examinez-la, testez-la, et archivez-la. Avec la méthode de programmation que vous avez décrite, vous allez certainement trouver quelques bogues sérieux.

C'est aussi un bon moyen de se former à de bonnes habitudes de programmation.

gnasher729
la source
C'est logiquement la même chose que la réponse ci-dessus basée sur Git ( git add --patchet git stash) et un bon exemple de scénario que les DVCS modernes peuvent gérer facilement, mais que les systèmes plus anciens ne peuvent pas.
Ron MacNeil
1

Je pense que vous vous inquiétez beaucoup trop. Si vous êtes le seul programmeur et que vous n’avez pas de feuille de spécifications contre laquelle travailler, c’est à vous de décider de ce que vous faites. Je suppose que personne ne va vous punir pour avoir fait un gros commit; les seuls problèmes que vous allez rencontrer sont d'ordre technologique, comme l'impossibilité d'annuler des modifications de fichiers individuels dans le commit. Étant donné que vous êtes uniquement en contrôle du repo pour le moment, cela ne devrait cependant pas être un problème majeur.

Il y a une ligne à séparer entre pragmatisme et dogmatisme. Ce que vous avez fait ne serait pas une bonne idée dans une équipe et ne devrait probablement pas être répété à l'avenir, mais dans votre situation, je voudrais simplement soumettre le grand engagement.

Roy
la source
1
cela ne semble pas ajouter grand chose à ce qui a déjà été posté dans les 12 réponses précédentes
gnat
-1

Le problème ne réside pas dans les longs délais entre les validations, mais dans le fait que le code reste inchangé trop longtemps. Tout d’abord, quelle est votre définition du terme "long"? Pour certaines personnes, 5 minutes pour l'état transitoire, c'est trop, mais certaines personnes peuvent modifier leur code pendant des jours sans même essayer de faire fonctionner le compilateur.

En fait, cela n'a pas d'importance - ce qui compte, c'est que vous ayez perdu le contrôle de votre code, votre code est devenu ingérable. C'est normal, cela signifie simplement que vous avez une dette technologique et qu'il est temps de penser à la refactorisation. Donc tu es frustré? Votre code ne compile pas, vous n'avez même pas de tests unitaires? Comment pouvez-vous penser à la refactorisation dans ce cas? Pas de soucis. Terminez votre "codage cow-boy" et commencez à le nettoyer. Dans l’idéal, essayez d’écrire des tests. Tu n'as pas le temps pour ça? Ok, commencez par de petites améliorations.

Certains changements ne nécessitent pas de tests. Changez le nom de la variable pour mieux convenir, déplacez le code répété en une fonction séparée, etc ... Vous obtiendrez une meilleure idée de votre code. Après cela, vous pouvez faire de plus gros changements. Encore une fois, essayez d'écrire des tests si possible. Rendez votre code gérable.

Après cela, vous verrez que le prochain changement ne vous prendra pas "trop ​​longtemps" (peu importe ce que cela signifie).

AlexT
la source
2
Il n'a pas dit qu'il gardait le code non compilable pendant longtemps. Le code dans le repo n’a pas été modifié pendant longtemps - mais reste compilable. Le code dans sa copie de travail a été mis à jour fréquemment mais n'a pas été validé. Rien dans la question n'indique que son code peut nécessiter une refactorisation - le "codage cowboy" fait ici référence à son flux de travail SCM, et non à la qualité réelle du code
Idan Arye
@IdanArye De la question initiale ...Try to break it into smaller commits that likely won't compile...Si quelque chose vous empêche de valider votre code, il est déjà difficile de le gérer, il est difficile à gérer. "S'engager" n'est qu'un des moyens de persévérer dans votre travail. Nous pouvons penser à un cas plus extrême - "si quelque chose m'empêche de sauvegarder le fichier source". Alors qu'est-ce que ça pourrait être? Je suppose que c'est la peur de vos propres changements. Pourquoi cela peut-il être? ... Je suppose que vous avez compris
AlexT
2
Pour moi, cela ressemble plus à ce qui l’empêchait de commettre n’était que de la paresse.
Idan Arye
@ IdanArye Vous avez raison sur tous les plans. Cela plus ne pas faire assez de TDD, qui est une question distincte.
durron597
@AlexT envisage un scénario dans lequel vous corrigez deux bogues, dont l'un nécessite une nouvelle méthode. Si vous avez commis correctement, vous corrigez un bogue, vous validez, puis corrigez l'autre bogue. Si vous ne l'êtes pas, alors lorsque vous validez, vous devez inclure les deux modifications dans la même validation ou valider le premier correctif avec les modifications pour la seconde, sauf que la version validée n'a pas le nouvel appel de méthode et par conséquent ne compile pas.
durron597