git over sshfs(带有 idmap):无法附加到“.git/logs/HEAD”:权限被拒绝

git over sshfs(带有 idmap):无法附加到“.git/logs/HEAD”:权限被拒绝

问题:

我有一个通过 sshfs 安装的 git 存储库,无法提交更改,并显示以下错误消息:

fatal: cannot update the ref 'HEAD': unable to append to '.git/logs/HEAD': Permission denied

请注意,我可以

cp -a .git/logs/HEAD .git/logs/HEAD.bu
printf foo > .git/logs/HEAD
mv .git/logs/HEAD.bu .git/logs/HEAD

没有问题,但是

printf foo >> .git/logs/HEAD

也给了我“权限被拒绝”。

问题:

我需要对配置进行哪些更改才能从本地计算机提交到远程存储库?

我尝试过的:

鉴于上述症状,我认为问题在于附加到文件。我发现SSHFS 上的 Git 存储库:无法附加到“.git/logs/HEAD”:参数无效这是指https://github.com/libfuse/sshfs/issues/82建议问题(注意略有不同的错误消息)可以通过使用writeback_cache=no.后一个来源引用了引用man以下警告/解决方法的页面:

CAVEATS / WORKAROUNDS
[...]
   O_APPEND
       When  writeback  caching is enabled, SSHFS cannot reliably support the O_APPEND open
       flag and thus signals an error on open.  To enable support for  unreliable  O_APPEND
       (which  may  overwrite  data if the file changes on the server at a bad time), mount
       the file system with -o unreliable_append.

但是,此部分不在我的手册页中:

sshfs -V
SSHFS version 3.7.0
FUSE library version 3.9.1
using FUSE kernel interface version 7.31
fusermount3 version: 3.9.1

我发现我尝试禁用的写回缓存功能,实际上已被删除(之后被残疾人重新启用 不止一次前)。所以我想我应该很好,但显然(仍然)存在问题。

我可能应该提到的另一个复杂问题是,我在远程系统上的用户名和 ID 与本地系统上的用户名和 ID 不匹配,因此我需要使用该idmap功能。

这是相应的fstab条目:

<remote-user>@<remote-machine>: /mnt/ssh/<remote-machine>  sshfs  _netdev,user,idmap=user,allow_other  0 0

另外,我的/etc/fuse.conf包含

user_allow_other

背景:

为了避免回答,只是告诉我不要这样做:

  • 我知道 git 是如何工作的。
  • 我知道我可以在本地克隆存储库,在那里提交,然后通过 ssh 推送到远程存储库。

为什么我不做呢? - 因为我跟踪只能在远程计算机上测试的代码,并且我确实想在提交之前对其进行测试。因此,在某种程度上,这“只是”一个方便问题,以避免:

  1. 在本地副本上编辑代码。
  2. 将更改提交到本地副本。
  3. 推送到远程副本。
  4. 通过 SSH 连接到远程计算机(或切换终端)。
  5. 在远程机器上测试代码。
  6. 签出另一个分支(以允许强制推送)。
  7. 结束 SSH 会话(或切换[返回]终端)。
  8. 编辑代码。
  9. 修改本地副本上的先前提交。
  10. 强制推送到远程副本。
  11. 通过 SSH 连接到远程计算机(或切换终端)。
  12. 检查强制推送的分支。
  13. 重复步骤 5 - 11(七个步骤!),直到我满意为止。

相反,我想:

  1. 通过 SSH 连接到远程计算机(或切换终端)。
  2. 从远程计算机上编辑远程副本上的代码。
  3. 在远程机器上测试代码。
  4. 从远程计算机上编辑远程副本上的代码。
  5. 重复步骤 3 - 4(两步!),直到我满意为止。
  6. 结束 SSH 会话(或切换[返回]终端)。
  7. 从本地机器将更改提交到远程副本。

为什么我不直接从远程机器提交? - 因为我想签署我的提交,但无法将私钥委托给远程计算机。所以我能想到的最好的选择是:

  1. 通过 SSH 连接到远程计算机(或切换终端)。
  2. 从远程计算机上编辑远程副本上的代码。
  3. 在远程机器上测试代码。
  4. 从远程计算机上编辑远程副本上的代码。
  5. 重复步骤 3 - 4(两步!),直到我满意为止。
  6. 从远程计算机提交对远程副本的更改。
  7. 签出另一个分支(以允许强制推送)。
  8. 结束 SSH 会话(或切换[返回]终端)。
  9. 从远程副本中拉取。
  10. 修改(签署)本地副本上的先前提交。
  11. 强制推送到远程副本。
  12. 通过 SSH 连接到远程计算机(或切换终端)。
  13. 检查强制推送的分支。

