Skip to content

Latest commit

Β 

History

History
364 lines (319 loc) Β· 21.2 KB

BLACKSMITH.md

File metadata and controls

364 lines (319 loc) Β· 21.2 KB

Blacksmith Git Mirror Cache

This document explains how the Blacksmith-optimized checkout action accelerates repository cloning through persistent git mirror caching.

How It Works

                                    BLACKSMITH VM
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                                                                         β”‚
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
    β”‚   β”‚                     STICKY DISK (Persistent)                    β”‚   β”‚
    β”‚   β”‚                    /blacksmith-git-mirror/v1/                   β”‚   β”‚
    β”‚   β”‚                                                                 β”‚   β”‚
    β”‚   β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
    β”‚   β”‚   β”‚              BARE MIRROR (owner-repo.git)               β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚                                                         β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚  objects/                                               β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚    β”œβ”€β”€ pack/                                            β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚    β”‚   β”œβ”€β”€ pack-abc123.pack   (compressed objects)      β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚    β”‚   └── pack-abc123.idx    (pack index)              β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚    └── info/                                            β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚  refs/                                                  β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚    β”œβ”€β”€ heads/   (all branches)                          β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚    └── tags/    (all tags)                              β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚                                                         β”‚   β”‚   β”‚
    β”‚   β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
    β”‚   β”‚                            β”‚                                    β”‚   β”‚
    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
    β”‚                                β”‚                                        β”‚
    β”‚                                β”‚ alternates                             β”‚
    β”‚                                β–Ό                                        β”‚
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
    β”‚   β”‚                      WORKSPACE CHECKOUT                         β”‚   β”‚
    β”‚   β”‚                   $GITHUB_WORKSPACE/repo/                       β”‚   β”‚
    β”‚   β”‚                                                                 β”‚   β”‚
    β”‚   β”‚   .git/                                                         β”‚   β”‚
    β”‚   β”‚     β”œβ”€β”€ objects/                                                β”‚   β”‚
    β”‚   β”‚     β”‚   └── info/                                               β”‚   β”‚
    β”‚   β”‚     β”‚       └── alternates ──► /blacksmith-git-mirror/.../      β”‚   β”‚
    β”‚   β”‚     β”‚                                objects                    β”‚   β”‚
    β”‚   β”‚     β”œβ”€β”€ refs/                                                   β”‚   β”‚
    β”‚   β”‚     └── HEAD                                                    β”‚   β”‚
    β”‚   β”‚                                                                 β”‚   β”‚
    β”‚   β”‚   src/                                                          β”‚   β”‚
    β”‚   β”‚   README.md                                                     β”‚   β”‚
    β”‚   β”‚   ...                                                           β”‚   β”‚
    β”‚   β”‚                                                                 β”‚   β”‚
    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
    β”‚                                                                         β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Checkout Flow

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚   Workflow Run   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     No      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Is Blacksmith   │────────────►│  Standard clone  β”‚
    β”‚   environment?   β”‚             β”‚   from GitHub    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚ Yes
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Request sticky  β”‚ ◄─────── gRPC to VM agent (192.168.127.1:5557)
    β”‚   disk from VM   β”‚           GetStickyDisk(key: "owner-repo")
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Mount disk at   β”‚
    β”‚  /blacksmith-    β”‚
    β”‚    git-mirror/   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     No      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Mirror exists?  │────────────►│  git clone       β”‚
    β”‚                  β”‚             β”‚    --mirror      β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚ Yes                            β”‚
             β–Ό                                β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”‚
    β”‚  git fetch       β”‚                      β”‚
    β”‚    --prune       β”‚                      β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β”‚
             β”‚                                β”‚
             β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  git init in     β”‚
    β”‚   workspace      β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Write alternates β”‚ ◄─────── .git/objects/info/alternates
    β”‚ file pointing to β”‚           points to mirror/objects
    β”‚     mirror       β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  git fetch from  β”‚ ◄─────── Objects already in mirror
    β”‚     origin       β”‚           are NOT re-downloaded
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  git checkout    β”‚
    β”‚   requested ref  β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     Yes     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  dissociate:     │────────────►│  git repack -a   β”‚
    β”‚     true?        β”‚             β”‚  (copy objects)  β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚ No                             β”‚
             β–Ό                                β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”‚
    β”‚  Checkout done!  β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚  (fast path)     β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why This Is Fast

