提问人:johhny tex 提问时间:9/29/2023 更新时间:9/30/2023 访问量:84
尝试执行 git commit 时出现错误“fatal: cannot run .git/hooks/pre-commit: No such file or directory”。预提交文件就在那里
Getting the error "fatal: cannot run .git/hooks/pre-commit: No such file or directory" when trying to execute git commit. The pre-commit file is there
问:
我的情况
我在项目的 .git/hooks 目录中安装了一个预提交钩子。但是,每当我尝试执行提交时,我都会收到一条错误消息,指出预提交文件不存在。该文件肯定存在。如果我删除该文件,提交将再次正常发生,但对于这个项目,我确实需要在提交到存储库之前有一个预提交钩子。git commit -m "whatever"
我的环境
我在Visual Studio Code(VSCode)开发容器中运行。devcontainer 使用 WSL 支持的 (适用于 Linux 的 Windows 子系统) Docker 和从 .python:3.10-slim-bullseye
主机操作系统
OS Name: Microsoft Windows 11 Enterprise
Version: 10.0.22621 Build 22621
VSCode
Version: 1.77.3 (system setup)
Commit: 704ed70d4fd1c6bd6342c436f1ede30d1cff4710
Date: 2023-04-12T09:16:02.548Z
Electron: 19.1.11
Chromium: 102.0.5005.196
Node.js: 16.14.2
V8: 10.2.154.26-electron.0
OS: Windows_NT x64 10.0.22621
Sandboxed: No
开发容器
$ uname -a
Linux 4fb27f5c92e0 5.10.102.1-microsoft-standard-WSL2 #1 SMP Wed Mar 2 00:30:59 UTC 2022 x86_64 GNU/Linux
$ cat /etc/issue
Debian GNU/Linux 11 \n \l
$ git --version
git version 2.30.2
我试过什么
例如,下面是运行命令的输出。提交将失败,并且不会因此错误而发生。git commit
$ git commit -m "arbitrary git commit message"
fatal: cannot run .git/hooks/pre-commit: No such file or directory
我认为可能预提交文件中存在导致问题的问题,所以我将文件剥离到骨头,只运行一个命令。但即使这样也行不通(同样,该文件也肯定存在,所以有这样一个文件或目录,Linux/Git!echo "test"
$ cat .git/hooks/pre-commit
#!/bin/bash
echo "test"
此外,以下是该文件的权限:
-rwxrwxrwx 1 me root 816 Sep 28 17:22 .git/hooks/pre-commit
我在哪里.这不是预提交文件内容的问题,因为预提交文件本身非常简单。据我所知,这是 Git 能够实际读取/执行文件的问题。me
我尝试在谷歌上搜索或查看其他关于预提交钩子遇到此问题的 SO 帖子,但大多数(所有?)这些问题都是预提交钩子代码本身的问题,而不是直接运行预提交钩子。
值得注意的是,pre-commit 在 devcontainer 之外工作
如果我使用我的主机 git 并尝试进行提交,则预提交钩子将运行(尽管它会遇到问题,因为我的主机没有预提交钩子尝试使用的软件,这些东西安装在 devcontainer 中)。这只是 devcontainer 中的一个问题。
我期望发生的事情
我希望我的钩子文件在我执行时执行。pre-commit
git commit
答:
根据的评论,我被要求尝试直接运行脚本,这揭示了问题。phd
$ .git/hooks/pre-commit
zsh: .git/hooks/pre-commit: bad interpreter: /bin/bash^M: no such file or directory
此外,我还被要求提供文件的输出。cat -v
$ cat -v .git/hooks/pre-commit
#!/bin/bash^M
^M
echo "test"^M
这也凸显了问题所在。
问题出在行尾字符上。在 *nix(在本例中为 Linux)中,行尾字符是 或 换行符 (LF) 字符。在 Windows 中,行尾字符是 ,或回车符 (CR) 和换行符 (LF) 字符(通常缩写为 CRLF)。\n
\r\n
为了解决这个问题,我能够使用 VScode 通过单击底部栏上的行结束按钮并将其从 CRLF 更改为 LF 来更改行结束字符。
显示文件现在将 LF 显示为行结束字符的图像,而不是之前显示的 CRLF。
我本可以做到这一点的另一种方法是使用命令行删除那些讨厌的 CR。类似于下面的东西,也许(未经测试)(也要注意,如果脚本中有其他目的,比如不在一行的末尾,它可能会破坏它):\r
cat .git/hooks/pre-commit | tr -d '\r' > .git/hooks/pre-commit.tmp && mv .git/hooks/pre-commit.tmp .git/hooks/pre-commit
评论
cat .git/hooks/pre-commit | … > .git/hooks/pre-commit
我会非常害怕一个文件,同时重定向到它。如果 shell 决定第一次重定向,则文件将被截断为零长度。我的建议是做cat
cat .git/hooks/pre-commit | tr -d '\r' > .git/hooks/pre-commit.tmp && mv .git/hooks/pre-commit.tmp .git/hooks/pre-commit
评论
.git/hooks/pre-commit
cat -v .git/hooks/pre-commit