名称: ctx-borrow 描述: “提取并应用同一项目两个目录之间的差异。当从并行工作树或单独的检出合并结果,且git push/pull不实用时使用。” 允许的工具: Bash(git:), Bash(diff:), Bash(ls:), Bash(patch:), Read
从"未来"目录提取更改,并将其应用到"当前"工作树。是ctx-worktree的补充:工作树将工作分开,而borrow则将结果合并回来。
何时使用
- 将并行工作树的结果合并回主检出
- 应用来自单独检出(不同机器、USB拷贝)的更改
- 用户说"借用"、“从…带来更改”、“从文件夹合并”
- 同一项目的两个副本需要协调其差异
何时不使用
- 目录位于共享的git远程仓库 — 使用
git pull/git merge - 工作树由git管理且可以使用
ctx-worktree teardown - 目录是不同的项目(没有共同的祖先)
飞行前检查
-
验证目录存在:
ls "<当前>" "<未来>" -
相同项目指纹 — 至少必须匹配一项:
- 相同的
go.mod模块路径,或相同的package.json名称 - 相同的
.context/CONSTITUTION.md存在于两者中 - 在去除工作树后缀后具有相同的基本名称 如果没有匹配项,则发出警告并在继续之前要求用户确认。
- 相同的
-
检测每个目录中的git状态:
git -C "<当前>" rev-parse --git-dir 2>/dev/null && echo "GIT" || echo "NOGIT" git -C "<未来>" rev-parse --git-dir 2>/dev/null && echo "GIT" || echo "NOGIT"
策略选择
| 当前 | 未来 | 策略 |
|---|---|---|
| git | git | 1 — git fetch + 合并基差异 |
| git | 非git | 2 — git diff --no-index |
| 非git | git | 2 — git diff --no-index |
| 非git | 非git | 3 — diff -rNu 后备方案 |
策略 1: 两者都是Git
# 一次性获取 — 不添加永久远程仓库
git -C "<当前>" fetch "<未来>" HEAD --no-tags
# 查找共同祖先
MERGE_BASE=$(git -C "<当前>" merge-base HEAD FETCH_HEAD)
# 生成从合并基到未来HEAD的差异
git -C "<当前>" diff "$MERGE_BASE" FETCH_HEAD
如果merge-base失败(没有共同历史),则回退到策略2。
策略 2: git diff --no-index
git diff --no-index "<当前>" "<未来>" -- . \
':!.git' ':!.git/**'
无论其中一个、两个或都没有目录包含.git/,此方法都有效。
策略 3: 普通diff
diff -rNu "<当前>" "<未来>" \
--exclude='.git' --exclude='node_modules' --exclude='.venv'
差异摘要
生成差异后,在应用之前显示摘要:
差异: <未来> → <当前>
策略: <1|2|3>
文件更改: 12 (+340 / -85)
已修改: internal/cli/pad.go, docs/getting-started.md, ...
已添加: internal/crypto/aes.go
已删除: hack/old-script.sh
始终在应用前显示此摘要并要求确认。
冲突检查
将差异文件与当前目录中的未提交更改进行交叉引用:
git -C "<当前>" status --porcelain
如果有任何文件同时出现在差异和工作树更改中, 则明确警告:
警告: 这些文件同时具有本地更改和传入更改:
- internal/cli/pad.go (本地已修改 + 差异中已修改)
应用可能会导致冲突或覆盖本地工作。
询问用户如何继续:仍然应用、跳过冲突文件、 或中止。
应用差异
-
首先进行试运行 (策略 1/2):
git apply --check --stat <补丁文件>对于策略 3:
patch --dry-run -p0 < <补丁文件> -
应用 (用户确认后):
git apply <补丁文件> # 策略 1/2 patch -p0 < <补丁文件> # 策略 3 -
如果应用失败并出现冲突,报告哪些块失败,并 提供使用
--reject应用的选项,以便用户可以手动解决。
选择性应用
用户可以选择特定文件。重新生成针对这些文件的差异:
- 策略 1:
git -C "<当前>" diff "$MERGE_BASE" FETCH_HEAD -- 文件1 文件2 - 策略 2:
git diff --no-index "<当前>/文件1" "<未来>/文件1" - 策略 3:
diff -u "<当前>/文件1" "<未来>/文件1"
应用后
提醒用户:
- 使用
git diff审查更改 - 更改未暂存 — 满意时提交
- 如果从工作树借用,考虑使用
ctx-worktree teardown进行清理
防护措施
- 始终预览 — 在未显示差异摘要之前绝不应用
- 无永久远程仓库 — 策略1使用一次性获取,不添加
git remote add - 尊重本地工作 — 每次应用前进行冲突检查
- 排除噪音 — 始终排除
.git/、node_modules/、.venv/ - 可逆 — 如果当前是git仓库,所有更改都可以通过
git checkout .撤销
质量检查清单
- [ ] 两个目录已验证为存在且属于同一项目
- [ ] 两个目录中均已检测到Git状态
- [ ] 从表格中选择了正确的策略
- [ ] 在应用前向用户显示了差异摘要
- [ ] 针对本地工作树更改运行了冲突检查
- [ ] 在实际应用前试运行通过
- [ ] 用户在应用更改前已确认