Only count remote-unreachable commits as local work in finish guard
ci / test (pull_request) Successful in 2m19s

Why: 本地 main 停在 origin/main 顶端(克隆默认态)在 pin 为 feature 顶端时不在 pin
历史内,--branches 直判仍会误阻(本 worktree 自身收尾实测踩到)。
Evidence: 第五例回归(本地默认分支+克隆 reflog 不阻)全绿;五例套件+全套治理回归
GOVERNANCE-SUITE-OK;worktree 实际 finish 通过即端到端自证。
Impact: local_work_outside 候选提交先过 --not --remotes 过滤(远端可达即已保全);
stash 仍恒算本地独有。
This commit is contained in:
2026-10-05 15:05:54 +00:00
parent c62a410e5a
commit a5f0ca107d
3 changed files with 65 additions and 7 deletions
File diff suppressed because one or more lines are too long
+10 -7
View File
@@ -107,16 +107,19 @@ def local_work_outside(child, expected):
"""2026-10-05 修复:pinned-history 检查此前用 --all --reflog,把 refs/remotes 也
计入——pin 在 feature 顶端的子仓因 origin/main 不在 pin 历史内而永远无法 finish
(实测被迫删远端引用+清 reflog 绕过,损害现场)。只认「本地独有」工作:
本地分支、stash、以及 HEAD 的 reflog(最近检出轨迹里的独有提交);
refs/remotes 一律不算——远端有副本即已保全。"""
if git(child, "rev-list", "--branches", "--not", expected).strip():
return True
if git(child, "stash", "list").strip():
return True
不在任何远端跟踪引用历史内的提交才算。克隆默认分支停在 origin/main 顶端、
reflog 里的检出轨迹等「远端有副本」的状态一律不算;stash 恒为本地独有。"""
candidates = git(child, "rev-list", "--branches", "--not", expected).split()
for line in git(child, "reflog", "show", "HEAD", "--format=%H").splitlines():
tip = line.strip()
if tip and git(child, "rev-list", "-1", tip, "--not", expected).strip():
if tip:
candidates.append(tip)
for tip in dict.fromkeys(candidates): # 去重保序
# 远端任一引用可达 ⇒ 已保全,不算本地独有
if git(child, "rev-list", "-1", tip, "--not", "--remotes").strip():
return True
if git(child, "stash", "list").strip():
return True
return False
+17
View File
@@ -758,6 +758,23 @@ class FinishGuardFixTests(unittest.TestCase):
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertFalse(wt.exists())
def test_local_default_branch_at_origin_main_does_not_block(self):
"""克隆默认分支停在 origin/main 顶端(pin 为 feature 顶端时不在其历史内)
且 HEAD reflog 含克隆/检出轨迹——均为远端有副本的状态,不得阻断 finish。"""
self.add_submodule_pinned_off_main()
wt = self.worktree()
self.git(wt, "submodule", "update", "--init", "--recursive")
(self.repo / "tracked").write_text("implementation done\n")
self.git(self.repo, "add", "-A")
self.git(self.repo, "commit", "-q", "-m", "done")
self.git(self.repo, "push", "-q", "origin", "feature/guard")
self.git(self.repo, "merge", "--no-ff", "-q", "-m", "Merge feature/guard", "feature/guard")
self.git(self.repo, "push", "-q", "origin", "main")
result = self.task(wt, "finish", check=False)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertFalse(wt.exists())
def test_local_unique_commit_still_preserved(self):
self.add_submodule_pinned_off_main()
wt = self.worktree()