Use git submodule foreach con función

10

Mi intención es tener un script que actualice todos los submódulos git de acuerdo con qué rama se proporciona. Si no hay tal rama para un submódulo, se usa master.

Esto es lo que tengo ahora:

#!/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

Pero cuando se ejecuta este script, se produce el error:

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.

Supongo que git submodule foreachutiliza eval (según la documentación ), que no uso correctamente en este contexto.

Hay miles de millones de ejemplos de cómo usar este comando con "devolución de llamada en línea", pero no pude encontrar uno solo con la devolución de llamada en forma de la función. Alguna idea de como resolver esto?

oleq
fuente

Respuestas:

7

Resolví mi problema poniendo la función dentro de las comillas como devolución de llamada:

#!/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;
"

Tenga en cuenta que las variables como $1son las del espacio de nombres del script. Los "escapados" como $\(bar), \$branchse evalúan dentro de "la devolución de llamada". Fue muy facil.

oleq
fuente
7

Puede usar funciones, pero primero debe exportarlas:

export -f pbranch

Además, si desea extensiones de sintaxis bash, es posible que desee forzar el inicio de un shell bash:

git submodule foreach bash -c 'pbranch'
nschum
fuente
5

Una función de shell solo existe dentro del shell donde se define. Del mismo modo, un método Java solo existe en la instancia del programa donde está definido, y así sucesivamente. No puede invocar una función de shell desde otro programa, incluso si ese programa es otro shell que es ejecutado por un proceso secundario del shell original.

En lugar de definir una función, cree pbranchun script por separado. Ponlo en tu RUTA.

#!/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"

Shell nota de programación: Siempre ponga comillas dobles sustituciones de variables y sustituciones de comando: "$foo", "$(foo)", a menos que sepa que tiene que salir de las cotizaciones a cabo. Las sustituciones no protegidas se interpretan como listas separadas por espacios en blanco de patrones globales, lo que casi nunca se desea. Además, no use backticks, por razones similares, use $(…)en su lugar. Aquí, en realidad no importa porque los nombres de rama de git no contienen caracteres especiales, y porque [ -z $branch ]se analiza como lo [ -z ]que también es cierto cuando branchestá vacío. Pero no se acostumbre a omitir las citas, volverá y lo morderá.

Digamos que el script se llama pbranch-submodule, luego puede ejecutar

git submodule foreach pbranch-submodule
Gilles 'SO- deja de ser malvado'
fuente
Y si lo nombra git-pbranch-submodule, puede comportarse como un comando git incorporado: git pbranch-submoduleo git submodule foreach git pbranch-submodule. (Tenga en cuenta que foreach acepta un comando de shell y no un comando git.)
idbrii