因此,一方面,我想摆脱这些额外的步骤(添加功能分支时事情会变得更加复杂,因为需要在两个副本上正确检查这些分支并配置正确的跟踪),另一方面我想理解为什么它不能“正常工作”(tm)。


更新:

跟进一条评论经过@图坎,我用调试输出重现了错误:

  1. 使用调试输出安装远程:
 mount -o sshfs_debug MOUNTPOINT
SSHFS version 3.7.0
executing <ssh> <-x> <-a> <-oClearAllForwardings=yes> <-2> <USER@SERVER> <-s> <sftp>
USER@SERVER's password:
Server version: 3
Extension: versions <2,3,4,5,6>
Extension: [email protected] <1>
Extension: [email protected] <1>
Extension: [email protected] <2>
Extension: [email protected] <2>
Extension: [email protected] <1>
remote_uid = 0
  1. 在不同的终端中,访问已安装的共享:
cd MOUNTPOINT/DIR_WITH_WRITE_PERMISSIONS
[00002] LSTAT
  [00002]          ATTRS       45bytes (188ms)
  1. 验证常规写作作品:
echo foo > foobar
[00003] LSTAT
  [00003]         STATUS       38bytes (46ms)
[00004] LSTAT
  [00004]         STATUS       38bytes (32ms)
[00005] LSTAT
  [00005]          ATTRS       45bytes (242ms)
[00006] OPENDIR
  [00006]         HANDLE       29bytes (31ms)
[00007] READDIR
[00008] READDIR
  [00007]           NAME      668bytes (58ms)
[00009] READDIR
[00010] READDIR
  [00008]           NAME      483bytes (65ms)
[00011] READDIR
[00012] READDIR
  [00009]         STATUS       37bytes (27ms)
  [00010]         STATUS       37bytes (27ms)
[00013] CLOSE
[00014] LSTAT
  [00011]         STATUS       37bytes (27ms)
  [00012]         STATUS       37bytes (27ms)
  [00013]         STATUS       28bytes (26ms)
  [00014]         STATUS       38bytes (31ms)
[00015] OPEN
[00016] LSTAT
  [00015]         HANDLE       29bytes (153ms)
  [00016]          ATTRS       45bytes (158ms)
[00017] FSTAT
  [00017]          ATTRS       45bytes (29ms)
[00018] WRITE
  [00018]         STATUS       28bytes (28ms)
[00019] CLOSE
  [00019]         STATUS       28bytes (28ms)
  1. 尝试附加时触发错误:
echo bar >> foobar
[00020] LSTAT
  [00020]         STATUS       38bytes (74ms)
[00021] LSTAT
  [00021]         STATUS       38bytes (57ms)
[00022] LSTAT
  [00022]          ATTRS       45bytes (52ms)
[00023] OPENDIR
  [00023]         HANDLE       29bytes (53ms)
[00024] READDIR
[00025] READDIR
  [00024]           NAME      668bytes (68ms)
[00026] READDIR
[00027] READDIR
  [00025]           NAME      597bytes (77ms)
[00028] READDIR
[00029] READDIR
  [00026]         STATUS       37bytes (47ms)
[00030] CLOSE
  [00027]         STATUS       37bytes (47ms)
[00031] OPEN
[00032] LSTAT
  [00028]         STATUS       37bytes (47ms)
  [00029]         STATUS       37bytes (47ms)
  [00030]         STATUS       28bytes (26ms)
  [00031]         STATUS       43bytes (28ms)
  [00032]          ATTRS       45bytes (29ms)
zsh: permission denied: foobar

希望这有助于找到我的问题的根本原因。


注:基于答案经过@德维达斯(即使在绝望的寻求关注的赏金周之后也缺乏解决方案),我将其交叉发布到相应的 GitHub 问题

答案1

这么大而详细的问题。让我们一步步解决这个问题。错误是“权限被拒绝”

Linux error code
EACCES          13      /* Permission denied */

当我在 sshfs repo 中搜索时,EACCES我发现文件中只有两个实例[sshfs.c][1]

一是关于本地上下文中的文件权限。你所展示的那个。

其他是SSH_FX_PERMISSION_DENIED 由于 ssh 权限被拒绝而导致的错误。

根据我掌握的数据,我几乎可以肯定地说。当您在本地计算机上拥有权限时

案例

printf foo >> .git/logs/HEAD

这给予许可被拒绝的原因而不是

printf foo > .git/logs/HEAD

您没有远程计算机的权限或不支持引用O_APPEND的远程服务器第117期

你可以使用 strace 来验证它。

这就是为什么部分。如何解决取决于您的回复。是哪一种情况?

请告诉我,以便我可以进一步帮助您。

如果您不同意,请随时发表评论。

相关内容