Journal Un bel exemple de financement participatif : magit

Posté par  (site Web personnel) . Licence CC By‑SA.
38
28
mai
2020

Salut,

Un petit billet d'humeur sur magit. Il s'agit d'une interface Emacs à git. Je l'utilise avec Doom Emacs, la meilleure implémentation de vim.

C'est la seule interface à git qui me permette d'éditer un commit à la ligne près plutôt que par morceau de diff. Parfois, j'aimerai aller plus finement et découper la modification d'une ligne en deux patch séparés :-) Il y a aussi le fixup instantané dans l'historique, le rebase interactif et la gestion de conflit accompagné, etc. Tout ça avec l'auto-documentation d'Emacs qui permet de tirer rapidement partie de toute les fonctionnalités de l'outils :-)

En 2017, magit a fait l'objet d'une campagne de financement participatif avec succès, relayé dans nos colonnes. Ce qui fait moins de bruit, c'est que le but de la campagne de 2017 a porté ses fruits: Magit est bien maintenu, le support des PR GitHub et des MR GitLab est super. Le projet est super stable.

Bref, Magit et son mainteneur Jonas sont de ceux qui donnent confiance dans le financement participatif. Merci !

Et vous ? Avez-vous des expériences de financement participatifs qui ont changé quelque chose ?

