Git本身无内置权限体系,所有权限控制依赖外部工具或平台;push成功而pull失败多因SSH与HTTPS认证机制不匹配、PAT权限不足、子模块凭据缺失或Protected Branches角色配置遗漏。

Git 本身没有权限体系,所有“权限控制”都依赖外部工具或托管平台实现。想靠纯 Git 命令或裸仓库做细粒度读写控制,注定失败——这不是配置问题,是设计边界问题。
为什么 git push 能成功但 git pull 失败?常见权限错位场景
这通常不是 Git 的错,而是底层传输协议与认证机制不匹配:
-
ssh://地址走 SSH 密钥认证,https://地址走 HTTP Basic 或 Token 认证,两者权限策略完全独立 - GitHub/GitLab 的个人访问令牌(PAT)默认只带
repo作用域,但 CI 场景常需workflow或packages,漏配就拉不到子模块或触发不了 Action - 使用
git submodule update --init时,子模块 URL 若仍为https://形式,即使主仓库用 SSH,也会因无凭据而静默失败
GitLab CE 自建如何绕过 Protected Branches 的硬限制?
Protected Branches 是 UI 层强管控,但底层 Git 协议不拦截。绕过不是为了破坏安全,而是应对 CI/CD 流水线中合法的自动化提交:
- 用
git push --force-with-lease替代--force,避免覆盖他人未 fetch 的提交 - 在 CI 脚本中用
git config --global user.name "CI Bot"+user.email "ci@example.com"显式声明身份,避免因空 user 导致提交被 Protected Rules 拒绝 - 关键:将 CI 服务账号加入项目
Maintainer角色,并在 Protected Branch 设置中勾选 “Allow users with Maintainer role to merge” 和 “Push” —— 否则即使有密钥也推不上去
用 gitolite 实现仓库级读写分离时,RW+ 和 RW 到底差在哪?
这是 gitolite 权限模型里最容易误用的点,直接决定能否重写历史:
-
RW允许推送新 commit、创建分支/标签,但拒绝git push --force、拒绝删除远程分支(git push origin :branch) -
RW+开放 force-push 和删除操作,适用于需要 rebase 后强制同步的协作流程,但必须配合deny delete refs/heads/master这类显式规则防误删 - 注意:gitolite 的规则按顺序匹配,
RW+ = main写在RW = @all下面就无效 —— 它不会覆盖,只会跳过
真正的复杂度不在 Git 命令本身,而在你把权限逻辑分散在 SSH 配置、HTTP 凭据、CI Token 作用域、托管平台角色、以及 gitolite 规则链里。漏掉任意一层,就会出现“看着能连上,实际推不进”的情况。











