Git别名导致“权限被拒绝”错误

19
以下命令
$ git co -b newbranch
$ git co oldbranch

在执行git-co时,可能会出现“fatal: cannot exec 'git-co': Permission denied”错误。

同时,

$ git checkout -b newbranch
$ git checkout oldbranch

$ sudo git co -b newbranch
$ sudo git co oldbranch

按预期工作。.git文件夹的所有权设置为拥有家庭文件夹的用户,.git文件夹/子文件夹/文件的模式为0755/0644。系统中没有任何git-co脚本(这是一个可扩展的别名,指向位于/usr/libexec/git-core目录下的git-checkout)。

别名在家目录的.gitconfig文件中定义:

[alias]
co = checkout

对于 root 用户和非特权用户,git config -l 的输出没有区别。但是 sudo git co oldbranch 可以工作,而 git co oldbranch 则不行。

我错过了什么?

Gentoo / 内核 3.0.6 / git 1.7.3.4


请附上 git config --get-regexp '^alias\.' 的输出结果。 - manojlds
@AlexeiDanchenkov:嗯...不是说废话,但“别名在哪里”(我们看不到它们)。 - sehe
1
在你的git安装目录中查找;我不知道gentoo,但它可能是/usr/libexec/git-core/usr/lib/git-core或其中一个,将/usr更改为/usr/local。您应该看到一堆可执行文件,用于所有git命令。看看那里是否还有一个git-co,它可以由root执行,但不能由您执行。如果这个git-co文件不在git安装目录中,它也可能在您的PATH中定位。如果不在git安装目录中,也可以使用sudo which git-co来定位它。 - Cascabel
@mahojlds alias.co checkout - Alexei Danchenkov
@Jefromi 不,情况并非如此。系统中没有名为 git-co 的文件。sudo which git-co 通过 which: no git-co in (...) 进行了确认。 - Alexei Danchenkov
显示剩余3条评论
3个回答

25

实际上,正确的答案是不同的。在 git 运行别名之前,它会检查$PATH。如果目录不存在或缺少权限,则 git 会产生"fatal: cannot exec 'git-co': Permission denied"错误。它永远不会检查别名,因此git foobar将产生相同的错误。

来自 git 邮件列表的好心人还提醒我一个strace工具,可以帮助找到返回 EACCES 的入口,例如:strace -f -e execve git foobar

感谢来自 git 邮件列表的 Jeff King。:)


7
我使用 Gentoo 操作系统,带有 git 版本 1.7.3.4,并且在 /usr/games/bin 目录中没有公共执行权限,这导致了我的问题。由于该目录在我的 PATH 环境变量中,Git 无法找到路径中一个目录的适当权限,因此为别名生成了此错误。只需运行 chmod +x /usr/games/bin 命令,即可轻松解决此问题。我使用以下一行命令快速查看 PATH 权限:echo $PATH |tr ':' '\n' |xargs ls -ld - SleighBoy
很好!很高兴你找到了正确的答案。确实,将没有执行权限的目录添加到PATH中会导致使用非内置命令运行git时出现“fatal: cannot exec 'git-hist': Permission denied”错误。我正在使用Git版本1.7.8;希望很快就会有修复。 - Go Dan
2
或者更好的方法是:strace -f -e execve git foobar 2>&1 | grep -i denied - sivann
正是我的问题。我的PATH预设了数十个目录(其中只有少数是错误的),这些目录来自于我无法控制的/etc脚本(例如,远程存储不总是可用)。为了快速将路径重置为有效目录:PATH=$(for d in ${PATH//:/ } ; do [ -x $d ] && printf "$d\n"; done | uniq | tr '\12' ':') (并且要删除尾随的“:”,请使用 PATH=${PATH%?} - michael
当你说一个返回“EACCES”的条目时,你的意思是什么? - camdixon
例如,检查这个系统错误列表:http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html。最初的问题是关于文件访问错误,本来不应该存在的。@camdixon - Alexei Danchenkov

8

你是否不小心在某个地方创建了一个非可执行的 git-co 文件?如果我这样做,就可以重新创建你的情况,如下所示。

$ git --version
git version 1.7.7.1.475.g997a1
$ git config --get-regexp '^alias\.co$'
alias.co checkout
$ git co b1
Switched to branch 'b1'
$ touch $HOME/bin/git-co
$ ls -al $HOME/bin/git-co
-rw-r--r-- 1 user user 0 2011-11-03 12:59 /home/user/bin/git-co
$ git co master
fatal: cannot exec 'git-co': Permission denied
$ for p in $(echo "$PATH" | sed -e 's/:/ /g'); do if [ -f "${p}/git-co" ]; then echo "Found git-co in ${p}"; fi; done
Found git-co in /home/user/bin
$ rm $HOME/bin/git-co
rm: remove regular empty file `/home/user/bin/git-co'? y
$ git co master
Switched to branch 'master'

您可能想尝试的另一件事是启用跟踪日志以获取有关Git正在执行的操作的更多信息。以下是一个示例:
GIT_TRACE=$HOME/trace.log git co master

如果你想将输出发送到文件中,必须使用绝对路径。否则,请使用true1将输出发送到标准错误;例如:GIT_TRACE=1trace.log文件包含:

trace: exec: 'git-co' 'master'
trace: run_command: 'git-co' 'master'
trace: alias expansion: co => 'checkout'
trace: built-in: git 'checkout' 'master'

如果您没有看到trace: alias expansion: co=> 'checkout'的跟踪日志输出,那么Git会在PATH环境变量中寻找git-co文件。Git使用以下方法来查找PATH
  1. 从空的PATH开始,保存任何“旧”的PATH以供参考。
  2. 如果发现--exec-path=<my git commands path> Git选项,则将<my git commands path>附加到PATH
  3. 如果未找到--exec-path=<my git commands path>并且已设置GIT_EXEC_PATH环境变量,则将其附加到PATH
  4. 如果您使用相对路径或绝对路径调用git,则将git可执行文件的绝对路径附加到PATH
  5. 如果之前定义了PATH,则将其附加到PATH
  6. 如果之前未定义PATH,则将/usr/local/bin:/usr/bin:/bin附加到PATH
您可以使用另一个别名来让Git告诉您它正在将PATH环境变量设置为什么。
$ git config --global alias.whatpath '!echo $PATH'
$ git whatpath
/usr/local/libexec/git-core:/home/user/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

然后检查每个目录是否存在一个名为git-co的文件。仅仅执行which git-co命令并假设如果没有找到就表示你在Git的PATH目录中没有git-co文件是不够的;可能存在一个不可执行的文件,而which命令将不会显示它。


这并不是事实。我已经检查过了,但是没有... 你示例中的for循环没有返回任何内容。 - Alexei Danchenkov
你也可以在 git --exec-path 显示的目录中检查 git-co 文件。同时,使用 find / -name git-co 命令来检查整个系统(显然,要小心使用)。 - Go Dan
谢谢,丹。有一个具有适当权限的/usr/libexec/git-core/git-checkout文件,但是没有找到任何git-co。我的假设是别名不起作用。但是对于root用户来说是有效的...变得绝望了。 - Alexei Danchenkov
丹,那已经很接近了,trace.log在第3步(别名扩展)停止,即对于非特权用户,trace: alias expansion: co => 'checkout'从未出现。但是对于root用户,它确实存在。无论哪种情况,traceSetup.log都从未出现。 - Alexei Danchenkov

1

检查您是否对git别名具有执行权限。 为我解决了这个问题的是提供执行权限。

我下载了"git-credential-osxkeychain"并将其添加到/usr/local/bin,并提供了执行权限,可以无任何问题地运行该命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接