我遇到了一个Azure DevOps管道停止工作的问题,原来是因为有一个“坏了”的ref .git/refs/remotes/origin/feature/__pycache__/app.cpython-310.pyc
(显然一开始就不应该存在)。所以我登录到服务器,删除了那个__pycache__
目录,管道又开始按预期工作了。
现在,我试着在我的本地上切换分支,我得到了同样的错误:
$ git fetch --all --prune
Fetching origin
error: cannot lock ref 'refs/remotes/origin/feature/__pycache__/app.cpython-310.pyc': unable to resolve reference 'refs/remotes/origin/feature/__pycache__/app.cpython-310.pyc': reference broken
error: could not remove reference refs/remotes/origin/feature/__pycache__/app.cpython-310.pyc
我很困惑这是怎么来的。有人见过吗?这是潜在的一个问题,有人意外地创建了一个新的分支,如git checkout -b feature/__pycache__/app.cpython-310.pyc
?其他东西?
2条答案
按热度按时间dgsult0t1#
我对这一切是怎么来的感到很困惑。
Git在key-value database中存储名称-分支名称、标记名称、远程跟踪名称等,其中的全名,例如
refs/heads/main
,是键,值是一个哈希ID。好吧,但这有什么关系呢?嗯,目前这个键-值数据库的实际 * 实现 * 相当低级:.git/packed-refs
的 file 中的一行(可能添加了一个辅助行)组成;.git/refs
内的 * 目录 * 中,目录名由引用的组成部分组成(省略冗余的refs/
)。有时它什至在两个位置,虽然这意味着“未打包”的文件引用覆盖了打包的文件,因为它被认为是较新的。
因此,这意味着如果一个名为
feature/foo
的分支存在,那么.git/refs/heads/feature/
可能存在,也可能不存在!好吧,但那又怎样?如果这个目录确实存在,你运行一个Python程序,Python会加载一个名为
app.py
的文件,并将其字节编译为.pyc
文件(并且您使用的是Python3),*python字节编译器 * 可能会 * 将.pyc
文件 * 写入名为__pycache__/app.cpython-310.pyc
的文件。1 Python将使用此字节-编译的文件来加载和运行东西。但是一旦 Python 完成了这个操作,Git 就会认为
.git/refs/heads/feature/__pycache__/app.cpython-310.pyc
是一个有效的ref,因此会有一个名为feature/__pycache__/app.cpython-310.pyc
的分支。远程跟踪名称也会发生同样的情况:唯一的区别是,这个目录的开始是
.git/refs/remotes/origin/feature/
。在这两种情况下,Git都认为这个名字是有效的,但其值--哈希ID--是假的。这就是为什么无法“锁定”“损坏”的引用。2那么,真实的的问题是:是什么原因导致运行中的Python程序将
__pycache__
文件放到Git仓库的子目录中?__pycache__
目录的位置应该与加载的.py
文件的位置相同,这意味着有人在Git仓库内部的.git/refs/
目录中写入了app.py
文件,这将是坏的(程序不应该做这样的事情:它们应该在专用临时目录或X1 M18 N1 X或类似目录中生成它们的临时文件)。除了指向What is pycache?和If Python is interpreted, what are .pyc files?,我必须离开这个谜在这一点上未解决,因为我不知道是什么创建了这个
app.py
文件摆在首位。1如果打开了字节代码优化,编译后的文件可能以
.pyo
结尾。2 Python 2将这些文件写入.py
文件的旁边,而不是__pycache__
目录中。中间的cpython-310
部分表示您使用的是CPython 3.10版;在Python的某些(较旧的)版本中不会出现这种版本号插入。2在这种情况下,“锁定”ref的操作包括创建一个文件,该文件的名称以
.lock
结尾,其他方面与完整ref文件名相同。该文件将用于保存新值,并且将使用原子rename
操作将文件交换到适当位置以更新和解锁ref。所有这些都严重依赖于POSIX文件语义,这是不应该将.git
存储库放入云管理软件文件夹的众多原因之一,因为云管理软件文件夹不遵守POSIX文件语义。izkcnapc2#
我想我应该更新一个答案:
我有一个验证提交的脚本,测试文件是否编译和做各种各样的事情。这个脚本显然是在
.git
目录上迭代,并试图编译一个(可能是名字不好的)refs/heads/feature/app.py
分支。通过删除__pycache__
目录并确保验证脚本跳过.git
目录来修复:)