diff --git a/.kimi-code/skills/git-push-dlp/SKILL.md b/.kimi-code/skills/git-push-dlp/SKILL.md index 1b22d4e..5f851ad 100644 --- a/.kimi-code/skills/git-push-dlp/SKILL.md +++ b/.kimi-code/skills/git-push-dlp/SKILL.md @@ -20,11 +20,12 @@ fatal: not a git repository (or any of the parent directories): .git ## 原理 -1. `xcopy .git` 到 `%TEMP%\git_push_dlp\-\`(保护区外,授权进程 - 读出明文,写出不再加密)。默认通过 `/EXCLUDE` 排除 `.git\lfs`(LFS 对象 - 缓存,动辄数 GB,普通提交 push 不需要)。 +1. `robocopy /MIR .git` 到固定 stage 目录 `%TEMP%\git_push_dlp\\`(保护区外, + 授权进程读出明文,写出不再加密)。stage 目录跨运行保留:首次全量镜像, + 之后每次 push 只复制变动的文件。默认通过 `/XD lfs` 排除 `.git\lfs`(LFS + 对象缓存,动辄数 GB,普通提交 push 不需要)。 2. 在 stage 副本里执行 `git push`。 -3. 回到原仓库 `git fetch` 同步远程跟踪引用,然后删除 stage。 +3. 回到原仓库 `git fetch` 同步远程跟踪引用。stage 目录保留不删,供下次增量复用。 ## 使用方法 @@ -45,9 +46,9 @@ set GIT_PUSH_DLP_WITH_LFS=1 ## 排障 -- **`[ERROR] xcopy .git failed. Insufficient disk space`**:TEMP 所在盘空间不足。 - 先清理 `%TEMP%\git_push_dlp\` 下历史失败残留的 `TestHub-*` 目录(脚本在 - xcopy 失败时不会自动清理)。仍不足时确认是否误设了 +- **`[ERROR] robocopy .git failed`**:常见于 TEMP 所在盘空间不足。stage 目录 + 跨运行复用(`%TEMP%\git_push_dlp\\`),旧版本脚本留下的 `-<数字>` + 残留目录可以整体删除。仍不足时确认是否误设了 `GIT_PUSH_DLP_WITH_LFS`(全量 lfs 可能超过盘符剩余空间)。 - **stage 在 E: 盘也报 128**:整个 E: 盘都在 DLP 拦截范围内,stage 必须落在 C:(`%TEMP%` 默认位置),不要把 `TEMP` 指到 E:。 diff --git a/.kimi-code/skills/git-push-dlp/scripts/git_push_dlp.bat b/.kimi-code/skills/git-push-dlp/scripts/git_push_dlp.bat index 2ae4486..e6e707f 100644 --- a/.kimi-code/skills/git-push-dlp/scripts/git_push_dlp.bat +++ b/.kimi-code/skills/git-push-dlp/scripts/git_push_dlp.bat @@ -5,8 +5,11 @@ 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 1. Mirror .git to a fixed per-repo stage dir under %TEMP% with +rem robocopy /MIR (outside the protected zone, an authorized process +rem reads plaintext, no re-encryption outside). The stage dir is kept +rem between runs, so after the first full mirror only changed files +rem are copied on subsequent pushes. rem 2. Run "git push" from the stage dir. rem 3. Run "git fetch" in the original repo to sync remote-tracking refs. rem @@ -16,8 +19,9 @@ 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 GIT_PUSH_DLP_WITH_LFS=1 = also mirror .git\lfs (needed only +rem when the push contains new LFS +rem objects) rem ========================================================================== setlocal EnableExtensions EnableDelayedExpansion chcp 65001 >nul @@ -28,24 +32,24 @@ if not exist ".git\" ( ) for %%I in ("%CD%") do set "REPO_NAME=%%~nxI" -set "STAGE=%TEMP%\git_push_dlp\%REPO_NAME%-%RANDOM%%RANDOM%" +set "STAGE=%TEMP%\git_push_dlp\%REPO_NAME%" 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 not need it for push. Excluding it avoids filling up the TEMP drive. 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!" +set "EXCLUDE_OPT=/XD lfs" +if defined GIT_PUSH_DLP_WITH_LFS set "EXCLUDE_OPT=" +if defined GIT_PUSH_DLP_WITH_LFS ( + echo [DLP] Including .git\lfs +) else ( 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. +robocopy ".git" "%STAGE%\.git" /MIR %EXCLUDE_OPT% /NFL /NDL /NJH /NP >nul +if errorlevel 8 ( + echo [ERROR] robocopy .git failed ^(exit %ERRORLEVEL%^). exit /b 1 ) @@ -64,7 +68,6 @@ 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% ) @@ -72,7 +75,6 @@ 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%