From 5c88af76176f480adf325af70d37420cd8b8491d Mon Sep 17 00:00:00 2001 From: nothariharan <228516901+nothariharan@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:47:56 +0100 Subject: [PATCH] fix(hooks): skip post-checkout rebuild when PREV_HEAD equals NEW_HEAD (#2421) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git checkout -b reports a branch switch (flag=1) but passes the same SHA for prev and new HEAD, so the post-checkout hook fired a full changed_paths-less rebuild — the most expensive graphify op — on essentially every new branch. Add a POSIX-sh guard that exits 0 when PREV_HEAD == NEW_HEAD; a real branch switch (PREV != NEW) still rebuilds. Co-Authored-By: Claude Opus 4.8 (1M context) --- graphify/hooks.py | 4 ++++ tests/test_hooks.py | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/graphify/hooks.py b/graphify/hooks.py index 5be58d12..d284903e 100644 --- a/graphify/hooks.py +++ b/graphify/hooks.py @@ -355,6 +355,10 @@ if [ "$BRANCH_SWITCH" != "1" ]; then exit 0 fi +# A no-op checkout (e.g. `git checkout -b` with no start point) reports a +# branch switch but leaves the tree unchanged ΓÇö nothing to rebuild (#2421). +[ "$PREV_HEAD" = "$NEW_HEAD" ] && exit 0 + # Only run if graphify-out/ exists (graph has been built before) if [ ! -d "graphify-out" ]; then exit 0 diff --git a/tests/test_hooks.py b/tests/test_hooks.py index 9fffb32b..dfc8f516 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -614,6 +614,15 @@ def test_hooks_honor_skip_env(name, script): ) +def test_checkout_hook_skips_same_head_noop(): + """`git checkout -b` with no start point passes identical PREV/NEW heads. + Rebuild must short-circuit ΓÇö PREV_HEAD/NEW_HEAD were previously assigned + and never read (#2421 / leftover from #1809).""" + assert "PREV_HEAD=$1" in _CHECKOUT_SCRIPT + assert "NEW_HEAD=$2" in _CHECKOUT_SCRIPT + assert '[ "$PREV_HEAD" = "$NEW_HEAD" ] && exit 0' in _CHECKOUT_SCRIPT + + @pytest.mark.parametrize("name,script", _HOOK_SCRIPTS) def test_hooks_skip_linked_worktrees(name, script): """Both hooks must short-circuit in a linked worktree (git-dir != common-dir),