Traditional Clone (No Cache)

GitHub ──────────────────────────────────────────────► Workspace
        Download ALL objects every time
        (100MB+ for large repos)

With Blacksmith Mirror Cache

                    First Run:
GitHub ──────────────────────────────────────────────► Mirror (persistent)
        Download ALL objects once                          β”‚
                                                          β”‚ alternates
                    Subsequent Runs:                       β–Ό
GitHub ─── fetch delta only (new commits) ───────────► Mirror ───► Workspace
        (typically KB to small MB)                     (objects shared,
                                                        not copied)

Key optimizations:

  1. Bare mirror: Stores all branches/tags, no working tree overhead
  2. Persistent storage: Survives across workflow runs via sticky disk
  3. Alternates: Workspace references mirror objects without copying
  4. Delta fetch: Only new commits since last run are downloaded

Cache Failure Semantics

The implementation is designed to be fail-safe - cache failures never break your workflow:

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ setupCache()     β”‚
    β”‚ or ensureMirror()β”‚
    β”‚    fails         β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ core.warning()   β”‚ ◄─────── "Blacksmith cache setup failed,
    β”‚ Log the error    β”‚           using standard checkout: <error>"
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ cacheInfo = null β”‚ ◄─────── Cache disabled for this run
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Standard clone   β”‚ ◄─────── Falls back to normal git clone
    β”‚ proceeds without β”‚           from GitHub (slower but works)
    β”‚    mirror        β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Failure scenarios handled:

  • gRPC connection to VM agent fails
  • Sticky disk unavailable
  • Mirror clone/fetch fails
  • Filesystem errors

Post-job cleanup also handles failures gracefully:

  • If unmount fails: warning logged, continues
  • If commit fails: warning logged, data may not persist (but workflow succeeded)

Garbage Collection

GC runs in the post-job cleanup phase to avoid impacting checkout performance or VM boot time.

    WORKFLOW TIMELINE
    ─────────────────────────────────────────────────────────────────────────────►
    β”‚                                                                            β”‚
    β”‚  VM Boot      Checkout (hot path)         User Steps        Post-job       β”‚
    β”‚    β”‚               β”‚                          β”‚                β”‚           β”‚
    β”‚    β–Ό               β–Ό                          β–Ό                β–Ό           β”‚
    β”‚  β”Œβ”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
    β”‚  β”‚Startβ”‚     β”‚setupCache β”‚            β”‚ build/test β”‚    β”‚  git gc    β”‚    β”‚
    β”‚  β”‚ VM  β”‚     β”‚ensureMirrorβ”‚            β”‚   etc.     β”‚    β”‚--prune=now β”‚    β”‚
    β”‚  β””β”€β”€β”€β”€β”€β”˜     β”‚(fetch only)β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  unmount   β”‚    β”‚
    β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β”‚  commit    β”‚    β”‚
    β”‚                   β”‚                                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
    β”‚                   β”‚                                            β”‚           β”‚
    β”‚              NO GC HERE                              GC RUNS HERE          β”‚
    β”‚           (fast checkout)                          (after user code)       β”‚
    β”‚                                                                            β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

What GC Does

We run git gc --prune=now which orchestrates:

  • Repack: Consolidates all reachable objects into optimized pack files
  • Prune: Removes all unreachable loose objects immediately
  • Pack-refs: Compresses refs for faster lookups
  • Reflog expire: Cleans up old reflog entries
    Before GC:                              After GC:
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ pack-aaa.pack  (100MB)     β”‚          β”‚ pack-consolidated.pack     β”‚
    β”‚ pack-bbb.pack  (5MB)       β”‚          β”‚ (95MB - only reachable     β”‚
    β”‚ pack-ccc.pack  (3MB)       β”‚    ──►   β”‚  objects, deduplicated)    β”‚
    β”‚ loose objects  (2MB)       β”‚          β”‚                            β”‚
    β”‚ unreachable    (10MB)      β”‚          β”‚ Unreachable: removed       β”‚
    β”‚                            β”‚          β”‚                            β”‚
    β”‚ Total: ~120MB              β”‚          β”‚ Total: ~95MB               β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why --prune=now Is Safe

