You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
make hooksで入る .git/hooks/pre-commit(make check実行)や、同様に make check/pytest を呼ぶ pre-push フックの内部から pytest を実行すると、一部テストがtmpディレクトリ内で行う git init/git commit/git config のnested subprocess呼び出しが、実リポジトリのgit状態を書き換えてしまう。観測した実害:
実リポジトリの .git/config に core.bare = true と、テスト用の user.email = test@example.com / user.name = test が書き込まれる(git status が fatal: this operation must be run in a work tree で全面的に失敗するようになる)。
実リポジトリの index が、nested コミットの内容(tmpフィクスチャ側のファイル状態)で上書きされ、git status/git diff HEAD が実際には存在する全ファイルを "deleted" として表示する(ディスク上のファイル自体は無事、index のみ破壊)。
破壊された index に対して再度 git commit/git push すると、今度は実リポジトリの pre-commit フック自体が nested 側から誤発火し、tmp フィクスチャに Makefile が無いため make: *** No rule to make target \check'` で nested コミットが失敗 → 該当テストが失敗する。
再現手順
make hooks で pre-commit フックを導入(または同等の make check を呼ぶ pre-push フックがある状態)。
何らかの変更を git commit(または git push)し、フック経由で make check → pytest が走る。
上記テストの _git/_run ヘルパー(tests/test_file_renames.py:45、tests/test_core_ingest.py:211、tests/test_db.py:1860、tests/test_eval_cmd.py:134 他)で subprocess.run に渡す env から GIT_DIR・GIT_WORK_TREE・GIT_INDEX_FILE・GIT_PREFIX・GIT_COMMON_DIR 等の GIT_* 継承変数を明示的に除去してから呼び出す(env={k: v for k, v in os.environ.items() if not k.startswith("GIT_") or k in ("GIT_AUTHOR_DATE", "GIT_COMMITTER_DATE")} のような allowlist/denylist)。ヘルパーが複数ファイルに重複しているため、共通の conftest.py フィクスチャ/ヘルパーに集約するのが望ましい。
概要
make hooksで入る.git/hooks/pre-commit(make check実行)や、同様にmake check/pytestを呼ぶ pre-push フックの内部から pytest を実行すると、一部テストがtmpディレクトリ内で行うgit init/git commit/git configのnested subprocess呼び出しが、実リポジトリのgit状態を書き換えてしまう。観測した実害:.git/configにcore.bare = trueと、テスト用のuser.email = test@example.com/user.name = testが書き込まれる(git statusがfatal: this operation must be run in a work treeで全面的に失敗するようになる)。git status/git diff HEADが実際には存在する全ファイルを "deleted" として表示する(ディスク上のファイル自体は無事、index のみ破壊)。git commit/git pushすると、今度は実リポジトリの pre-commit フック自体が nested 側から誤発火し、tmp フィクスチャにMakefileが無いためmake: *** No rule to make target \check'` で nested コミットが失敗 → 該当テストが失敗する。再現手順
make hooksで pre-commit フックを導入(または同等のmake checkを呼ぶ pre-push フックがある状態)。git commit(またはgit push)し、フック経由でmake check→pytestが走る。tests/test_file_renames.py(_make_git_repo_with_rename等)、tests/test_core_ingest.py(test_ingest_resolves_symbols_against_touch_time_git_blob_not_live_disk等)、tests/test_db.py::test_backfill_touch_time_symbol_edges_*、tests/test_eval_cmd.py::test_eval_gen_writes_symbol_recall_dataset。これらは共通してtmp_path配下でsubprocess.run(["git", "init"/"config"/"commit", ...], cwd=tmp_path)を行うが、呼び出し元プロセスの環境をそのまま継承している。git statusを実行すると壊れている。根本原因(推定)
git はフック(pre-commit/pre-push)を起動する際、
GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_PREFIX等を子プロセスの環境変数として export する。フック →make check→pytest→ 上記テストのsubprocess.runはこの環境をそのまま継承するため、テストがcwd=tmp_pathでgit initした「つもり」でも、後続のgit commit/git configが継承されたGIT_DIR(実リポジトリの gitdir)を見てしまい、実リポジトリの config/index に対して操作してしまう。影響
make hooksを実行した全コントリビューターが対象。フック経由で日常的なgit commit/git pushのたびに発火しうる。core.bare・index が静かに破壊される。ディスク上のファイル自体は無事(git reset --mixed HEAD+git config修正で復旧可能)だが、気づかずにgit commit --amend/git reset --hard等を打つと実データ損失になり得る。make check自体が誤って失敗し、CI/ローカル双方で原因不明のテスト失敗として現れる(本Issueの発見経緯: アーキテクチャ境界の歪み: adapters 多義語 / persistence→harness 層破り / cli __init__ docstring ドリフト #39 のPR作成中にgit commit→git pushで2回連続発生)。修正案
上記テストの
_git/_runヘルパー(tests/test_file_renames.py:45、tests/test_core_ingest.py:211、tests/test_db.py:1860、tests/test_eval_cmd.py:134他)でsubprocess.runに渡すenvからGIT_DIR・GIT_WORK_TREE・GIT_INDEX_FILE・GIT_PREFIX・GIT_COMMON_DIR等のGIT_*継承変数を明示的に除去してから呼び出す(env={k: v for k, v in os.environ.items() if not k.startswith("GIT_") or k in ("GIT_AUTHOR_DATE", "GIT_COMMITTER_DATE")}のような allowlist/denylist)。ヘルパーが複数ファイルに重複しているため、共通のconftest.pyフィクスチャ/ヘルパーに集約するのが望ましい。発見経緯
issue #39 (PR #45) 作業中に
git commit→git pushで2回連続再現。実リポジトリの.git/configは手動で復旧済み(core.bare=false、テスト由来のuser.*削除、git reset --mixed HEADで index復旧)。