docs: 收编 git-push-dlp skill(DLP 保护区内 git push 流程)

This commit is contained in:
p40000043244@byd.com
2026-07-31 17:59:19 +08:00
parent 65b277fc72
commit e0f1db75c2
3 changed files with 160 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
---
name: git-push-dlp
description: 在 DLP 透明加密保护区(如 E:\WorkSpace\)内执行 git push。保护区内直接 git push 必现 "fatal: not a git repository (or any of the parent directories): .git"(退出码 128),但其他 git 命令(status / fetch / commit / pull)全部正常。触发条件:"git push 失败"、"push 报 not a git repository"、"DLP push"、"git_push_dlp",或遇到上述 128 错误时。
---
# git-push-dlp — DLP 保护区内 git push
## 问题背景
本机装有透明加密系统(DLP),`E:\WorkSpace\` 属于保护区。在保护区内执行
`git push` 会必现:
```
fatal: not a git repository (or any of the parent directories): .git
```
退出码 128。这是 DLP 驱动对 push 进程访问模式的拦截,**不是仓库损坏**——
不要修仓库、不要重装 git。同一个 `.git` 复制到保护区外 push 立刻正常;
对保护区内的 `.git` 原地解密无效(写回会被驱动重新加密)。
## 原理
1. `xcopy .git``%TEMP%\git_push_dlp\<repo>-<random>\`(保护区外,授权进程
读出明文,写出不再加密)。默认通过 `/EXCLUDE` 排除 `.git\lfs`LFS 对象
缓存,动辄数 GB,普通提交 push 不需要)。
2. 在 stage 副本里执行 `git push`
3. 回到原仓库 `git fetch` 同步远程跟踪引用,然后删除 stage。
## 使用方法
脚本位置:`<skill_dir>\scripts\git_push_dlp.bat`,在**仓库根目录**执行:
```bat
cmd /c <skill_dir>\scripts\git_push_dlp.bat = git push origin HEAD
cmd /c <skill_dir>\scripts\git_push_dlp.bat origin main = git push origin main
cmd /c <skill_dir>\scripts\git_push_dlp.bat upstream main:main
```
如果本次 push 包含新增 / 变更的 LFS 文件(`.pt` / `.onnx` / `.zip` 等,见
`.gitattributes`),先设置环境变量再运行,恢复全量复制 `.git\lfs`
```bat
set GIT_PUSH_DLP_WITH_LFS=1
```
## 排障
- **`[ERROR] xcopy .git failed. Insufficient disk space`**TEMP 所在盘空间不足。
先清理 `%TEMP%\git_push_dlp\` 下历史失败残留的 `TestHub-*` 目录(脚本在
xcopy 失败时不会自动清理)。仍不足时确认是否误设了
`GIT_PUSH_DLP_WITH_LFS`(全量 lfs 可能超过盘符剩余空间)。
- **stage 在 E: 盘也报 128**:整个 E: 盘都在 DLP 拦截范围内,stage 必须落在
C:`%TEMP%` 默认位置),不要把 `TEMP` 指到 E:。
- **注释行被当成命令执行 / 解析错乱**:bat 被写成了 LF 行尾或混入了 UTF-8
中文注释,见下面维护注意。
## 维护注意(修改 scripts/git_push_dlp.bat 时必读)
- 文件必须保持 **CRLF 行尾**;编辑工具若写成 LF,cmd 会把注释行当命令执行。
修正方法:`unix2dos <file>`
- 注释(`rem`)保持**英文**。UTF-8 无 BOM 的中文注释会被 cmd 批解析器误解析。
- 括号代码块内引用本块内 `set` 的变量要用延迟扩展 `!VAR!` 而不是 `%VAR%`
## 备注
全局副本 `C:\Users\p40000043244\bin\git_push_dlp.bat`(已加入用户 PATH)仍然
可用,供其他保护区仓库使用;本仓库内以 `<skill_dir>\scripts\` 这份为准。
@@ -0,0 +1,81 @@
@echo off
rem ==========================================================================
rem git_push_dlp.bat
rem Push from a DLP-protected (transparent-encrypted) directory where
rem "git push" fails with: fatal: not a git repository
rem
rem How it works:
rem 1. xcopy .git to a stage dir under %TEMP% (outside the protected zone,
rem an authorized process reads plaintext, no re-encryption outside).
rem 2. Run "git push" from the stage dir.
rem 3. Run "git fetch" in the original repo to sync remote-tracking refs.
rem
rem Usage (run inside the repo root):
rem git_push_dlp = git push origin HEAD
rem git_push_dlp origin main = git push origin main
rem git_push_dlp upstream main:main = any normal push args
rem
rem Env vars:
rem GIT_PUSH_DLP_WITH_LFS=1 = also copy .git\lfs (needed only when
rem the push contains new LFS objects)
rem ==========================================================================
setlocal EnableExtensions EnableDelayedExpansion
chcp 65001 >nul
if not exist ".git\" (
echo [ERROR] .git not found. Run this inside a git repository root.
exit /b 1
)
for %%I in ("%CD%") do set "REPO_NAME=%%~nxI"
set "STAGE=%TEMP%\git_push_dlp\%REPO_NAME%-%RANDOM%%RANDOM%"
echo [DLP] Stage dir: %STAGE%
rem .git\lfs is the LFS object cache (often several GB); normal commits do
rem not need it for push. Excluding it avoids xcopy disk-space failures.
rem If this push contains new/changed LFS files, set GIT_PUSH_DLP_WITH_LFS=1 first.
set "EXCLUDE_OPT="
if not defined GIT_PUSH_DLP_WITH_LFS (
set "EXCLUDE_FILE=%TEMP%\git_push_dlp_exclude.txt"
> "!EXCLUDE_FILE!" echo \lfs\
set "EXCLUDE_OPT=/EXCLUDE:!EXCLUDE_FILE!"
echo [DLP] Excluding .git\lfs ^(set GIT_PUSH_DLP_WITH_LFS=1 to include^)
)
xcopy /E /I /Q /H /Y %EXCLUDE_OPT% ".git" "%STAGE%\.git" >nul
if errorlevel 1 (
echo [ERROR] xcopy .git failed.
exit /b 1
)
set "REMOTE=%~1"
if not defined REMOTE set "REMOTE=origin"
if "%REMOTE:~0,1%"=="-" set "REMOTE=origin"
set "PUSHARGS=%*"
if not defined PUSHARGS set "PUSHARGS=origin HEAD"
pushd "%STAGE%"
echo [DLP] Run: git push %PUSHARGS%
git push %PUSHARGS%
set "EXIT_CODE=%ERRORLEVEL%"
popd
if not "%EXIT_CODE%"=="0" (
echo [ERROR] push failed with exit code %EXIT_CODE%
rmdir /s /q "%STAGE%" 2>nul
exit /b %EXIT_CODE%
)
echo [DLP] Sync back: git fetch %REMOTE%
git fetch %REMOTE%
set "FETCH_CODE=%ERRORLEVEL%"
rmdir /s /q "%STAGE%" 2>nul
if not "%FETCH_CODE%"=="0" (
echo [WARN] push succeeded but fetch back failed with exit code %FETCH_CODE%
exit /b %FETCH_CODE%
)
echo [DLP] Done.
exit /b 0