裸仓库唯一合理角色是作为中央共享点,不可用于写代码或日常开发;必须用git init --bare创建,仅支持git push/pull/clone等操作,不支持git checkout或git status。

裸仓库只该用在远程协作场景
裸仓库不是用来写代码或日常开发的,它的唯一合理角色是作为中央共享点——比如你搭在内网服务器上的代码中转站,或者 GitLab / GitHub 背后实际存储数据的那个目录。它不带工作区,所以没人能直接在上面改文件、git checkout 或 git commit,这反而是设计优势:避免多人 push 时因当前分支被“检出”而触发拒绝(refusing to update checked out branch)。
常见误用包括:
- 把本地开发完的项目目录重命名为
project.git就当裸仓用了 → 实际仍是普通仓库,git push会失败 - 用
git clone --bare克隆已有项目,再当新中央仓用 → 它带完整历史和所有引用,但初始状态不是“空仓”,不适合从零开始协作 - 在裸仓里手动删
refs/heads/*想清空分支 → 极易漏掉HEAD或packed-refs,后续git receive-pack可能异常
创建裸仓库必须用 git init --bare
这是唯一安全、可预期的方式。命令执行后,目录下只有 objects、refs、HEAD 等 Git 内部文件,没有 .git 子目录,也没有任何源码文件。
正确示例:
git init --bare myapp.git
注意命名习惯:.git 后缀不是强制要求,但几乎所有 Git 工具链(包括 SSH URL 解析、GitLab 的仓库发现逻辑)都默认识别这种命名;若起名 myapp-bare,部分自动化脚本可能无法识别为裸仓。
错误做法:
监控一个或多个 GitCode 仓库的 PR,通过 OpenClaw Gateway 自动执行 AI 审查,发布 PR 评论,并发送钉钉和企业微信通知。
-
git init && rm -rf *→ 会残留.git/index和未清理的引用,破坏裸仓一致性 -
cp -r .git/ ../myapp.git && rm -rf .git→ 缺少hooks权限、config中路径错乱,git push可能静默失败
推送代码到裸仓库前要配 receive.denyCurrentBranch
即使裸仓没工作区,Git 默认仍检查 HEAD 是否指向某分支,并拒绝推送——这是历史兼容性行为。现象是 git push origin main 报错:
remote: error: refusing to update checked out branch
解决方法只认两个合法值:
-
git config receive.denyCurrentBranch ignore→ 最常用,适合 CI/CD 自动部署或纯同步场景,推送后引用更新,但不触发钩子或工作区操作 -
git config receive.denyCurrentBranch updateInstead→ Git 2.4+ 支持,允许推送直接更新引用,且自动更新HEAD(如果指向的是推送目标分支),但需确保没其他进程正读取旧引用
别试 false 或 no —— 这些值 Git 不识别,配置无效。
裸仓库里不能运行 git status、git checkout 等命令
因为缺少 worktree,所有依赖工作目录的操作都会报错:
fatal: this operation must be run in a work tree
你能做的仅限于读取型操作:git log、git show、git cat-file、git ls-remote。想看某次提交的源码?只能:
- 用
git archive --format=tar HEAD | tar -x临时解包 - 或克隆一份非裸仓:
git clone /path/to/repo.git tmp-checkout && cd tmp-checkout
真正容易被忽略的一点:裸仓库的 hooks 目录虽存在,但 post-receive 等钩子不会自动执行——除非你显式启用并确保权限正确;很多用户以为推完就该触发部署,结果什么都没发生,问题往往出在这里。










