• [^] # Re: Exemples concrets?

    Posté par . En réponse à la dépêche Pijul, contrôle de version et théorie des patchs, version 0.12. Évalué à 5.

    Peut-être serais-je encore plus efficace avec Pijul, qui sait! Ce n'est donc pas antithètique (être efficace avec git vs. Pijul est pour moi? Aucun rapport, fils unique!). 😛

    D'abord, je ne me suis pas du tout senti "attaqué" par ton commentaire. J'essaie en général d'être rigoureux et concis dans mes réponses (et j'aime bien Git, je l'ai déjà dit).

    D'autre part, Pijul étant significativement plus simple que Git, il n'est souvent pas complètement évident pour nous d'écrire de la doc. Pour avoir appris Pijul à des gens autour de moi, il me semble que la principale difficulté consiste à oublier les workflows, les bonnes pratiques, etc. Mais nous sommes complètement ouverts à des contributions, en particulier sur la documentation, comme tu peux le voir sur https://nest.pijul.com/pijul_org/manual/patches.

    Je pense qu'une bonne façon de voir des exemples concrets, c'est d'essayer. Effectivement, le manuel n'est pas écrit en pensant aux gens qui vont vouloir comprendre tout Pijul sans jamais l'essayer, mais plutôt aux gens qui l'essaient et veulent comprendre comment ça marche (et pourquoi ça marche dans 100% des cas).

    Je te suggère d'essayer tous les trucs dont j'ai parlé ici :

    • essaie d'utiliser Pijul sans faire de branches. Ne fais que des clones dans un premier temps. Les branches de Pijul sont des clones rapides, mais comme la copie de travail est au même endroit, utiliser les branches peut cacher des trucs.
    • essaie de pousser tes patchs sur https://nest.pijul.com, et fais des unrecord de vieux patchs dans l'onglet "patchs",
    • essaie de faire des pull entre dépôts locaux sans prendre tous les patchs (du cherry-picking implicite).
    • essaie de faire des conflits, d'éditer juste un côté et de faire record et push. Ensuite, dans un autre dépôt, pull seulement les patchs relatifs au côté que tu as édité. (A et B sont en conflit, C édite le morceau introduit par A. Pull juste A et C dans un dépôt séparé).

    Tiens là par exemple j'ai vraiment du mal à comprendre ce que tu me dis. Comment la branche peut-elle être rebasée sans demande explicite?

    Exemple concret d'un rebase d'une branche sur une autre : tu as une branche Git A, forkée depuis une branche Git B.

    Pour faire plus concret:

     - y - z
     /
    --- x -- u - v
    

    Et tu veux la rebaser :

     - y - z
     /
    --- x -- u - v
    

    Dans Pijul, cette opération est parfaitement inutile, vu que les branches sont juste des patchs (il y a aussi un truc qui s'appelle "branche" dans Pijul, ce n'est pas la même chose). Dans Pijul, tu as juste deux ensembles de patchs, { x, y, z } et { x, u, v }. Si tu veux, tu peux appliquer un patch sur l'un des deux : { x, y, z, u }. Il n'y a pas d'opération spéciale pour faire ça, c'est juste appliquer un patch qui est dans une autre branche. Tu n'as pas besoin de réfléchir à la disposition de tes branches en le faisant.

    Et tu pourras toujours revenir en arrière plus tard, même après avoir appliqué d'autres patchs. Concrètement : si tu as { x, y, z, u, a, b }, et que tu te rends compte que tu ne voulais pas u, ce que tu veux faire est "enlever u de l'ensemble", pas "dire que le parent de a devient z, puis essayer d'inverser le diff entre z et u".

    Je suis d'accord que ça ne fait aucune différence sur les exemples simplifiés sur lesquels on explique généralement Git. Mais si tu imagine que u était en fait un merge avec conflit, qu'il a fallu plusieurs heures de travail d'un ingénieur cher pour résoudre les conflits et fabriquer u, et qu'on va peut-être vouloir le reprendre plus tard, tu peux imaginer le temps et l'argent perdu (par rapport à Pijul).

    Et comme je l'ai déjà dit dans d'autres réponses, le modèle de Git oblige l'utilisateur à recharger un modèle mental du dépôt dans sa mémoire avant de commencer à taper des commandes. Ça n'a aucun inconvénient si ce modèle est simple (une seule branche, chaque commit ajoute une ligne, pas de conflits). Ça peut prendre du temps dans les autres cas. On pourrait répondre "oui mais tu vas bien devoir connaître ton dépôt quand même, pour travailler avec". Mon expérience (et celle des utilisateurs de Darcs et Pijul) est que c'est dû aux contraintes internes de Git, et que ce n'est souvent pas nécessaire.

    Mais tu le retires-retires? Il n'est plus disponible du tout, plus de trace dans l'historique (genre pas comme un git revert où tu annules l'action du commit sans retirer dans l'historique)?

    Ça reste un patch écrit dans un fichier, donc il existe encore, il n'est juste plus dans le dépôt. On peut le réappliquer.

    C'est tout de même assez tendancieux de permettre la réécriture à volonté (pour les branches publiques, notamment communément celle appelée "master" dans git). Et ce n'est pas seulement car on casse l'historique dans git (les hashs de commit qui ne sont pas cassés dans Pijul, j'ai bien compris cette partie!), mais bien aussi car réécrire l'histoire, c'est perdre des informations.

    Le morceau de mon commentaire auquel tu réponds ici était juste un exemple d'utilisation de rebase autre que "rebaser une branche sur une autre" dans Git.

    J'ai déjà dit dans plusieurs autres commentaires que Git perdait de toute façon un peu d'informations en imposant la même histoire à tout le monde une fois un merge fini, alors qu'il y a eu en vrai ("concrètement") plusieurs histoires différentes qui ont produit la même chose.

    En d'autres termes: Alice et Bob travaillent ensemble, Alice fait un patch A, Bob fait un patch B en parallèle. Après le merge, Git dit juste "A et B ont été fusionnés", alors que Pijul dit "Alice a appliqué A, puis B" et "Bob a appliqué B, puis A", et on a la garantie que les deux ont exactement la même chose dans 100% des cas.

    Aussi les gens avec un vieux hash de commit ne peuvent plus le retrouver. Les seuls cas considérés comme acceptables sont normalement lorsqu'on a "commité" des infos méga-confidentielles par erreur (et encore... en général si on a fait ça, il faut surtout considérer que c'est trop tard cas on ne sait pas qui en a pris connaissance; donc réécrire l'histoire ne sert en général à rien, même dans ce cas, à part limiter les dégâts éventuellement le temps de changer les infos fuitées à la source).

    J'ai l'impression que tu parles de bonnes pratiques Git. Je ne sais pas encore ce que peut être une bonne pratique dans Pijul, ni comment les gens vont vraiment l'utiliser. Git a plein de bonnes pratiques et de trucs "considérés comme acceptables" à cause de contraintes techniques, je ne sais pas quelles "bonnes pratiques" resteraient si on enlevaient ces contraintes (et je ne pense pas que quelqu'un puisse le savoir sans avoir essayé concrètement dans la vraie vie).

    Mais ça veut dire quoi concrêtement une "vraie représentation interne des conflits", pour nous autres simples développeurs qui veulent juste versionner nos sources?

    Ça veut dire que dans Pijul, un conflit n'est pas juste une erreur de fusion, c'est un état normal. Tu peux par exemple éditer l'un des côtés du conflit sans le résoudre, ou encore partager la résolution du conflit entre deux patchs sans avoir à partager tout le reste.

    Avec des noms sur les patchs, ça donne : si tu as deux patchs A et B qui sont en conflit (par exemple, A écrit "a" dans un fichier, et B écrit "b" au même endroit), tu peux produire un patch C qui résout ce conflit. N'importe qui qui a les deux patchs A et B va voir le même conflit (indépendamment des autres patchs qu'ils pourraient avoir, par exemple s'ils ont d'autres patchs D ou E). Et à partir du moment où tu as A, B, et C dans le même dépôt, ce conflit est résolu. Il ne reviendra pas (au revoir, git rerere!).