Git Workflow Skill · v1Git 工作流 Skill · v1

Two clones.
One push path.
Zero accidents.
两份 clone。
一条 push 路径。
零误推。

For projects where the upstream is protected (MR / PR only) and the build is heavy or pollutes the tree. One command sets up a gateway repo that pushes and a satellite repo that builds — the build tree is physically unable to reach the remote. 适用于上游分支受保护(必须走 MR / PR)且编译重、会污染工作树的项目。一条命令搭起 gateway 仓库负责 push 和 satellite 仓库只读编译——编译树在物理上够不到远程。

Most git workflows assume you trust yourself not to push the wrong thing. On a heavy project — Android builds, Yocto images, multi-gigabyte datasets — you stop trusting yourself the hundredth time git status returns sixty lines of unrelated artefacts. A tired afternoon, one wrong git push, and the whole team is rolling back. 大多数 git 工作流的前提是:你信得过自己不会把错东西推出去。但在重型项目上——Android 编译、Yocto 镜像、多 GB 数据集——当 git status 第一百次返回 60 行无关产物,你就开始信不过自己了。一个疲惫的下午,一条错误的 git push,整个团队回滚半天。

This skill removes the choice. The tree that compiles is not the tree that pushes. They are two directories, each with its own origin, and the build tree's origin never left your laptop. 这个 skill 把“选择”拿掉了。编译的目录不等于推代码的目录。是两个目录,各自有自己的 origin,而编译目录的 origin 从来没离开过你的笔记本。

2 clones份 clone
3 safety gates道安全检查
1 push path条 push 路径
The whole skill exists to make this command boring — so you can forget it, and trust the shape. 这个 skill 存在的全部意义,就是让这条命令变得无聊——你可以忘掉它,信任这个结构。

The topology 拓扑

Three nodes, two clones, one direction of push. The satellite's origin points at the local gateway — no protocol path to upstream exists from the build tree. 三个节点,两份 clone,一条 push 方向。satellite 的 origin 指向本地的 gateway——编译树到上游根本不存在协议通路。

upstream remote git@gitlab.example.com:team/project.git protected · MR / PR only gateway/ edit here · push source · 编辑 · push 源 origin = git@gitlab.example.com:... pre-push hook: reject protected satellite/ build here · fetch only · 编译 · 只读 origin = file:///path/to/gateway/.git push URL = DISABLED push personal branch only fetch fetch hardlinked .git/objects BLOCKED LEGEND push fetch blocked
Three tiers · two clones · push traffic is physically confined to the gateway. The satellite has no network path to upstream — only to the local gateway on disk. 三层结构 · 两份 clone · push 流量被物理约束在 gateway 里。satellite 到上游没有网络路径,只连到本地磁盘上的 gateway。

Should I use this? 该不该用

Four yes/no questions. Three or more "yes" means the pattern earns its weight. Otherwise a single repo or a git worktree is the right tool — this skill would add ceremony you don't need. 4 道是非题。≥ 3 个 yes 这个模式的额外工程量才划得来。不到 3 个 yes,单仓库或者 git worktree 更合适,本 skill 会是多余的复杂度。

01

Is the upstream branch protected? 上游分支是否受保护?

MR / PR required, direct push rejected by the host. Check in the hosting UI (GitLab "Protected branches", GitHub "Branch protection rules"). 必须走 MR / PR,直接 push 被托管平台拒。托管后台看(GitLab "Protected branches"、GitHub "Branch protection rules")。

02

Build > 10 min, or > 500 MB of artefacts? 构建 > 10 分钟,或产物 > 500 MB?

Look at CI timing and du -sh out/ build/. Heavy builds are what make the separate satellite tree pay for itself. 看 CI 时长和 du -sh out/ build/。编译重,satellite 独立工作树的开销才值得。

03

Disk for two trees — including LFS? 盘够两份工作树 —— 含 LFS 吗?

.git/objects hardlinks, but git-lfs payloads and large binary submodules do not — they really cost 2× on disk. Budget for it. .git/objects 会 hardlink,但 git-lfs 对象和大型二进制 submodule 不会——真的 2× 占盘。预算时考虑进去。

04

Want physical edit/build isolation? 想要 edit / build 物理隔离吗?

Build artefacts never pollute git status; an accidental git push from the build tree can't even reach upstream. 编译产物永远不污染 git status;从编译树误跑 git push 也够不到上游。

Verdict结论

Three or more "yes" — use this skill. Fewer — see the comparison table for the better-fitting alternative. ≥ 3 个 yes — 用本 skill。少于 3 个 — 去看对比表挑更合适的方案。

