防止在 git 中提交带有平台特定非法字符的文件名
Prevent committing filenames with platform-specific illegal characters in git
我们经常遇到用户意外提交名称中包含平台特定非法字符的文件的问题。例如。 Mac OS X 上的用户正在提交名称为 file-name?xyz
的文件,这会在 Windows 平台上造成问题,这些平台显然总是将 ?
字符视为通配符。
这会导致各个客户端出现混乱,我们目前总是需要在最初完成提交的平台上修复名称(例如,将 file-name?xyz
重命名为 file-name-xyz
)。
是否有任何机制可以完全防止 committing/pushing 有问题的文件名? (直接通过 git,或通过 Bitbucket 服务器)
我认为最好的选择是创建一个个性化的挂钩:https://git-scm.com/docs/githooks
你可以通过做一个钩子来做到这一点,就像 pedro suggets。
下面是我制作的 precommit
挂钩。它基于包含在 Git For Windows 中的示例(或 Sourcetree 或 Bitbucket,我不确定它来自哪里)。
将以下内容放在项目根目录 .git/hooks/
内名为 precommit
的文件中:
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=$(git hash-object -t tree /dev/null)
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ !#-)+-9;=@-[]-{}~][=10=]' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --
我更改的地方是:
LC_ALL=C tr -d '[ !#-)+-.0-9;=@-[]-{}~][=11=]' | wc -c) != 0
曾经说过:
LC_ALL=C tr -d '[ -~][=12=]' | wc -c) != 0
原文删除了所有文件名中的所有ascii字符,并检查是否没有剩余字符(它们都是ascii字符)。如果还有剩余,它们是 non-ascii 个字符,它会出错并停止提交。
我的更改只是意味着它不会删除字符 \/:*?">?|
并且如果不为空则出错。也就是说,如果有 non-ascii 个字符,或任何这些字符,它将不允许提交。
如果直接使用该文件,您可能需要更改文件中的注释以解释新功能。
编辑: 脚本中存在错误。如果它在文件中找到 /
,它会阻止提交,但由于它正在查看完整路径,如果您尝试提交不在 Mac 或 Unix 根目录中的任何内容,这将中断。我已经更新了下面的代码,所以应该可以正常工作。
我们经常遇到用户意外提交名称中包含平台特定非法字符的文件的问题。例如。 Mac OS X 上的用户正在提交名称为 file-name?xyz
的文件,这会在 Windows 平台上造成问题,这些平台显然总是将 ?
字符视为通配符。
这会导致各个客户端出现混乱,我们目前总是需要在最初完成提交的平台上修复名称(例如,将 file-name?xyz
重命名为 file-name-xyz
)。
是否有任何机制可以完全防止 committing/pushing 有问题的文件名? (直接通过 git,或通过 Bitbucket 服务器)
我认为最好的选择是创建一个个性化的挂钩:https://git-scm.com/docs/githooks
你可以通过做一个钩子来做到这一点,就像 pedro suggets。
下面是我制作的 precommit
挂钩。它基于包含在 Git For Windows 中的示例(或 Sourcetree 或 Bitbucket,我不确定它来自哪里)。
将以下内容放在项目根目录 .git/hooks/
内名为 precommit
的文件中:
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=$(git hash-object -t tree /dev/null)
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ !#-)+-9;=@-[]-{}~][=10=]' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --
我更改的地方是:
LC_ALL=C tr -d '[ !#-)+-.0-9;=@-[]-{}~][=11=]' | wc -c) != 0
曾经说过:
LC_ALL=C tr -d '[ -~][=12=]' | wc -c) != 0
原文删除了所有文件名中的所有ascii字符,并检查是否没有剩余字符(它们都是ascii字符)。如果还有剩余,它们是 non-ascii 个字符,它会出错并停止提交。
我的更改只是意味着它不会删除字符 \/:*?">?|
并且如果不为空则出错。也就是说,如果有 non-ascii 个字符,或任何这些字符,它将不允许提交。
如果直接使用该文件,您可能需要更改文件中的注释以解释新功能。
编辑: 脚本中存在错误。如果它在文件中找到 /
,它会阻止提交,但由于它正在查看完整路径,如果您尝试提交不在 Mac 或 Unix 根目录中的任何内容,这将中断。我已经更新了下面的代码,所以应该可以正常工作。