我的目标是编写一个脚本,根据给定的分支更新所有 git 子模块。如果某个子模块没有这样的分支,则使用 master。
这就是我现在所拥有的:
#!/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
但是当运行这个脚本时,会抛出错误:
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.
我的猜测是git submodule foreach
利用 eval (根据文档),在这种情况下我没有正确使用它。
有数十亿个例子如何将此命令与“内联回调”一起使用,但我找不到一个具有函数形式回调的命令。知道如何解决这个问题吗?
答案1
我通过将函数作为回调放在引号内解决了我的问题:
#!/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;
"
请注意,类似的变量$1
来自脚本的命名空间。像$\(bar)
,这样的“逃逸的”\$branch
在“回调”中进行评估。这很容易。
答案2
您可以使用函数,但需要先导出它们:
export -f pbranch
另外,如果您想要 bash 语法扩展,您可能需要强制启动 bash shell:
git submodule foreach bash -c 'pbranch'
答案3
shell 函数仅存在于定义它的 shell 内部。同样,Java 方法仅存在于定义它的程序实例中,依此类推。您不能从另一个程序调用 shell 函数,即使该程序恰好是由原始 shell 的子进程运行的另一个 shell。
不要定义函数,而是创建pbranch
一个单独的脚本。将其放入您的路径中。
#!/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 编程注意事项:始终在变量替换和命令替换周围加上双引号:"$foo"
, "$(foo)"
,除非您知道需要省略引号。不受保护的替换被解释为以空格分隔的全局模式列表,这几乎是不需要的。另外,不要使用反引号,出于类似的原因,请使用反引号$(…)
。在这里,这实际上并不重要,因为 git 分支名称不包含特殊字符,并且因为[ -z $branch ]
被解析为为空[ -z ]
时也为 true 。branch
但不要养成省略引号的习惯,它会反过来咬你。
假设脚本被调用pbranch-submodule
,然后你可以运行
git submodule foreach pbranch-submodule