The command 搭建命令

One invocation. Eight parameters. Every value is documented inline — no magic, no hidden state. 一条命令,8 个参数,每个值都有行内注释 —— 无魔法,无隐藏状态。

scripts/bootstrap.sh \
  --remote          git@gitlab.example.com:team/project.git \
  --upstream-branch release                                 \
  --push-branch     feature/alice-auth                      \
  --gateway-dir     ~/projects/foo-work                     \
  --satellite-dir   ~/projects/foo-verify                   \
  --user-email      alice@example.com                       \
  --user-name       alice

# gateway/     — edit here, pushes to your personal branch— 在这里改代码,push 到你的个人分支
# satellite/   — build here, fetch from gateway, push is DISABLED— 在这里编译,从 gateway fetch,push 被禁用

Three safety gates 三道安全检查

After bootstrap finishes, three checks must pass. Each one verifies a separate layer — protocol, git config, hook. Any single layer holds; three together is belt, braces, and a shoulder strap. bootstrap 完成后跑 3 道检查。每道验证一层——协议层、git 配置层、hook 层。任意单层都够用,三层叠加是三重保险。

Load-bearing · Layer 1主防线 · 第 1 层

Gate A · Protocol wall 检查 A · 协议墙

Satellite origin points at the local gateway path. There is no network route from the build tree to upstream — you can't push what you can't reach. Satellite origin 指向本地 gateway 路径。编译树到上游没有网络路由——够不到,就推不了。

cd satellite/ && git push
# → "does not accept"
Gate A — protocol-layer barrier.检查 A — 协议层屏障。

Gate B · Explicit disable 检查 B · 显式禁用

Satellite's push URL is overwritten to the literal string DISABLED. Even a malformed config edit still yields a fast, readable error instead of a silent attempt. Satellite 的 push URL 覆盖为字符串 DISABLED。哪怕配置被误改,也报错直接清晰,不会静默尝试。

cd satellite/ && git remote -v
# → "origin ... (push): DISABLED"
Gate B — git-config belt-and-braces.检查 B — git 配置双保险。

Gate C · Pre-push hook 检查 C · pre-push hook

Gateway runs a pre-push hook that rejects any push whose remote ref matches the protected-branch regex. Catches finger-slips like git push origin main. Gateway 的 pre-push hook 在推保护分支时拒绝。接住类似 git push origin main 的手滑误操作。

cd gateway/ && \
git push origin release --dry-run
# → "REJECTED: protected branch"
Gate C — human-readable reject.检查 C — 人类可读的拒绝提示。
Client-side hooks are advisory, not enforcement. --no-verify bypasses them. Real protection is server-side protected-branch rules on GitLab / GitHub / Gerrit. This skill layers on top of that — it does not replace it. 客户端 hook 是教学性质的提醒,不是强制边界。--no-verify 可以绕过。真正的保护是 GitLab / GitHub / Gerrit 服务端的 protected branch 规则。本 skill 只是在它之上加一层,不替代它。

Optional · reproducibility gate 可选 · reproducibility 关卡

A 3rd clone for when "works on dev disk, fails on CI" has a real cost 第 3 仓 —— 当“dev 盘能编,CI/HDD 挂”真的要付代价时

Pass --clean-verify-dir=<path> (ideally on a cold HDD or a separate machine) and bootstrap.sh adds a third clone plus a pre-push gate: every push is refused unless a from-scratch full build has stamped the exact commit. --clean-verify-dir=<path>(推荐冷 HDD / 异机器),bootstrap.sh 会加第 3 仓 + 一道 pre-push 关卡:没经过从零全量编 stamp 的 commit 推不出去。

UPSTREAM gitlab / github / gerrit GATEWAY · SSD dev + commits + push pre-push: protect + stamp-match SATELLITE · SSD iteration build push = DISABLED CLEAN-VERIFY · HDD from-scratch full build push = DISABLED · origin + upstream GATEWAY/.GIT/LAST-CLEAN-VERIFY <sha> <ts> sha256(build-cmd) written on build pass · read by pre-push push fetch (local path) fetch (local path)
Only gateway reaches upstream. Satellite and clean-verify both fetch from gateway's local path — no network route out, pushurl DISABLED on both. On build pass, clean-verify writes a stamp; gateway's pre-push hook reads it. 只有 gateway 能到上游。Satellite 和 clean-verify 都从 gateway 本地路径 fetch —— 没有对外网络路由,pushurl 都禁用。编译通过时 clean-verify 写 stamp,gateway pre-push hook 读。

