• # Du gitcode à partager - ou pas

    Posté par  (Mastodon) . Évalué à 9.

    Ah ben j'ai pas mal d'alias, ou de fonctions bash, de workflow git chez moi.
    J'ai même un .bashrc.git inclus dans le .bashrc général pour mettre ça dans un endroit séparé.

    Par exemple, tu bosses sur ton clone gitlub, et tu fais des PR sur l'origine gitlub aussi, il faut régulièrement remettre ta branche master/main à jour depuis l'origine.
    Alors :

    function gitmaster() {
        git status -bsuno | head -1 | sed -r 's/## ([^.]*).*/\1/'
        local master=main
        git checkout master && master=master || git checkout main
        git fetch upstream
        git rebase upstream/$master
        git push
    }

    Qui s'adapte en fonction de master/main, et t'affiche en haut le nom de la branche d'où tu es parti.
    Typiquement derrière tu peux faire un
    git checkout ma_branche_de_travail; git rebase/merge master

    J'ai aussi des alias simples comme :

    alias gitdiff="git diff --ignore-space-change --ignore-blank-lines"
    alias gitstatus="git status -bsuno"

    Après, quand j'ai commencé à bosser sur mainster, et qu'il est temps de commiter, j'ai pas encore de branche, alors j'ai ça, avec sa version tout intégré une branche, un commit avec le même texte que le nom de la branche vaguement mis en forme, pas de choix des fichiers à commiter, ie tu commites tout ce que tu as modifié, un push, et yapluka faire la PR sur gitlub :

    function gitnewbranch() {
      git stash
      gitmaster  # la fonction plus haut pour synchro mon master avec celui de l'origine
      git checkout -b "$1"
      git stash pop
    }
    function gitsimplebranch() {
      local branchname="$(sed 's/*/⚹/g' <<< "$1")"
      gitnewbranch "$branchname"
      git commit -am "$(tr _ \  <<< "$1")"
      git push --set-upstream origin "$branchname"
    }

    Et pour le « oups j'ai commité/pushé trop tôt », j'ai aussi ça :

    function gitrepush() {
      local msg="$(git log -n1 --pretty=format:%s)"
      git reset HEAD~
      git commit -am "$msg"
      git push -f
    }

    Cette fonction est un condensé de conneries à ne pas faire : déjà on ne reprend que la première ligne du commit, ensuite on commite tous les fichiers modifiés sans réfléchir, et enfin on écrase un commit déjà envoyé sur le dépôt central, donc public, un vrai bonheur de goret !
    Ça se marie bien avec la gitsimplebranch de plus haut où le message ne fait qu'une ligne et équivaut au nom de la branche, et quand on pushe sur notre clone perso, c'est public mais pas trop, assez pratique pour débugger depuis le gitlub (des fois qu'il y ait une CICD automagique derrière) avant de faire la PR évidemment.

    • Yth.
    • [^] # Re: Du gitcode à partager - ou pas

      Posté par  (Mastodon) . Évalué à 4.

      Pas mal ces petits outils !

      Tu pourrais expliquer le coup du local branchname="$(sed 's/*/⚹/g' <<< "$1")" ?

      En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

      • [^] # Re: Du gitcode à partager - ou pas

        Posté par  (Mastodon) . Évalué à 8.

        Il veut pouvoir mettre le caractère ⚹ dans un nom de branche en le tapant plus facilement en utilisant * qui est directement accessible sur le clavier mais ne veut pas que la commande git l'interprète comme un glob pattern.

    • [^] # Re: Du gitcode à partager - ou pas

      Posté par  . Évalué à 6.

      Oh un copain qui fait beaucoup trop de choses avec git comme moi !

      Tu me permet quelques remarques ? Je suis optimiste, je vais considérer que c'est oui.

      function gitmaster() {
          git status -bsuno | head -1 | sed -r 's/## ([^.]*).*/\1/'
          local master=main
          git checkout master && master=master || git checkout main
          git fetch upstream
          git rebase upstream/$master
          git push
      }

      Je comprends pas le master=master, il sert à quoi ?
      ±a vaut le coup je trouve de faire git rev-parse --abbrev-ref HEAD pour avoir le nom de ta branche, c'est un peu ésothérique mais c'est plus solide que parser la sortie de git (quand on peut l'éviter).

      Quand je peux j'évite de faire des checkout, du coup de fais simplement :

      git fetch -a
      git rebase origin/master
      git force

      git force est un alias git force = push --force-with-lease. Comme ça j'ai l'hébitude de faire git force et pas de push -f.

      function gitrepush() {
        local msg="$(git log -n1 --pretty=format:%s)"
        git reset HEAD~
        git commit -am "$msg"
        git push -f
      }

      Ca me parait super compliqué pour faire :

      git commit -a --amend --no-edit

      que j'ai bien sûr alias en

      ff = commit -a --amend --no-edit
      

      L'alias que je trouve trop cool c'est :

      fixup = "!git log origin/master.. --pretty=format:'%h %s' --no-merges | fzf | cut -c -7 | xargs -o git commit -a --fixup"
      

      Ca permet de choisir avec quel commit de ma branche les changements en cours vont être fusionnés. Ca demande un coup de git rebase -i origin/master pour être appliqué ensuite (j'ai l'option rebase.autoStash = true activé).

      Dernier trucs pour le fun. Si j'ai un git wip qui commit les changements en cours dans un commit wip. J'ai un alias ragequit = !sh -c 'git commit -am wip && shutdown -h now' plus expéditif encore.

      https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

      • [^] # Re: Du gitcode à partager - ou pas

        Posté par  (Mastodon) . Évalué à 3.

        local master=main
        git checkout master && master=master || git checkout main

        Il faut voir les deux lignes :
        * on crée une variable $master qui vaut "main" ;
        * on tente de checkout master ;
        * si ça fonctionne on remplace la valeur de $master par "master" ;
        * sinon on checkout main ;
        * ça permet juste après de faire le git rebase upstream/$master avec le bon nom de branche.

        À la fin la variable $master vaut le nom de ta branche de base, soit master pour les vieux dépôts, soit main pour les plus récents.
        Vu que master n'est plus politiquement correct, même en dehors de la terminologie douteuse de master/slave.
        Bref, c'est pragmatique, pas politique, j'ai affaire à des dépôts où la branche main s'appelle master et d'autres où la branche master s'appelle main. Enfin un truc du genre.

        git rev-parse --abbrev-ref HEAD : T'as raison, ça marche bien, c'est plus propre !

        Concernant le checkout plutôt que fetch, ici je fais ça :
        * afficher le nom de la branche courante pour référence visuelle ;
        * basculer sur mainster ;
        * mettre à jour depuis origin/mainster ;
        * pousser la mise à jour sur son dépôt gitlub.

        Donc on bascule sur mainster, et on synchronise son dépôt perso avec l'origine. On pourrait aller sur l'interface de gitlub et faire une synchro là-bas, puis fetch/checkout localement, mais là c'est une seule commande dans mon terminal qui fait tout.
        Ça évite d'aller clicouiller sur un site web…
        Ok, en général je refais un checkout de ma branche et je rebase/merge depuis mainster, mais disons que jusqu'à présent j'ai jugé que l'automatisation de l'étape de synchro/mise à jour de mainster était suffisante pour mon besoin.
        Ça me sert souvent pour mettre à jour des dépôts sur lesquels je bosse peu, mais dont je peux avoir besoin de la version à jour. Je suis en général déjà sur mainster, et je pourrais faire du fetch/checkout directement, mais faudrait vérifier qu'on n'est pas par hasard sur une branche, etc.
        Disons que la commande gitmaster me ramène dans un état nominal permettant de démarrer un développement, et est la seule que j'adapte à la polémique master/main.

        gitrepush: Ouaip, la fonction est pas clean. Je n'ai jamais cherché le --amend mais en effet ça sert pile à ça.
        On pourrait donc simplifier en :

        function gitrepush() {
          git commit -a --amend --no-edit
          git force
        }
        # Ou plus simple
        alias gitrepush="git commit -a --amend --no-edit && git force"

        J'aime bien ton ragequit :)
        J'aurais plutôt mis un loginctl suspend :)

        • Yth.
        • [^] # Re: Du gitcode à partager - ou pas

          Posté par  . Évalué à 3.

          À la fin la variable $master vaut le nom de ta branche de base, soit master pour les vieux dépôts, soit main pour les plus récents.

          Aaaah ! Je comprends et je comprends du coup "mainster".

          Pour les problématiques "multi dépôts". J'avoue ne pas trop avoir le besoin. Tous les dépôts où je travaille sont configurés de manière identique et les autres je les manipule tellement peu que je m'en fou de devoir taper des commandes un peu plus longues.

          Après comme ça s'appuie sur des usages ça s'appuie aussi beaucoup sur tout un tas d'autres configurations git, mais aussi de mon shell qui m'affiche le nom des branches dans les quels je suis dans le prompt.

          Après j'essaie de garder des automatisations plus petites et de m'appuyer massivement sur mon shell (mais je suis entrain de voir pour faire une exception avec un outil qui intéragis avec git, mais aussi les apis de gitlab pour générer pour moi les noms de branches comme je veux).

          C'est pour ça que je préfère garder :

          git ff && git force

          mais c'est une question de goût.

          J'aurais plutôt mis un loginctl suspend :)

          J'éteins toujours mes machines, mais je fais plus "systemctl poweroff" que shutdown maintenant.

          https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

          • [^] # Re: Du gitcode à partager - ou pas

            Posté par  . Évalué à 1.

            J'éteins toujours mes machines, mais je fais plus "systemctl poweroff" que shutdown maintenant.

            Il y a donc une commande pour ça ! Mais alors, à quoi sert le gros bouton à côté de l'alimentation ?

            L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès

    • [^] # Re: Du gitcode à partager - ou pas

      Posté par  . Évalué à 3.

      Si je comprend bien ta fonction gitmaster(), c'est pour synchroniser la branche master/main sur laquelle tu ne travaille pas (bonne pratique importante pour le code suivant) avec upstream.

      Si cela est le cas, tu peux le faire sans faire un checkout (et donc de façon plus pratique):

      # Fetch from upstream
      git fetch upstream
      # get hash of upstream/master
      hash="$(git rev-parse upstream/master)"
      # update 'master' without doing a checkout
      git push . "$hash:refs/heads/master"
      # push to origin
      git push origin master
      • [^] # Re: Du gitcode à partager - ou pas

        Posté par  . Évalué à 3.

        Note: la màj de master echoue si ce n'est pas un fast-forward (et c'est ce qu'on veut)

        • [^] # Re: Du gitcode à partager - ou pas

          Posté par  (Mastodon) . Évalué à 2.

          Ben ça peut aussi être pour démarrer un nouveau développement.
          Je me met sur une master propre et bien mise à jour et de là je crée une branche de travail.
          J'ai indiqué la fonction gitnewbranch plus haut, qui en interne fait en gros git stash && gitmaster && git checkout -b ma_branche && git stash pop.
          Et parfois juste pour voir où en est master, lire le code d'un dépôt sur lequel je ne travaille pas.

          Bon, faut dire, dans mon boulot on a une centaine de repo actif en 2023, sur 170 au total (bigre, tout de même ? je pensais pas avant de regarder, doit y'avoir pas mal de déchets quand même), et je bosse sur quelques-uns, et j'ai de temps en temps à regarder le code de quelques autres, j'en ai 40 clonés à un moment où à un autre, et 22 forkés sur mon gitlub interne, donc pour lesquels j'ai fait au moins une PR à un moment où à un autre.
          À noter que gitmaster fonctionne aussi si on a simplement cloné upstream sans fork perso, ça va râler sur le fetch upstream et le rebase, le push n'aura rien à faire, mais on aura fait notre checkout de master, et sans savoir si on a un fork perso ou pas :)

          Autant dire que la commande « mets-moi ce dépôt localement à jour, sur la branche de base, dans un état synchronisé avec un éventuel fork perso, et prêt pour un nouveau dev » sans poser d'autres questions, elle est bien pratique…

          • Yth.
          • [^] # Re: Du gitcode à partager - ou pas

            Posté par  . Évalué à 3.

            Mon commentaire était pour indiquer qu'on peut détourner la commande 'push' pour modifier/mettre à jour une branche locale sans être obligé de faire un checkout (qui peut être pénible et lent si la branche courante a pas mal divergé) et que cette solution (que peu connaissent), qui peut être adaptée pour gérer ton 2ème cas, est beaucoup plus performante car l'update de la branche est instantané (seul le fetch et push final prennent du temps) et a moins de chance d'échouer (car on a pas à gérer les cas particuliers du checkout --changes local, merge conflicts,… --)

            • [^] # Re: Du gitcode à partager - ou pas

              Posté par  . Évalué à 3.

              on peut détourner la commande 'push' pour modifier/mettre à jour une branche locale sans être obligé de faire un checkout (qui peut être pénible et lent si la branche courante a pas mal divergé)

              J'avoue que je ne connaissais pas. Généralement j'évite les checkout en me référençant à la branche distante du genre :

              git fetch
              git rebase origin/${branch}
              git push --force-with-lease

              J'ai pas trouvé la description du point dans la doc de git push, j'imagine que ça représente le "remote" local ?

              https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

              • [^] # Re: Du gitcode à partager - ou pas

                Posté par  . Évalué à 4.

                'ai pas trouvé la description du point dans la doc de git push, j'imagine que ça représente le "remote" local ?

                Comme remote, on peut donner l'url d'un depot qui peut être un chemin local. Ici, on utilise le répertoire courant '.' comme "remote" et on fait donc un push dans notre propre dépot local pour mettre à jour une ref de branche avec le hash d'un commit.

                • [^] # Re: Du gitcode à partager - ou pas

                  Posté par  . Évalué à 4.

                  Ah oui ! Je vois. C'est super cool.

                  Je viens d'essayer du coup ça marche bien avec des noms plus simples.

                  Au lieu de :

                  # Fetch from upstream
                  git fetch upstream
                  # get hash of upstream/master
                  hash="$(git rev-parse upstream/master)"
                  # update 'master' without doing a checkout
                  git push . "$hash:refs/heads/master"

                  Je peux faire :

                  # Fetch from upstream
                  git fetch upstream
                  # update 'master' without doing a checkout
                  git push . upstream/master:master

                  Merci beaucoup pour l'astuce !

                  https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

    • [^] # Re: Du gitcode à partager - ou pas

      Posté par  (site web personnel, Mastodon) . Évalué à 2.

      Les alias, pour ma part, je fais ça au niveau de Git et non du shell.

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

Suivre le flux des commentaires

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