Skip to content

Fetch only the pinned commit of a git source-repository-package - #12531

Open
ulysses4ever wants to merge 4 commits into
haskell:masterfrom
ulysses4ever:vcs/shallow-tag-fetch-12523
Open

ulysses4ever wants to merge 4 commits into
haskell:masterfrom
ulysses4ever:vcs/shallow-tag-fetch-12523

Conversation

@ulysses4ever

@ulysses4ever ulysses4ever commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #12523: a source-repository-package from git now downloads only the commit that its tag or branch names, instead of that commit's whole history. Below is the longer story from your friendly AI engine (Opus 5.5).


Since #10254 (cabal 3.16), cabal clones with --depth=1, which gets the tip of the default branch, and then runs git fetch origin <tag> without --depth. In a shallow repository, that fetches the whole history of the pinned commit, so unless the pin is the tip, the shallow clone saves little. This passes --depth=1 to that fetch as well.

A complete checkout stays complete. Git ignores --depth when it clones a plain local path, and such a checkout is what the other stanzas for the same repository borrow objects from through --reference (#12296). A --depth=1 fetch would make it shallow and stop the sharing, so the fetch passes --depth=1 only when .git/shallow exists.

Packages now see only the pinned commit. Tags were already missing before this change: on master, git describe fails in the checkout too. A package that needs the history or the tags can use post-checkout-command: git fetch --depth=2147483647 --tags, which the docs now describe. git fetch --unshallow would make the next sync fail, because by then the checkout is complete.

Testing

  • The git tests in cabal-install:test:long-tests: syncSourceRepos, shallow, distinct tags now pins a tag with two commits of history and checks that every checkout has one commit; the local-path case checks for the full history. Without the change, the test fails with expected: 1, but got: 2.
  • End to end, with a project pinning a commit two behind the tip of a repository over file://: master's checkout has 3 commits and this branch's has 1. With the post-checkout-command above, the checkout has 3 and git describe works, also after the pin moves to the tip; with git fetch --unshallow --tags instead, that second sync fails with exit code 128.

Not covered: submodules are still fetched in full, and so is the default branch on later syncs. Abbreviated hashes still fail, as they did before (#10605).


QA Notes

In an empty directory, write a cabal.project with

optional-packages: ./*.cabal

source-repository-package
  type: git
  location: https://github.com/haskell/containers
  tag: <the full hash of a commit well behind the default branch>
  subdir: containers

and run cabal build --dry-run containers. Then git -C dist-newstyle/src/contain*/ rev-list --count HEAD prints 1; with cabal 3.16 to 3.18, it prints the number of commits up to the pinned one.

🤖 Generated with Claude Code

https://claude.ai/code/session_0176vAefrw8jPKXdh9h1wKuj

A git source-repository-package is cloned with --depth=1, which gets the
tip of the default branch, and the commit that its tag or branch names is
then fetched without --depth. In a shallow repository that fetches the
whole history of that commit, so unless the pin is the tip, the shallow
clone saves little (haskell#12523).

Pass --depth=1 to that fetch too, but only in a shallow checkout. A
checkout cloned from a plain local path, where git ignores --depth, stays
complete, so that the other checkouts of the repository can still borrow
its objects through --reference.

A package that needs the history or the tags can fetch them with
post-checkout-command; the docs now say how.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0176vAefrw8jPKXdh9h1wKuj
ulysses4ever and others added 2 commits November 5, 2026 09:52
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0176vAefrw8jPKXdh9h1wKuj
Why only in a shallow checkout: a complete checkout, which is what git
makes when it clones a plain local path (it ignores --depth there), stays
complete, so that the other checkouts of the repository can still borrow
its objects through --reference (haskell#12296).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0176vAefrw8jPKXdh9h1wKuj
@ulysses4ever
ulysses4ever marked this pull request as ready for review November 5, 2026 15:18
@ulysses4ever ulysses4ever added the 1️⃣ more approval needed Set by Mergify: has one of the two required approvals label Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI-assisted attention: needs-review 1️⃣ more approval needed Set by Mergify: has one of the two required approvals

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Partial clone for Git repositories in cabal.project

2 participants