Utiliser git submodule foreach avec fonction

10

Mon intention est d'avoir un script qui met à jour tous les sous-modules git selon la branche donnée. S'il n'y a pas une telle branche pour un sous-module, master est utilisé.

Voici ce que j'ai maintenant:

#!/bin/bash -x

if [ -z $1 ]; then
    echo "Branch name required."
    exit
fi

function pbranch {
    exists=`git show-ref refs/heads/$branch`

    if [ -z $exists ]; then
        branch="master"
    fi

    git co $branch
    git pull origin $branch
}

branch=$1

git submodule foreach pbranch

Mais lors de l'exécution de ce script, l'erreur est levée:

oleq@pc ~/project> git-fetchmodules major
+ '[' -z major ']'
+ branch=major
+ git submodule foreach pbranch
Entering 'submodule'
/usr/lib/git-core/git-submodule: 1: eval: pbranch: not found
Stopping at 'submodule'; script returned non-zero status.

Je suppose que git submodule foreachutilise eval (selon la documentation ), que je n'utilise pas correctement dans ce contexte.

Il existe des milliards d' exemples sur la façon d'utiliser cette commande avec le "rappel en ligne", mais je n'ai pas trouvé un seul avec le rappel sous la forme de la fonction. Aucune idée sur la façon de résoudre ça?

oleq
la source

Réponses:

7

J'ai résolu mon problème en mettant la fonction à l'intérieur des guillemets comme rappel:

#!/bin/bash

if [ -z $1 ]; then
    echo "Branch name required."
    exit
fi

git submodule foreach "
    branch=$1;
    exists=\$(git show-ref refs/heads/\$branch | cut -d ' ' -f1);

    if [ -z \$exists ]; then
        branch='master';
    fi;

    echo Checking branch \$branch for submodule \$name.;

    git fetch --all -p;
    git co \$branch;
    git reset --hard origin/\$branch;
"

Notez que les variables comme $1sont celles de l'espace de noms du script. Les "échappés" comme $\(bar), \$branchsont évalués dans "le rappel". C'était assez facile.

oleq
la source
7

Vous pouvez utiliser des fonctions, mais vous devez d'abord les exporter:

export -f pbranch

De plus, si vous voulez des extensions de syntaxe bash, vous pouvez forcer le démarrage d'un shell bash:

git submodule foreach bash -c 'pbranch'
nschum
la source
5

Une fonction shell n'existe qu'à l'intérieur du shell où elle est définie. De même, une méthode Java n'existe que dans l'instance de programme où elle est définie, etc. Vous ne pouvez pas appeler une fonction shell à partir d'un autre programme, même si ce programme se trouve être un autre shell exécuté par un processus enfant du shell d'origine.

Au lieu de définir une fonction, créez pbranchun script séparé. Mettez-le dans votre CHEMIN.

#!/bin/sh
branch="$1"
ref="$(git show-ref "refs/heads/$branch")"
if [ -z "$ref" ]; then
    branch="master"
fi
git co "$branch"
git pull origin "$branch"

Note de programmation Shell: toujours mettre des guillemets doubles autour de substitutions variables et substitutions de commandes: "$foo", "$(foo)", sauf si vous savez que vous devez laisser les citations sur. Les substitutions non protégées sont interprétées comme des listes de motifs glob séparés par des espaces, ce qui n'est presque jamais souhaité. Aussi, n'utilisez pas de backticks, pour des raisons similaires, utilisez $(…)plutôt. Ici, cela n'a pas vraiment d'importance parce que les noms de branche git ne contiennent pas de caractères spéciaux, et parce que [ -z $branch ]est analysé comme [ -z ]ce qui est également vrai lorsqu'il branchest vide. Mais ne prenez pas l'habitude d'omettre les citations, cela reviendra et vous mordra.

Disons que le script est appelé pbranch-submodule, vous pouvez ensuite exécuter

git submodule foreach pbranch-submodule
Gilles 'SO- arrête d'être méchant'
la source
Et si vous le nommez git-pbranch-submodule, il peut se comporter comme une commande git intégrée: git pbranch-submoduleou git submodule foreach git pbranch-submodule. (Notez que foreach accepte une commande shell et non une commande git.)
idbrii