Install
openclaw skills install @huanmeng9527/safe-git-push从 agent 工作区安全推送文件到 GitHub。父级 git 仓库场景下隔离 init,防止敏感配置文件、构建产物目录、其他无关项目子目录被误推。触发:用户说「上传到 GitHub」「推到 GitHub」「创建 GitHub 仓库」「备份项目到 GitHub」,或 OpenClaw 沙箱内 git push 超时需走 Contents API fallback。
openclaw skills install @huanmeng9527/safe-git-push~/.openclaw/workspace/ 本身就是 git 仓库, 里面有 .env / skills/ / node_modules/ / 其他项目目录等大量未跟踪敏感文件)不要直接在当前目录 git add . 然后 push. 父级仓库会被污染, 可能把 .env (密钥)、node_modules/ (几百 MB 噪声)、其他无关项目一起推到 GitHub, 后果包括:
.env, .aws/, ~/.ssh/ 误包含)cd <target_dir>
git rev-parse --is-inside-work-tree # true = 在某个 git 仓内
git rev-parse --show-toplevel # 真正的 git 根
git status --short | wc -l # 未跟踪文件数量
git remote -v # 是否已有远端
判断:
toplevel == target_dir → 目录本身就是独立仓库, 可直接用toplevel ≠ target_dir → 目录在父级仓库内, 必须隔离(见 Step 2)在子目录内独立 git init, 不污染父级:
cd <target_dir>
git init -b main # 或 master, 对齐目标平台
只 git add 你要追踪的文件(永远不要 git add .):
git add file1 file2 file3 ... # 显式列出
git status --short # 复核
最小 .gitignore(Python 项目起步):
__pycache__/
*.pyc
.DS_Store
.vscode/
.idea/
.vs/
*.tmp
gh repo create <repo-name> --private --description "..."
# 注:--confirm 在 gh 2.0+ 已废弃, 任何额外参数(如 --private)即跳过确认
也可走网页手动建仓, 然后 git remote add 即可.
git remote add origin https://github.com/<user>/<repo>.git
git commit -m "Initial commit: ..."
git push -u origin main
推送后用 gh repo view <user>/<repo> --json isPrivate,pushedAt 或网页确认.
git push 被反复 SIGTERM 杀掉时触发条件(必须先有 2 次以上 SIGTERM 失败才换路径, 避免误诊):
git push 命令被 sandbox 超时中断(无错误输出就结束)gh api repos/<user>/<repo>/contents 返回 "This repository is empty" 404main 分支仍是空gh repo view ... --json pushedAt 显示的时间戳其实是 gh repo create 时的, 不是 push 成功的证据——不要被这个字段误导原因: OpenClaw sandbox 大约 30s 杀长进程。git push 上传含图、PDF、docx 的仓库一定会超时, HTTPS / SSH / 带 token URL 三种鉴权方式都同样被杀。
修复路径: 用 GitHub Contents API (gh api -X PUT) 逐文件上传, 走普通 HTTPS POST, 单请求小不会触发超时:
# payload.json 模板(每个文件一份)
{
"message": "upload <file>",
"branch": "main",
"content": "<base64 编码的文件内容>"
}
# 二进制文件 (PNG/DOCX/PDF): Python 生成
python3 -c "import base64,json; print(json.dumps({'message':'upload x.png','branch':'main','content':base64.b64encode(open('x.png','rb').read()).decode()}))"
# 文本文件 (.md / .py / .json): 直接原文 (注意 JSON 字符串内换行需 \\n 转义)
gh api -X PUT repos/<user>/<repo>/contents/<path> --input payload.json
为什么这个路径可靠:
为什么不选这些替代方案:
gh repo sync —— 要求远端已有 main 分支, 首次推送时是空仓库, 不能用gh repo push —— 该子命令在 gh CLI 中不存在git push https://x-access-token:TOKEN@github.com/... —— 仍走 git 协议, 同样被杀完成后验证:
gh api repos/<user>/<repo>/contents --jq 'if type == "array" then [.[].name] else .message end'
返回数组 = 推送成功; 返回 "This repository is empty" = 还没推完, 重跑脚本。
git add . 是高危 —— 永远显式列出要追踪的文件, 或至少用 git add <file> 加 git status --short 复核git rev-parse --show-toplevel 输出不等于当前目录就是隔离信号.gitignore 别忘 —— 至少屏蔽常见噪声: __pycache__/ / .DS_Store / 编辑器配置 / 大目录(node_modules/ / venv/ / .venv/ / dist/ / build/)--confirm 已废弃 —— 不要照旧教程写, 会报错main; 老仓库可能是 master, 推送前先 git branch --show-current 看git status --short + 抽查文件列表, 确认没有 .env / *.key / *secret* / id_rsa 等git push 在 OpenClaw sandbox 常被 SIGTERM 杀掉 —— 含图/PDF/docx 的仓库必超时。多次失败后改走 Step 5 的 Contents API fallback; 不要被 gh repo view --json pushedAt 的时间戳误导(那是 gh repo create 时写入的, 不是 push 成功的证据)# 1. 探测
cd /home/lv/.openclaw/workspace/my-project
git rev-parse --show-toplevel
# → /home/lv/.openclaw/workspace ← 与 target_dir 不同, 需隔离
# 2. 隔离
git init -b main
cat > .gitignore << 'EOF'
__pycache__/
*.pyc
.DS_Store
EOF
git add README.md src/ # 显式列出
git status --short # 复核
git commit -m "Initial commit"
# 3+4. 创建并推送
gh repo create my-project --private --description "..."
git remote add origin https://github.com/<user>/my-project.git
git push -u origin main
git initgit status --short 显示的文件就是要追踪的全部(无 .env / node_modules / 其他项目文件).gitignore 至少覆盖 __pycache__/ / .DS_Store / 编辑器配置git add <dir>, 不需要隔离/tmp/project) → 可直接 init, 但仍避免 git add .sandbox-web-fetch —— 同在 OpenClaw sandbox 下, 但管的是从公网拉内容; push 走 Contents API, fetch 走 curl/tarballopenclaw-credential-injection —— push 通常不需要 LLM key, 但若脚本里要调用 OpenAI/DeepSeek 等 LLM 做 release notes / commit message 润色, 用本技能接 key