由于解析器错误,添加更复杂的脚本作为Git别名不起作用

时间:2017-07-03 16:49:48

标签: git bash shell ubuntu git-alias

在Git中,为了方便起见,我想添加一些全局别名。

命令

git config --global alias.unstage 'reset HEAD --'

在文档中找到,工作正常。所以我尝试使用相同的语法,在命令前加!来运行外部的,更复杂的脚本:

# release-major
latest=$(git describe --abbrev=0 --tags 2>/dev/null); latest=${latest:-v0.0.0}; components=(${latest//./ }); major=${components[0]}; major=${major//v/}; minor=${components[1]}; patch=${components[2]}; major=$((major+1)); minor=0; patch=0; next='v'$major'.'$minor'.'$patch; git tag -a $next -m ""

# release-minor
latest=$(git describe --abbrev=0 --tags 2>/dev/null); latest=${latest:-v0.0.0}; components=(${latest//./ }); major=${components[0]}; major=${major//v/}; minor=${components[1]}; patch=${components[2]}; minor=$((minor+1)); patch=0; next='v'$major'.'$minor'.'$patch; git tag -a $next -m ""

# release-patch
latest=$(git describe --abbrev=0 --tags 2>/dev/null); latest=${latest:-v0.0.0}; components=(${latest//./ }); major=${components[0]}; major=${major//v/}; minor=${components[1]}; patch=${components[2]}; patch=$((patch+1)); next='v'$major'.'$minor'.'$patch; git tag -a $next -m ""

如果我尝试使用语法

添加这三个脚本
git config --global alias.my-alias-name '!my-alias-code'
但是,它不起作用。结果始终是解析器错误。

我试过了我能想象的引用,不引用,单引号和双引号的各种变体。我甚至尝试将这些文件直接添加到.gitconfig文件中。这些都不起作用。

我错过了什么?如何修复这些脚本以便我可以将它们添加为别名?

2 个答案:

答案 0 :(得分:4)

您可以对单行脚本进行解除冲突。我们来看看这个例子:

latest=$(git describe --abbrev=0 --tags 2>/dev/null)
latest=${latest:-v0.0.0}
components=(${latest//./ })

这是你的第一个bash-ism:你正在用数字替换空格(然后分解)来制作一个数组。普通shell没有数组;相反,我们使用位置参数,使用$IFS将其与set分开。为了保持干净,我们需要在函数中使用它(每个函数都有自己的私有位置),但是如果所有位置参数都已经被捕获到局部变量中,我们可以覆盖它们:

set -- $(echo $latest | sed "s/\./ /g")

(回到你的代码)

major=${components[0]}
major=${major//v/}
minor=${components[1]}
patch=${components[2]}

现在我们在这里使用$ 1,$ 2和$ 3。我们不妨将v替换移到上面的sed中(POSIX sh可以做这个替换,但我说让我们让它做,因为它更明显和/或更有效率):

set -- $(echo $latest | sed -e s/v// -e "s/\./ /g")
major=$1
minor=$2
patch=$3

返回原始代码:

major=$((major+1))
minor=0
patch=0
next='v'$major'.'$minor'.'$patch
git tag -a $next -m ""

这是所有有效的POSIX sh,所以我们完成了这次转换。

答案 1 :(得分:1)

您在脚本中使用特定于bash的语法(例如$(( ))用于算术)。但是,默认情况下,!执行以/bin/sh开头的git别名。由于/bin/sh只是一个简单的POSIX shell,因此它的语法中没有任何这些功能。

幸运的是,这很容易解决。只需将#!/bin/bash添加到脚本的开头即可。 (如果它是一个单独的文件。)

如果您使用这些内联,那么您可能需要直接调用bash。这可能是一个令人头疼的问题,但你的例子看起来并不像是一个大问题。我想这可能会这样做:

# release-major
bash -c "latest=$(git describe --abbrev=0 --tags 2>/dev/null); latest=${latest:-v0.0.0}; components=(${latest//./ }); major=${components[0]}; major=${major//v/}; minor=${components[1]}; patch=${components[2]}; major=$((major+1)); minor=0; patch=0; next='v'$major'.'$minor'.'$patch; git tag -a $next -m ''"

# release-minor
bash -c "latest=$(git describe --abbrev=0 --tags 2>/dev/null); latest=${latest:-v0.0.0}; components=(${latest//./ }); major=${components[0]}; major=${major//v/}; minor=${components[1]}; patch=${components[2]}; minor=$((minor+1)); patch=0; next='v'$major'.'$minor'.'$patch; git tag -a $next -m ''"

# release-patch
bash -c "latest=$(git describe --abbrev=0 --tags 2>/dev/null); latest=${latest:-v0.0.0}; components=(${latest//./ }); major=${components[0]}; major=${major//v/}; minor=${components[1]}; patch=${components[2]}; patch=$((patch+1)); next='v'$major'.'$minor'.'$patch; git tag -a $next -m ''"