NdM : l'article dans nos colonnes dont parle l'auteur est ici : https://linuxfr.org/users/dzecniv/journaux/financement-participatif-pour-magit

  • # Commit plus fin

    Posté par  (site Web personnel) . Évalué à 1 (+0/-0).

    Il me semble que tu peux stage une région (au sens emacs du terme) du diff pour avoir des commits plus fin.

    • [^] # Re: Commit plus fin

      Posté par  (site Web personnel) . Évalué à 5 (+3/-0).

      Peut-être fais-tu référence à l'option --patch (voire --interactive) qui permet de faire des commit ou de stager (avec add) les changements par morceaux? Si c'est le cas, cela permet en effet de faire des commits plus fins. Je l'utilise régulièrement quand je fais des très gros changements et que je me rends compte que je peux les couper un peu pour les rendre moins imbitables.

      Mais il y a des limites à la fonctionnalité. Des fois, par défaut, le morceau proposé est trop grand. Dans ce cas, y a la possibilité de demander à faire un split. Parfois git y arrive, parfois non. Typiquement quand y a 2 lignes modifiées l'une après l'autre, git ne sait pas les séparer en 2 patches.

      Alors quand je lis que cet outil saurait séparer (j'ai pas testé) des commits "à la ligne près", et même "découper la modification d'une ligne en deux patch séparés", alors là je dis, ce serait effectivement magitmagique!

      Malheureusement c'est pour un éditeur de code que je n'utilise pas. C'est dommage, ils auraient pu rendre cet outil plus générique (ce qui ne les empêchait pas de faire aussi un plug-in pour leur éditeur de prédilection, lequel utiliserait leur outil générique). 😕

      Parce que là, changer d'éditeur juste pour ça, ça vaut pas le coup. Dommage. 😢

      Film d'animation libre en CC by-sa/Art Libre, fait avec GIMP et autre logiciels libres: ZeMarmot [ http://film.zemarmot.net ]

      • [^] # Re: Commit plus fin

        Posté par  . Évalué à 3 (+1/-0).

        Pas de soucis, tu peux évoquer une instance d'Emacs avec Magit dans le répertoire courant avec qlq chose comme:

        emacs -nw --eval '(magit-status "./")'
        le -nw est pour "no window system", lancer Emacs dans le terminal. Il faut avoir installé Magit au préalable, qui n'est pas inclus par défaut (oui c'est dommage). Il l'est peut-être dans Spacemacs ou Doom-Emacs ou d'autres "starter kits".

        Et pour gagner en temps de lancement, tu peux lancer Emacs une fois, appeler son server-mode, puis utiliser emacsclient.

        Construire un exécutable de Magit pour les non-utilisateurs d'Emacs était un but de la campagne, mais il semblerait bien non atteint. https://emacsair.me/2017/09/01/magit-for-non-emacs-users/

  • # Pas la seule interface à la ligne près

    Posté par  . Évalué à 3 (+3/-0).

    C'est la seule interface à git qui me permette d'éditer un commit à la ligne près plutôt que par morceau de diff.

    Ce n'est pas la seule : on peut citer au moins git-cola et mon chouchou vimagit qui est grandement inspiré de magit mais pour vim comme son nom l'indique.

    Mais les alternatives n’enlèvent rien à ce super outil !

    • [^] # Re: Pas la seule interface à la ligne près

      Posté par  (site Web personnel) . Évalué à 2 (+0/-0).

      Tu peux aussi affiner ton commit comme cela dans SourceTree (propriétaire ouh ouh) et dans une moindre mesure dans TortoiseGit moyennant une manip un peu plus complexe (Restore this file after commit, ajustement de ce que tu veux committer dans ton editeur/diff viewer).

      TortoiseHg faisait ça super bien, dommage que git ait écrasé toute la concurrence.

      Moi aussi, j'aime bien les commits précis.

    • [^] # Re: Pas la seule interface à la ligne près

      Posté par  . Évalué à 1 (+0/-0).

      git gui permet également de découper son commit par lignes (le menu contextuel sur une sélection contient les entrées "Stage Lines For Commit" et "Stage Hunks For Commit").

      Certes l'outil est un peu austère, mais il a l'avantage d'être livré en standard avec git.

  • # édition de commit

    Posté par  (site Web personnel) . Évalué à 4 (+1/-0).

    C'est la seule interface à git qui me permette d'éditer un commit à la ligne près plutôt que par morceau de diff.

    J’ai du mal à saisir ce que tu appelles « éditer un commit » et le besoin derrière. D’ordinaire ma méthode de travail est la suivante : je fais plein de micro-commits, et de temps à autres, je fusionne les commits en divers commits plus gros. Je n’ai donc jamais à scinder des commits puisque ma méthodologie est de fusionner des micro-éditions de manière cohérente quand j’ai enfin assez de recul sur la forme que prend mon travail. Note que mon environnement de travail n’est pas mon éditeur (vim), mais le terminal. Vim n’est qu’un composant de cet environnement de travail, comme le sont le shell, vim, git et d’autres outils.

    J’ai lu cette phrase sur le site de magit:

    [to allow] Git users to perform almost all of their daily version control tasks directly from within Emacs

    J’ai aussi du mal à saisir cette phrase et imaginer le besoin. Je peux aussi quasiment tout faire avec git depuis le vim de base sans plugins puisque… vim permet de lancer des commandes abitraires. Mais en général j’ai un terminal ouvert juste à côté de vim pour parler à Git parce que c’est quand-même plus pratique.

    En fait il y a une raison pour laquelle j’ai du mal à saisir ce besoin-là, qui est aussi la raison pour laquelle je reviens toujours (très rapidement) à vim après avoir essayé tel ou tel IDE: ma méthode de travail consiste à parler à mes outils. L’excellence de Git vient aussi de ce que c’est un langage. Que ce soit le shell, vim ou git, ce sont des outils qui sont conçus pour « parler à l’outil » (voir ce commentaire détaillé à propos de vim).

    ce commentaire est sous licence cc by 4 et précédentes

    • [^] # Re: édition de commit

      Posté par  . Évalué à 2 (+1/-0).

      Par curiosité, comment fais-tu pour "stager" puis committer 10 fichiers parmi 20 qui apparaissent modifiés lors d'un "git status" ? Pour moi, c'est l'un des points forts de magit - La sélection/déselection est super rapide et l'accès aux commandes de commit/merge/push/pull est super bien faite (ma commande préférée : le "merge into" - je ne sais même pas comment la faire sur la ligne de commande :-) )

      • [^] # Re: édition de commit

        Posté par  . Évalué à 3 (+2/-0).

        comment fais-tu pour "stager" puis committer 10 fichiers parmi 20 qui apparaissent modifiés lors d'un "git status" ?

        git commit fichier1 fichier2 ... fichier10
        

        ou bien:

        git add fichier1 fichier2 ... fichier10
        git commit
        

        ou bien si tu ne veux committer que certaines modifications (au lieu des fichiers entiers):

        git add -p 
        # ensuite tu choisis interactivement ce que tu veux committer, puis
        git commit
        

        (ma commande préférée : le "merge into" - je ne sais même pas comment la faire sur la ligne de commande

        Je suis allé voir la doc (mais je n'ai pas tout compris) :

        (magit-merge-into)

        This command merges the current branch into another local branch and then removes the former. The latter becomes the new current branch.

        Before the source branch is merged, it is first force pushed to its push-remote, provided the respective remote branch already exists. This ensures that the respective pull-request (if any) won’t get stuck on some obsolete version of the commits that are being merged. Finally, if magit-branch-pull-request was used to create the merged branch, then the respective remote branch is also removed.

        C'est plus compliqué (vu que ça fait 4 ou 5 choses en même temps), en gros:

        git push -f
        git checkout autreBranch
        git merge branch
        git branch -D branch
        # et si on veut
        git push someRemote :branch
        

        C'est probablement foireux et il y a probablement plus simple, je n'ai pas compris le cas d'utilisation (ça doit être lié à magit-branch-pull-request mais j'ai la flemme de comprendre :o).

        • [^] # Re: édition de commit

          Posté par  . Évalué à 4 (+3/-0).

          C'est bien ce que je pensais - Tu tapes tout explicitement dans le terminal (avec l'aide de la completion bien sur et sans doute du copier/coller avec la souris). L'intérêt de magit est de simplifier tout ça .
          Pour stager 10 fichiers, je n'ai qu'a utiliser la touche s dix fois car magit me construit la liste des fichiers potentiels à committer. Ensuite "c c" pour rédiger le message de commit, Ctrl-c Ctrl-c pour commiter, Puis p-u pour le git pull Tout ça sans quitter le clavier ni quitter emacs, avec une aide dynamique pour les commandes les plus compliquées.

          Et ça marche même avec tramp (le système d'accès à une machine distante d'Emacs) - Super pratique quand le shell de la machine distante n'est pas configuré au petit oignon comme son shell local

          • [^] # Re: édition de commit

            Posté par  . Évalué à 2 (+1/-0).

            Et j'oubliais, ça marche super bien avec les "submodules" de git. On peut se balader sans problème entre le project principal et les sous projects comme si on navigue au clavier dans un gestionnaire de fichier

            • [^] # Re: édition de commit

              Posté par  (site Web personnel) . Évalué à 5 (+2/-0). Dernière modification le 28/05/20 à 23:38.

              Amusant, étant donné que mon environnement de développement est le terminal et que j’utilise un terminal pavant, je ne me ballade pas entre le projet principal et les sous projets, j’ai tout simplement une vue dans chacun des projets dont j’ai besoin. Je n’utilise le gestionnaire de fichier — depuis le terminal en l’ouvrant dans le dossier courant — que dans des cas très particuliers comme lorsqu’il est pratique de visualiser des miniatures. Le gestionnaire de fichier est fermé aussitôt qu’il ne sert plus, ce n’est qu’une visionneuse de dossier en quelque sorte.

              C’est intéressant de lire ces retours parce qu’au delà du fait que je reconnais l’efficacité de faire toutes ces choses que tu décris en une lettre ou deux (à la vim) au lieu de taper des mots comme je fais, la façon de travailler est radicalement différente : je ne sais pas vraiment ce que c’est de « naviguer au clavier dans un gestionnaire de fichier », je vois très bien ce que c’est mais cela ne fait pas partie de mon workflow, je ne peux donc pas ressentir le besoin de rendre plus efficace le fait de se balader dans un gestionnaire de fichier par exemple.

              Une chose intéressante est de constater que les IDE ont tendance à fournir des surcouches à Git assez élaborées, alors que si l’environnement est le terminal directement, l’intégration de Git ne demande rien (les commandes usuelles comme git log, git branch, etc. sont considérés par git comme des porcelain). Le workflow modèle d’un rebase c’est le shell + git + vim. Il semble que Git soit pensé directement pour cette méthode de travail où le développeur vit dans un terminal.

              Je serai curieux de voir comment Linus Torvalds travaille par exemple…

              ce commentaire est sous licence cc by 4 et précédentes

      • [^] # Re: édition de commit

        Posté par  (site Web personnel) . Évalué à 8 (+5/-0).

        Par curiosité, comment fais-tu pour "stager" puis committer 10 fichiers parmi 20 qui apparaissent modifiés lors d'un "git status" ?

        Si tu as 10 fichiers parmi 20 qui apparaissent modifiés lors d’un “git status” c’est que tu n’appliques pas ma méthode de travail et que tu as raté autant sinon plus d’occasions de faire un “micro commit”.

        Par exemple je commence à travailler sur une fonctionnalité, la première modification significative je la commite avec un mot clé qui désigne ma fonctionnalité (par exemple: fonctionnalité). à chaque fois que je fais une modification qui contribue à l’implémentation de cette fonctionnalité, je nomme le commit fixup-fonctionnalité.

        Si en implémentant cette fonctionnalité je tombe sur un bug qui n’a rien à voir dans une autre partie du code et qu’il est trivial, je le corrige tout de suite pour décharger la charge mentale et je le commit avec un message du genre fix-nomdubug. Idem pour des trucs àlacon© genre un problème accessoire ayant très à des conventions d’écriture ou une faute de frappe quelque part dans un commentaire.

        Si, alors que j’implémente ma fonctionnalité je me rend compte que ma fonctionnalité a besoin d’un travail péallable, par exemple le découplage d’un code qui n’est qu’une partie d’une fonction existante et que cette partie doit être réutilisable sans le reste pour mon implémentation, et bien je fais un commit avec un message du genre découplage-lecodequifaitça, et je continue mon implémentation. Si je me rends compte que mon implémentation a besoin que mon « prérequis » (ici mon découplage) soit fait autrement, bah je modifie cet autre code et je fais un commit fixup-découplage-lecodequifaitça.

        À la fin j’ai un historique qui ressemble à ça:

        * dernier commit déjà poussé de ma branche
        - fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - bikeshedding
        - fixup-fonctionnalité
        - découplage
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-découplage
        - fixup-découplage
        - fixup-fonctionnalité
        - fixup-découplage
        - fixup-bikeshedding
        - fixup-découplage
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        

        Quand j’estime que mon code est prêt à être soumis à revue, je fais un rebase interactif (le combo shell/git/vim par excellence) et je réorganise mes commits :

        * dernier commit déjà poussé de ma branche
        - découplage
        - fixup-découplage
        - fixup-découplage
        - fixup-découplage
        - fixup-découplage
        - fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - fixup-fonctionnalité
        - bikeshedding
        - fixup-bikeshedding
        

        En général je ne fusionne pas encore, histoire de ne pas avoir à recommencer s’il y a un conflit dans le rebasage. Je fusionne ensuite:

        * dernier commit déjà poussé de ma branche
        - découplage
        - fonctionnalité
        - bikeshedding
        

        Et j’en profite pour rédiger de jolis messages pour la postérité, parce que c’est prêt à pousser vers la revue. Je pourrai même en extraire plusieurs branches.

        Là je montre une situation ou la fonctionnalité peut se réviser simplement avec un seul commit, mais il est tout à fait possible de faire ça, chaque étape aura eu son lot de micro-commit intermédiaire :

        * dernier commit déjà poussé de ma branche
        - découplage, étape 1
        - découplage, étape 2
        - fonctionnalité, étape 1
        - fonctionnalité, étape 2
        - fonctionnalité, étape 3
        - fonctionnalité, étape 4
        - bikeshedding
        

        Un exemple avec un projet public. À la fin du processus, une fois que mon travail était prêt à être soumis à revue, la branche ressemblait à ça:

        commit 720ebe934fcdb49bb30d5d797e5c7e173bbba77f
            commands: use switch/case for weapon kind and attack key
        
            - use switch/case instead of reading pm->ps->weapon everytime a test is needed
            - reuse attack1/2/3 buttons instead of calling usercmdButtonPressed again
            - only do goon-related tests in goon-related block
            - only do tyrant-related code in tyrant-related block
            - only do luci-related code in luci-related block
        
        commit 365ea2cc6b58f093f8785974c71de9c9cc2bb341
            commands: make deconstruction code reusable
        
        commit 55a9ff32d938547ff15f47d63fdd658db4fbfd60
            commands: make code to test if buildable is protected reusable
        
        commit 2347840a057cda0b0fca6400c9f14a9b5c461940
            commands: edit message for protected spawn in a way it's meaningful at marking step
        
        commit 04a6ad0798d0cc3ce90188340571fa4ead51adc2
            charge: add command to remap a number in another range
        
        commit 155513f37e3e6a2b259e3d456cdbd9ebb7fad116
            hack: use negative STAT_MISC for build timer, positive STAT_MISC will be weapon charge
        
            Since weapon charge require build timer to expire first,
            we can wait for build timer to not be smaller than zero
            then store the weapon charge in the same field.
        
            That's very ugly and will bite someone hard in the back in the future,
            please fix engine instead. The day a bug surfaces because of this hack,
            more people would be hurt than the day we would fix the engine.
        
            Not fixing the engine is like feeding an idol who does not mind about us
            and does not deserve it.
        
        commit a23831c44d964469505daa2903fc37116fca0b1b
            commands: press attack2 to mark, hold attack2 to deconstruct, or fire if no buildable
        
        commit c3efc0de5229a505237145a5e5ead6a5d7e0436b
            tutorial: press attack2 to mark, hold attack2 to deconstruct buildables
        
        commit 0d184afd2a767c40ea50e4fd5aa2cf74e1e2b2e1
            bikeshedding: add some comments to help to understand or fix the code
        
        commit c9cbab8e38663a609a5a0c936f092646ceaeeac8
            commands: substract build timer with the time the player spent on holding deconstruct key
        
        commit 7c8008fc62de0e1bf8e682a4e05e293ff2728bcf
            commands: display the protected buildable message as soon as possible, at marking step
        
            display it when marking for replacement,
            do not wait for the complete deconstruction procedure.
        

        La majorité de ces commits sont la fusion d’une dizaine d’autres. On remarque des commits qui implémentent des découplages qui sont apparus comme nécessaire pour implémenter la fonctionnalité, et on remarque que la partie de l’implémentation de la fonctionnalité qui est le tutoriel pour cette fonctionnalité est dans son commit propre pour faciliter la revue. On remarque également un commit qui ajoute des commentaires dans du code existant que je n’ai pas modifié mais que j’ai du lire et comprendre pour implémenter ma fonctionnalité, et je veux m’épargner cet effort de compréhension dans le futur (toujours économiser la charge mentale de soi et du futur-soi).

        Je ne sais pas c’est un merge-into, c’est comme un checkout suivi d’un cherry-pick?

        ce commentaire est sous licence cc by 4 et précédentes

    • [^] # Re: édition de commit

      Posté par  (site Web personnel) . Évalué à 2 (+1/-0).

      En fait il y a une raison pour laquelle j’ai du mal à saisir ce besoin-là, qui est aussi la raison pour laquelle je reviens toujours (très rapidement) à vim après avoir essayé tel ou tel IDE: ma méthode de travail consiste à parler à mes outils. L’excellence de Git vient aussi de ce que c’est un langage. Que ce soit le shell, vim ou git, ce sont des outils qui sont conçus pour « parler à l’outil » (voir ce commentaire détaillé à propos de vim).

      Les outils-langages c'est bien, mais ça peut devenir compliqué quand tu en utilises plus que trois et que tu passes de l'un à l'autre régulièrement pendant une session de travail.

      Ce que propose Emacs, c'est justement un seul langage uniforme pour parler à tous tes outils (au moins à tous ceux qui produisent et/ou consomment du texte). Dans la pratique, c'est plus ou moins utilisable selon les outils. Mais magit est un excellent exemple de cette idée appliquée de façon brillante. Un git add -p totalement interactif dans les deux sens (tu peux stage et unstage n'importe quelle sélection de texte) et basé sur le texte sélectionné dans l'éditeur, c'est excellent en termes d'expérience utilisateur : après l'avoir utilisé ne serait-ce que quelques fois, on ne peut plus s'en passer et les autres interfaces à git semblent bien moins pratiques. Je n'ai pas encore eu besoin des fonctionnalités plus poussées, mais j'ai lu qu'elles sont aussi intuitives à utiliser.

      • [^] # Re: édition de commit

        Posté par  (site Web personnel) . Évalué à 4 (+1/-0).

        Ce que propose Emacs, c'est justement un seul langage uniforme pour parler à tous tes outils (au moins à tous ceux qui produisent et/ou consomment du texte).

        Je n’ai pas de problèmes a jongler avec les dialectes mais j’ai le pressentiment qu’il est probable que si un jour un IDE arrive à me convaincre, ce soit Emacs, pour ces différentes raisons. En attendant, terminator + bash (<3 liquidprompt) + git + vim + meld est plus efficace pour moi que VSCode (et les autres que j’ai essayé).

        ce commentaire est sous licence cc by 4 et précédentes

        • [^] # Re: édition de commit

          Posté par  . Évalué à 2 (+0/-0).

          C'est dingue je n'ai jamais réussi à me faire à Meld. Pourtant j'aimerais bien parce que kdiff3 me plante souvent avec un "data loss error" inexplicable tandis que Meld semble être d'accord pour faire mon merge.
          Mais l'interface avec les dessins et les flèches là… Je m'y perds.

  • # Mettre en staging un bout de ligne (ou n'importe quoi)

    Posté par  . Évalué à 1 (+0/-0).

    j'aimerai aller plus finement et découper la modification d'une ligne en deux patch séparés

    1. Dans magit-status, place ton curseur sur le fichier contenant la ligne (section Unstaged).
    2. Presse la touche e (M-x magit-ediff-dwim). Ceci ouvre Ediff.
    3. Tu as maintenant 3 fenêtres contenant différentes versions de ton fichier :
      • la fenêtre de gauche affiche le fichier tel qu'il est commité (HEAD) ;
      • la fenêtre de droite affiche le fichier tel qu'il est sur ton disque (working copy) ;
      • la fenêtre du milieu (ou en bas suivant ton écran et ta configuration) affiche le fichier tel que tu le veux dans ton prochain commit (index).
    4. Tu as aussi une petite fenêtre où tu peux taper les commandes.

    Ta mission, si tu l'acceptes, est de faire des changements dans la fenêtre index. C'est ce que tu mets dans cette fenêtre qui deviendra le contenu de ton prochain commit. Tu peux appliquer une partie des changements d'une ligne en particulier. Tu peux aussi mettre quelque chose qui n'a rien à voir.

    Comme d'habitude avec Emacs, l'outil est très puissant et bien documenté mais ça prend un peu de temps pour le maîtriser.

    Quand tu as fait tous les changements que tu veux, va dans la fenêtre de commande et tape q pour quitter. Tu te retrouves avec un index qui contient exactement ce que tu as tapé dans la fenêtre d'index, peu importe ce qu'il y a dans la working copy.

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n’en sommes pas responsables.