如何防止 git 提交两个名称仅大小写不同的文件?

2024-01-12

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

然而,当 Mac 上的人们去检查存储库时,拥有不区分大小写的文件系统意味着这两个文件(仅大小写不同)会相互覆盖并造成严重破坏。

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

我意识到解决这个问题的唯一方法是确保 Linux 人员不会提交仅在情况下有所不同的两个文件。 -- 如果区分大小写的文件系统上的用户尝试提交在不区分大小写的文件系统上会相互混淆的文件,git 中是否有一些设置会弹出警告或错误?


没有内置任何东西(尽管毫无疑问应该有)。您可以做的是提供一个预提交挂钩,用于验证所有名称是否正常,如果不正常则阻止提交。

这个钩子只需要在 Linux 机器上运行(虽然让它在 Linux 和 Mac 上工作很容易,但只有 Windows 及其默认的贫乏工具箱才有问题)。您可能想将其添加到侧分支并向 Linux 人员提供有关设置它的说明。

您可能想检查分支names以及,如在git 预提交或更新挂钩,用于停止具有不区分大小写匹配的分支名称的提交 https://stackoverflow.com/q/35658887/1256452。 (有趣的是:这个问题的答案是我自己的;我忘了。)

首先,让我们编写一个“检查大小写冲突”函数。这只是使用大小写折叠进行排序的问题(以便“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, so:

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仅检查added文件,允许现有的案例冲突继续,和/或尝试跨多个分支和/或提交检查内容,但这变得很困难。

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

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

这是一种在服务器上使用预接收脚本、shell 脚本而不是 Python 执行此操作的方法(如链接的答案中所示)。我们仍然需要checkstdin不过,您可能希望在更新挂钩而不是预接收挂钩中执行此操作,因为您不需要拒绝entirePush,只是一个分支名称。

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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止 git 提交两个名称仅大小写不同的文件? 的相关文章

  • git reword 在变基期间显示合并冲突,但是 pick 工作正常

    我正在尝试用很少提交的另一个分支来重新建立一个分支 虽然提交包括合并提交 但我可以使用以下命令成功地对其进行变基git rebase i r m
  • 原始文件被分成另外两个文件,git 有没有办法查看内容去了哪里?

    我的问题 我是一名代码审查员 我在GIT中有一个情况 before a txt 然后开发人员决定拆分内容a txt分成 2 个文件 并在一次提交中添加一些更改 after b txt 很少的变化和c txt 一些变化 有没有简单的方法可以看
  • 如何从 git 存储库中删除作者?

    如果我创建一个 Git 存储库并公开发布它 例如在 GitHub 等上 并且我收到存储库贡献者的请求 无论出于何种原因删除或隐藏他们的名字 有没有一种方法可以轻松做到这一点 基本上 我有这样的请求 可能想将他们的姓名和电子邮件地址替换为 匿
  • 如何确定两个文件路径(或文件 URL)是否标识 macOS 上的同一文件或目录?

    想象一下 macOS 上两个路径的简单示例 etc hosts private etc hosts 两者都指向同一个文件 但你如何确定这一点呢 另一个例子 Desktop Users yourname Desktop 或者在不区分大小写的文
  • 如何正确设置 Azure DevOps 和 GitHub 之间的双向同步

    我想通过执行以下操作在 Azure DevOps 和 GitHub 之间创建双向同步 使用 CI 触发器创建 Azure DevOps 管道 将更改从 Azure DevOps 存储库推送到 GitHub 中的分支 创建第二个管道 用于侦听
  • 无论我做什么,我都无法推送我的代码并不断收到相同的错误

    我正在尝试将代码推送到远程分支 但不断收到此错误 rejected non fast forward error failed to push some refs to email protected cdn cgi l email pro
  • OSX 和 SED - 删除文档目录中第 25 行之后的所有行

    我有一个包含数千个 txt 文件的目录 我需要修剪文件 以便删除每个文件中第 25 行之后的每一行 我使用的是 Mac OSX 10 14 6 我怎样才能做到这一点 我所做的尝试 经过研究 我认为 Mac OSX 终端中的 SED 是实现此
  • SIGHUP 用于重新加载配置

    根据signal 7 SIGHUP用于检测控制终端的挂起或控制进程的死亡 然而 我遇到过很多 OSS 守护进程 服务 其中SIGHUP用于启动配置的重新加载 这里有一些例子 hostapd sshd snort etc 这是实现重新加载的标
  • 尝试在 Mac Snow Leopard 上安装 PyCurl 时出现问题

    我的应用程序需要使用 PyCurl 因此我尝试将其安装在我的 Mac 上 但发现了很多问题和错误 要求 首先我必须说我的Mac上运行的Python版本是基于32位的 因为我需要使用WxPython 这需要32位Python 为此 我使用了
  • NSCollectionview didSelectItemsAt 没有被第二次调用

    我正在开发 mac os 应用程序 我使用 NSCollectionview 在某些时候我需要获取特定索引的数据 我已经实现了 didSelectItemsAt 委托方法 现在的问题是 当我第一次单击单元格时 它将执行 didSelectI
  • 自给定提交以来 git 中的作者列表

    我想要一种列出所有 git 作者的方法 仅自给定提交以来 是独特的 这两个很简单 我在网上看到过一些解决方案 大多数使用git log format 但我看到的都不符合附加要求 按提交日期排序 因此 如果约翰 史密斯 John Smith
  • 切换到工作区并在 Xcode 中添加 CocoaPods 后提交 git 吗?

    我刚刚在 Xcode 5 中将 CocoaPods 添加到我当前的项目中 当然 CocoaPods 创建了一个工作区 并且我已在 Xcode 中启动了该工作区 我在工作区中看到了我的项目和 Pods 项目 我的项目从第一天起就处于源代码控制
  • 防止在 Git 中签出

    我目前正在研究使用 Git 管理 OpenInsight 应用程序的源代码 由于 OI 代码存储在数据库表中 因此需要进行一定量的手动工作才能将源代码导出为文本 反之亦然 到目前为止 我已经成功地使用 Git 挂钩自动化了很多这项工作 但是
  • 设置 Vim 背景颜色

    当我尝试更改背景颜色时 vimrc或者直接在 Vim 中使用以下命令 set background dark 这根本不影响我的背景 也没有light选项 不过 当我运行 gvim 时 看起来还不错 有没有办法在不更改 Konsole 设置的
  • LaunchAgent 不运行 shell 脚本

    在 Catalina 之前的 macOS 下 我有一个每天运行 shell 脚本的 LaunchAgent 升级并切换到 zsh 后 它不起作用 我检查过的事情 shebang 切换到 zsh shell脚本可以从命令行手动执行 sh 在系
  • Git 查找第一个非本地提交

    有关的 列出尚未推送到源的 Git 提交 https stackoverflow com questions 3080509 list git commits not pushed to the origin yet git rev par
  • NSMenuItem、自定义视图和 mouseUp 的奇怪问题:

    我在这里遇到了一个非常非常奇怪的 NSMenu 问题 我使用的大约一半的 NSMenuItems 通过 NSMenuItem 上的 setView 方法具有自定义视图 在此自定义视图中 我实现了 mouseUp 来捕获用户单击菜单项的时间
  • 在Linux中创建可执行文件

    我计划做的一件事是编写 非常简单的 Perl 脚本 并且我希望能够在不从终端显式调用 Perl 的情况下运行它们 我明白 要做到这一点 我需要授予他们执行权限 使用 chmod 执行此操作非常简单 但它似乎也是一个稍微费力的额外步骤 我想要
  • Visual Studio 2017/2019/2022 gitsync/pull/push/fetch 操作卡住,并且无法停止

    我从 Visual Studio 中的 Git Changes 选项卡启动同步 获取 拉取或推送 但操作只是挂起 没有选项可以停止它 我必须点击 X 才能关闭 Visual Studio 如果操作是同步的 它会在其他所有操作上打开一个模式对
  • ARM 的内核 Oops 页面错误错误代码

    Oops 之后的错误代码给出了有关 ARM EX 中的恐慌的信息 Oops 17 1 PREEMPT SMP在这种情况下 17 给出了信息 在 x86 中它代表 bit 0 0 no page found 1 protection faul

随机推荐