Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 22, 2025

Problem

When performing a shallow clone with gix clone --depth 1, gitoxide was fetching all branches using the wildcard refspec +refs/heads/*:refs/remotes/origin/*, resulting in significantly larger repositories compared to Git. For example, cloning the gitoxide repository itself produced a ~130MB .git directory with gitoxide vs ~70MB with Git.

Root Cause

The refspec in gix/src/clone/fetch/mod.rs was hardcoded to always use the wildcard pattern +refs/heads/*:refs/remotes/origin/*, regardless of whether the clone was shallow or not. This meant all branches were fetched and stored, even though shallow clones typically only need a single branch.

Solution

Modified the clone logic to detect shallow clones and automatically use single-branch refspecs when appropriate, matching Git's behavior:

  • When ref_name is specified: Uses a refspec targeting that specific branch (e.g., +refs/heads/feature:refs/remotes/origin/feature)
  • When ref_name is not specified: Attempts to detect the remote's default branch:
    • For Protocol V1: Extracts HEAD target from handshake
    • For Protocol V2 or fallback: Uses init.defaultBranch config or defaults to "main"
  • Result: Persistent refspec like +refs/heads/main:refs/remotes/origin/main instead of wildcard

This only applies when no custom configure_remote callback is provided, preserving flexibility for advanced use cases.

Results

  • ✅ Shallow clones now use single-branch refspecs matching Git's behavior
  • ✅ Repository size reduced by ~62% (130MB → 49MB for gitoxide repo)
  • ✅ All existing tests pass, new test added to verify correct refspec
  • ✅ Proper refspec stored in .git/config for future fetches

Note: The remaining size difference with Git (49MB vs 6.6MB) is due to tag fetching behavior - gitoxide currently fetches all tags by default while Git doesn't for shallow clones. This is a separate behavioral difference that could be addressed in a future PR.

Fixes #2227

Original prompt

Fix the refspec used in conjunction with shallow cloning, using #2227 as reference.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix refspec for shallow cloning Fix refspec for shallow clones to use single-branch instead of wildcard Oct 22, 2025
Copilot AI requested a review from Byron October 22, 2025 16:25
Copilot finished work on behalf of Byron October 22, 2025 16:25
@Byron Byron force-pushed the copilot/fix-refspec-for-shallow-clone branch from 7bb2283 to b05f8ba Compare October 24, 2025 05:23
When doing shallow clones (depth != NoChange), it now uses a single-branch
refspec instead of fetching all branches. This matches Git's behavior
and significantly reduces the repository size for shallow clones.

For shallow clones:
- If ref_name is specified: uses that branch
- Otherwise: attempts to detect from Protocol V1 handshake or falls
  back to init.defaultBranch config or "main"

This addresses issue #2227 where `gix clone --depth 1` was creating
repositories ~130MB vs Git's ~70MB due to fetching all branches.

Co-authored-by: Byron <63622+Byron@users.noreply.github.com>
@Byron Byron force-pushed the copilot/fix-refspec-for-shallow-clone branch from b05f8ba to da114c1 Compare October 24, 2025 05:23
@Byron
Copy link
Member

Byron commented Oct 24, 2025

I must say that I am very impressed by this PR!

Review notes

  • the test fails when run with the version from main.
  • refactor

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.

Repo cloned by gix clone --depth 1 is larger than git clone --depth 1

2 participants