Skip to content

fix: avoid shallow-ifying full local clones#74

Merged
yannrouillard merged 1 commit into
mainfrom
fix/preserve-clone-shallowness
Apr 24, 2026
Merged

fix: avoid shallow-ifying full local clones#74
yannrouillard merged 1 commit into
mainfrom
fix/preserve-clone-shallowness

Conversation

@yannrouillard
Copy link
Copy Markdown
Contributor

@yannrouillard yannrouillard commented Apr 24, 2026

Summary

Follow-up to #73. v0.58.0's git fetch --no-tags --depth=1 origin $TARGET_BRANCH runs unconditionally from the pre-push hook. On a full local clone (the typical dev setup), --depth=1 writes a .git/shallow file and truncates origin/$TARGET_BRANCH to a single commit, leaving the developer's local main detached from prior history. After a git push, users see weird states — rebases produce unexpected conflicts because the ancestor commits previously visible under origin/main have disappeared.

Reported by @tmaurin in the same Slack thread that triggered #73 (recovery: git fetch --unshallow). @dhalmschlager correctly diagnosed the mechanism and suggested the guard.

Reproduction (5 lines of shell on a full clone)

git clone <remote> /tmp/test && cd /tmp/test
test -f .git/shallow && echo "shallow BEFORE" || echo "not shallow BEFORE"
git fetch --no-tags --depth=1 origin main   # what v0.58.0 runs
test -f .git/shallow && echo "shallow AFTER" || echo "not shallow AFTER"
git log origin/main --oneline | wc -l       # now 1 instead of full history

Fix

Gate --depth=1 on whether the clone is already shallow:

if [ -f "$(git rev-parse --git-dir)/shallow" ]; then
    fetch_depth="--depth=1"
else
    fetch_depth=""
fi
git fetch --no-tags $fetch_depth origin "$TARGET_BRANCH"

CI (starts shallow via actions/checkout@v6 defaults) keeps the fast --depth=1 path; local full clones fetch normally and preserve their history.

Test plan

  • New regression test in tests/test_git_branch_linearity.sh: runs the hook on a full local clone and asserts both that .git/shallow is absent and that origin/main retains its full 3-commit history.

  • Confirmed the new test fails against v0.58.0 (origin/main has 1 commits, expected 3) and passes with this fix.

  • Existing 4 tests from fix: make git-branch-linearity.sh work with shallow CI clones #73 still pass (6/6 total).

  • Local validation on the real supply-demand-lng repo at the commit that originally failed (SHA 2778d4937c):

    Scenario .git/shallow after hook origin/main commits after hook
    Full clone + v0.58.0 (current) ❌ created 278 → 1 (bug reproduced)
    Full clone + this fix ✅ absent 278 → 278 (preserved)
    Shallow clone + this fix + GITHUB_HEAD_REF ✅ stays shallow exit 0
  • End-to-end CI validation in the real repo that was broken. Reopened the failing state of PR #122 (SHA 2778d4937c) with a single change — rev: v0.57.0 → this PR's fix commit — then ran the pre-commit workflow in both actions/checkout configurations:

    Configuration actions/checkout Result
    Shallow clone (default) fetch-depth: 1 Check for git branch linearity... Passed (job)
    Full clone fetch-depth: 0 Check for git branch linearity... Passed (job)

    Validation PRs (now closed): Kpler/supply-demand-lng#124 (shallow) and Kpler/supply-demand-lng#125 (full).

v0.58.0's `git fetch --no-tags --depth=1 origin $TARGET_BRANCH` runs
unconditionally from the pre-push hook. On a full local clone (the typical
dev setup), `--depth=1` writes a `.git/shallow` file and truncates
`origin/$TARGET_BRANCH` to a single commit, leaving the developer's local
main detached from prior history. Users then hit weird states after a
`git push` — rebases produce unexpected conflicts because the ancestor
commits visible under origin/main have disappeared.

Reported by @tmaurin on the same Slack thread as PR #73; the recovery is
`git fetch --unshallow`, but we should not put the developer in that
state in the first place.

Gate `--depth=1` on whether the clone is already shallow: CI (which
starts shallow via `actions/checkout` defaults) keeps the fast path;
local full clones fetch normally and preserve their history.

Add a regression test that runs the hook on a full local clone and
asserts both that `.git/shallow` is absent and that `origin/main`
retains its full history. Confirmed: the new test fails against v0.58.0
and passes with this fix.
@yannrouillard yannrouillard requested a review from a team as a code owner April 24, 2026 18:47
@yannrouillard yannrouillard merged commit a0fc19d into main Apr 24, 2026
2 checks passed
@yannrouillard yannrouillard deleted the fix/preserve-clone-shallowness branch April 24, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant