1

在 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文件中。这些都不起作用。

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

4

2 回答 2

4

您可以对单行脚本进行反bash 化。让我们看一下这个例子:

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

这是您的第一个 bash 主义:您正在从值中创建一个数组,用空格替换点(然后分解)。普通外壳没有数组;相反,我们使用位置参数,将它们分解为$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 可以做这个替换,但我说让 sed 做它,因为它更明显和/或更有效):

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,所以我们完成了这个转换。

于 2017-07-03T17:28:53.153 回答
1

您在脚本中使用了特定于 bash 的语法(例如$(( ))用于算术)。但是,默认情况下!会执行以开头的 git 别名。/bin/sh由于/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 ''"
于 2017-07-03T16:58:39.940 回答