由于解析器错误,无法将更复杂的脚本添加为 Git 别名
Adding more complex scripts as Git aliases doesn't work due to parser errors
在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
文件中。 None 有效。
我错过了什么?如何修复这些脚本以便我可以将它们添加为别名?
您在脚本中使用了 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 ''"
您可以取消bash您的单行脚本。让我们以这个为例:
latest=$(git describe --abbrev=0 --tags 2>/dev/null)
latest=${latest:-v0.0.0}
components=(${latest//./ })
这是您的第一个 bash-ism:您正在用用空格替换点(然后分解)的值制作一个数组。 Plain 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 可以执行此替换,但我说让 sed 执行它,因为它更明显 and/or 更有效):
set -- $(echo $latest | sed -e s/v// -e "s/\./ /g")
major=
minor=
patch=
回到你原来的代码:
major=$((major+1))
minor=0
patch=0
next='v'$major'.'$minor'.'$patch
git tag -a $next -m ""
这都是有效的 POSIX sh,所以我们完成了这个转换。
在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
文件中。 None 有效。
我错过了什么?如何修复这些脚本以便我可以将它们添加为别名?
您在脚本中使用了 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 ''"
您可以取消bash您的单行脚本。让我们以这个为例:
latest=$(git describe --abbrev=0 --tags 2>/dev/null)
latest=${latest:-v0.0.0}
components=(${latest//./ })
这是您的第一个 bash-ism:您正在用用空格替换点(然后分解)的值制作一个数组。 Plain 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 可以执行此替换,但我说让 sed 执行它,因为它更明显 and/or 更有效):
set -- $(echo $latest | sed -e s/v// -e "s/\./ /g")
major=
minor=
patch=
回到你原来的代码:
major=$((major+1))
minor=0
patch=0
next='v'$major'.'$minor'.'$patch
git tag -a $next -m ""
这都是有效的 POSIX sh,所以我们完成了这个转换。