Bootstrap with 3-clone 3 仓模式搭建

scripts/bootstrap.sh \
  --remote              git@gitlab.example.com:team/project.git \
  --upstream-branch     release                                 \
  --push-branch         feature/alice-auth                      \
  --gateway-dir         ~/projects/foo-work                     \
  --satellite-dir       ~/projects/foo-verify                   \
  --clean-verify-dir    /mnt/hdd/foo-clean-verify               \
  --user-email          alice@example.com                       \
  --user-name           alice

# adds Step 5b (clone clean-verify) + Step 6b (configure pushurl=DISABLED on origin + upstream)追加 Step 5b(clone clean-verify)+ Step 6b(origin + upstream 双重 pushurl=DISABLED)
# adds Gate D post-setup + passes --enforce-clean-verify to install-hooks.sh追加 Gate D 验证 + 自动给 install-hooks.sh 传 --enforce-clean-verify

Before each push · the gate 每次 push 前 · 跑关卡

scripts/clean-verify-run.sh \
  --gateway-dir        ~/projects/foo-work           \
  --clean-verify-dir   /mnt/hdd/foo-clean-verify     \
  --push-branch        feature/alice-auth            \
  --build-cmd          'make -j$(nproc) all test'    \
  --yes

# 1. fetch + reset --hard from gateway   2. git clean -fdx   3. run --build-cmd1. 从 gateway fetch + reset --hard   2. git clean -fdx   3. 跑 --build-cmd
# 4. on pass: write gateway/.git/last-clean-verify  5. next git push is allowed4. 通过则写 stamp  5. 下一次 git push 才放行
# emergency bypass:  git push --push-option=allow-unverified紧急 bypass:  git push --push-option=allow-unverified

What 3-clone catches 3 仓多抓什么

  • SSD-cache-only bugs (cold HDD exposes them)SSD 缓存独有的 bug(冷 HDD 暴露)
  • Stale build artefacts that satisfy missing #include旧产物掩盖了缺的 #include
  • Dirty-tree bugs · edits author forgot未提交改动躲在 SSD 里
  • Build-command drift (hashed into stamp)build command 漂移(sha256 进 stamp)
Failure modes 2-clone doesn't catch.2 仓抓不到的失败模式。

Cost of the 3rd clone 第 3 仓的代价

  • Extra disk (one more checkout on HDD)额外磁盘(HDD 一份 checkout)
  • One full-build wait before each push每次 push 前等一次全量编
  • Discipline to run clean-verify-run.sh要养成跑 clean-verify-run.sh 的习惯
  • Revisit: skip if no reproducibility pain没 reproducibility 痛就别开
The bill you pay for the gate.开这道关卡的账。

Audit auto-detects 3-clone audit 自动识别 3 仓

Pass --clean-verify-dir to gated-dual-clone-audit too and it adds 4 extra gates: S9-S11 (exists, is git repo, stamp present) + C9a-c (origin at gateway, pushurls all DISABLED) + B4 (push actually rejected). 26 gates total in 3-clone mode. gated-dual-clone-audit--clean-verify-dir 就自动扩 4 gate:S9-S11(存在、是 git 仓、stamp 有)+ C9a-c(origin 指 gateway、两 pushurl 都 DISABLED)+ B4(push 实际被拒)。3 仓模式共 26 gate。

The evaluator tracks the new gates.评估器跟上新 gate。

Dual-clone vs worktree vs single repo 双 clone · worktree · 单仓库三者对比

Quick reference — each row scores one practical dimension. Pick the column that fits your constraints; don't force the pattern to fit you. 速查表——每行打一个实际维度的分。按约束挑列,不要硬套模式。

Dimension维度 Dual-clone (this)双 clone(本方案) git worktreegit worktree Single repo单仓库
Disk cost盘占用 2× tree; .git hardlinked2× 工作树;.git hardlink .git + N× tree.git + N× 工作树 1× total1× 总
LFS / binary submoduleLFS / 大二进制 submodule 2× (no hardlink)2×(不 hardlink)
Physical push isolation物理防误推 Yes — satellite origin is local有——satellite origin 是本地 No — shared remote无——共享 remote No
Build pollutes git status编译污染 git status Isolated隔离 Isolated隔离 Polluted污染
Cross-machine migration跨机迁移 Medium (re-install hooks)中(要重装 hook) Low Low
Shared-machine safety共用机器的安全 Safe安全 Risky有风险 Risky有风险
Client-hook bypass risk客户端 hook 被绕风险 Low — protocol barrier低——有协议层保护 Full完全暴露 Full完全暴露