我们在混合环境中进行开发-有些人在Mac上工作,有些人在Linux上工作。事实证明,有时这是一个挑战,因为那些在Linux上工作的人已经习惯于使他们的文件系统区分大小写,因此提交(偶然或以其他方式)因大小写而不同的多个文件没有问题。 (例如FileName.extfilename.ext)

但是,当Mac上的人们去检阅存储库时,具有不区分大小写的文件系统意味着两个文件(仅大小写不同)会相互覆盖并造成普遍破坏。

我知道有各种git设置可以帮助不区分大小写的文件系统上的人员更好地处理大小写更改(例如core.ignorecase),但是这些不能解决存储库中存在两个不同文件的问题,只是大小写不同。

我认识到,修复该问题的唯一方法是确保Linux人员不会提交仅在大小写不同的两个文件。 -git中是否有某些设置,如果区分大小写的文件系统上的用户尝试提交在不区分大小写的文件系统上会相互混淆的文件,则会 pop 警告或错误提示?

最佳答案

没有内置任何内容(毫无疑问,尽管应该存在)。您可以做的是提供一个预提交钩子(Hook),该钩子(Hook)会验证所有名称是否正确,如果没有,则阻止提交。

该挂钩仅需要在Linux机器上运行(尽管使其在Linux和Mac上运行很容易,但是只有Windows及其默认的贫困工具箱才是有问题的)。您可能需要将其添加到侧边分支,并向Linux人员提供有关设置它的说明。

您可能还需要检查分支名称,如git pre-commit or update hook for stopping commit with branch names having Case Insensitive match一样。 (有趣的是:这个问题的答案是我自己的;我已经忘记了。)

首先,让我们编写一个“检查大小写冲突”功能。这只是一个用大小写折叠排序的问题(以便“helloworld”和“helloWorld”彼此相邻放置),然后使用uniq -di打印任何重复的(在折叠后的)字符串,但不打印非重复的字符串:

sort -f | uniq -di

如果这产生任何输出,则这些是“坏名”。让我们将输出捕获到一个临时文件中并检查其大小,以便我们也可以将它们打印到标准输出中:
#! /bin/sh

TF=$(mktemp)
trap "rm -f $TF" 0 1 2 3 15
checkstdin() {
    sort -f | uniq -di > $TF
    test -s $TF || return 0   # if $TF is empty, we are good
    echo "non-unique (after case folding) names found!" 1>&2
    cat $TF 1>&2
    return 1
}

现在,我们只需要在将要提交的文件上使用它,也许还可以在分支名称上使用它。前者以git ls-files列出,因此:
git ls-files | checkstdin || {
    echo "ERROR - file name collision, stopping commit" 1>&2
    exit 1
}

您可以使用git diff-index --cached -r --name-only --diff-filter=A HEAD仅检查添加的文件,从而允许现有的大小写冲突继续发生,和/或尝试检查多个分支和/或提交中的内容,但这很困难。

将以上两个片段组合成一个脚本(并进行测试),然后将其简单复制到名为.git/hooks/pre-commit的可执行文件中。

检查分支名称有点棘手。这实际上应该在创建分支名称时发生,而不是在您提交分支名称时发生,并且不可能在客户端上做得很好—必须在具有适当全局 View 的集中式服务器上完成。

这是一种在服务器上以预接收脚本,以Shell脚本而不是Python(如链接的答案)那样进行操作的方法。但是,我们仍然需要checkstdin函数,您可能希望在更新挂钩中而不是在预先接收挂钩中进行操作,因为您不需要拒绝整个推送,只需拒绝一个分支名称即可。
NULLSHA=0000000000000000000000000000000000000000 # 40 0s

# Verify that the given branch name $1 is unique,
# even IF we fold all existing branch names' cases.
# To be used on any proposed branch creation (we won't
# look at existing branches).
check_new_branch_name() {
    (echo "$1"; git for-each-ref --format='%(refname:short)' refs/heads) |
      checkstdin || {
        echo "ERROR: new branch name $1 is not unique after case-folding" 1>&2
        exit 1  # or set overall failure status
    }
}

while read oldsha newsha refname; do
    ... any other checks ...
    case $oldsha,$refname in
    $NULLSHA,refs/heads/*) check_new_branch_name ${refname#refs/heads/};;
    esac
    ... continue with any other checks ...
done

07-28 02:21
查看更多