Using --prune=now (immediate pruning) is safe in our context because:

  1. Post-job timing: GC runs after all user workflow steps complete
  2. No concurrent writes: The mirror is idle during cleanup
  3. Single consumer: Only the checkout action uses the mirror

The default git gc uses --prune=2.weeks.ago to protect against concurrent processes, but that's unnecessary here.

Why Post-Job GC?

Phase Operation Impact if GC ran here
VM Boot Mount sticky disk Would delay job start
Checkout git fetch Would delay checkout
User Steps build, test, etc N/A (GC not applicable)
Post-Job GC + commit No user impact

Disk Size Growth

With GC, the mirror is bounded to approximately the size of reachable objects:

  • Repository history: All reachable commits, trees, blobs
  • All branches and tags: Objects referenced by any ref

Unreachable objects (from force-pushes, deleted branches) are removed immediately.

Syncing with Upstream

The mirror stays in sync with GitHub through incremental fetches:

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                         BARE MIRROR                            β”‚
    β”‚                                                                 β”‚
    β”‚  Before fetch:                   After fetch:                   β”‚
    β”‚  refs/heads/main β†’ abc123        refs/heads/main β†’ def456      β”‚
    β”‚  refs/heads/feature β†’ xyz789     refs/heads/feature β†’ (deleted)β”‚
    β”‚                                  refs/heads/newbranch β†’ ghi012 β”‚
    β”‚                                                                 β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚
                                  β”‚  git fetch --prune origin
                                  β”‚
                                  β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                         WHAT HAPPENS                            β”‚
    β”‚                                                                 β”‚
    β”‚  1. Download new commits (def456, ghi012)                       β”‚
    β”‚  2. Update refs/heads/main to point to def456                   β”‚
    β”‚  3. Delete refs/heads/feature (--prune removes deleted refs)    β”‚
    β”‚  4. Create refs/heads/newbranch pointing to ghi012              β”‚
    β”‚  5. Objects from deleted branch xyz789 remain (no GC)           β”‚
    β”‚                                                                 β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

What syncs:

  • All branches (refs/heads/*)
  • All tags (refs/tags/*)
  • New commits and their objects

What gets cleaned up (in post-job GC):

  • Redundant pack files (consolidated into single optimized pack)
  • All unreachable objects (removed immediately via git gc --prune=now)

The dissociate Option

When to use dissociate: true:

- uses: useblacksmith/checkout@v6
  with:
    dissociate: true  # Copy objects locally
    WITHOUT dissociate (default):          WITH dissociate: true:
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚      Docker Container      β”‚         β”‚      Docker Container      β”‚
    β”‚                            β”‚         β”‚                            β”‚
    β”‚   .git/objects/info/       β”‚         β”‚   .git/objects/            β”‚
    β”‚     alternates ──────────┐ β”‚         β”‚     pack/                  β”‚
    β”‚                          β”‚ β”‚         β”‚       pack-xxx.pack        β”‚
    β”‚                          β–Ό β”‚         β”‚     (all objects local)    β”‚
    β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”     β”‚                            β”‚
    β”‚                    β”‚ MOUNT NOT β”‚     β”‚   No external dependency   β”‚
    β”‚                    β”‚ AVAILABLE β”‚     β”‚                            β”‚
    β”‚                    β”‚   β•³ β•³ β•³   β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚   git commands fail!         β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use dissociate: true when:

  • Running Docker-based actions that don't mount the cache volume
  • Building container images that include the git repository
  • Needing a fully self-contained checkout

Trade-off:

  • Slower checkout (must copy all objects)
  • Larger workspace (objects duplicated)
  • But works in isolated environments

Drop-in Compatibility

This action is a drop-in replacement for actions/checkout@v6:

# Before (standard GitHub Action)
- uses: actions/checkout@v6

# After (Blacksmith-optimized - just change the org)
- uses: useblacksmith/checkout@v6

Compatibility guarantees:

  • All existing inputs work identically
  • Only addition: optional dissociate input
  • Non-Blacksmith environments fall back to standard behavior
  • Cache failures fall back to standard clone