How do you move a Git LFS repository to Crab?
Use the transfer bridge when commit identity must stay stable. Rewrite history only when native chunk reuse is worth a coordinated cutover.
Suppose models/encoder.safetensors is an 8 GB LFS file used by developers, CI, and old release tags.
Crab gives that repository two paths:
- Bridge: keep the LFS pointer and commit IDs; invoke Crab's local standalone transfer agent, which accesses the Crab object store directly.
- Convert: replace selected LFS pointers with native Crab pointers; rewrite affected commits.
These are different migrations. Pick the boundary before picking the command.
IDENTITY LAB / 8 GB MODEL / SELECT A PATH
What actually changes?
Git LFS owns the transfer route
version https://git-lfs.github.com/spec/v1 oid sha256:91ae…b72c size 8589934592
COMMIT IDENTITY
TRANSFER ROUTE
Git LFS → LFS endpoint
STORAGE SHAPE
one 8 GB LFS object
First, prove the source is complete
Use a disposable clone. Do not learn that an old object is missing halfway through a rewrite.
git status --short
git remote -v
git lfs ls-files
crab lfs migrate info --pointers only --everythingCheck four things:
| Evidence | Why it matters |
|---|---|
| LFS object exists locally or remotely | A pointer cannot recreate missing bytes |
| Branch and tag inventory is complete | An old tag may be the only user of an object |
.gitattributes matches the intended paths | Filters decide which pointer format Git expects |
| CI and bootstrap scripts are known | They may call git lfs even when developers do not |
Hash a few representative files now. After migration, a fresh client should produce the same bytes.
shasum -a 256 models/encoder.safetensorsSigned commits and tags need a separate plan: rewritten Git objects get new IDs, so old signatures no longer describe them.
Path 1: keep LFS semantics, change the route
Install Crab as Git LFS’s custom transfer agent:
crab lfs install
crab lfs env
crab lfs fetch
crab lfs checkout
crab lfs fsckinstall configures the local transfer agent, LFS filters, and a pre-push
gate. Crab does not deploy an LFS gateway. Git still commits the standard LFS
pointer:
version https://git-lfs.github.com/spec/v1
oid sha256:91ae…b72c
size 8589934592That means:
- existing commits keep their IDs;
- tools that require LFS pointers can keep using them;
- rollback is a configuration change, not a ref rewrite;
- the stored unit is still the whole LFS object.
The last point matters. The bridge changes transport and ownership, but it does not turn an LFS object into Crab chunks. A slightly changed 8 GB model still has a new whole-file LFS object ID.
Test both directions. Push one new LFS object, then fetch it from a disposable clone with an empty local LFS cache. Reading old data alone does not prove that new writes use the Crab route.
Also test one machine without the Crab configuration. Decide whether that client should keep using the old endpoint or fail with a clear bootstrap instruction. An accidental mixed-client period is not a migration plan.
To remove Crab’s transfer configuration later:
crab lfs uninstallKeep the previous LFS endpoint available until supported refs no longer depend on it.
Path 2: convert to native Crab pointers
Use native conversion when chunk reuse, native hydration, and Crab’s storage layout justify new Git identities.
crab lfs migrate export \
--include '*.safetensors' \
--to-crab \
--everything \
--object-map ../lfs-to-crab.csvFor every matched LFS blob, Crab resolves the original bytes, creates native content and metadata, replaces the blob with a Crab pointer, updates tracking rules, and rewrites descendants.
version https://crab.dev/spec/v1
file-hash 4cb9…731a
size 8589934592The object map records old and new commit IDs. Keep it outside the rewritten clone so it survives a reset or replacement clone.
DESCENDANT MAP / MODEL FIRST APPEARS AT B
source only
model v1
model v2
release prep
COMMAND
crab lfs installA path pattern limits which blobs convert. Ref selection limits which history is rewritten. They solve different problems.
If the model first appears in commit B, converting that blob changes B and every selected descendant—even commits that never touch the model again. Branch protections, release records, submodules, and open work may all name the old IDs.
Partial conversion is possible, but it leaves two pointer systems in supported history. Document exactly which paths and refs remain LFS-backed, or choose one clean boundary.
Rehearse the failure, not just the command
Use an isolated Crab destination and the same branch/tag scope planned for production.
CUTOVER REHEARSAL / CHOOSE A FAILURE OR SUCCESS
New writes and cold reads both work
Inventory
LFS objects available
Upload
new object reaches Crab storage
Cold clone
empty cache fetches the object
Integrity
crab lfs fsck passes
A useful rehearsal has observable gates:
- Fetch the selected refs and resolve every required LFS object.
- Run the bridge or conversion against a separate destination prefix.
- Push to an isolated remote namespace.
- Clone with an empty cache on another machine or runner.
- Materialize files from the default branch and an old release tag.
- Compare hashes, run the real workload, and record old/new commit IDs.
For a native conversion, verify the repository as well as sample bytes:
git log --all --oneline --decorate
crab status
crab fsckCheck that every selected ref exists at its mapped ID, parent relationships preserve the intended topology, tracking rules match each historical pointer format, and every remaining LFS pointer still has a supported source.
Byte equality proves the migration copied data correctly. A build, training smoke test, or model load proves automation still finds it.
Cut over only after an independent client passes
The bridge can roll out gradually if every supported client has the transfer configuration. A native rewrite needs a write freeze and one coordinated publication event.
For native cutover:
- Announce the freeze and preserve the final old refs.
- Run the rehearsed conversion from the final production state.
- Verify hashes, topology, attributes, and object closure.
- Publish mapped refs under the agreed protection exception.
- Update CI, release records, branch protections, and submodule references.
- Have an independent clean client hydrate and run the workload.
- Reopen writes only after that client passes.
Contributors with unpushed work need a backup ref and a deliberate rebase or cherry-pick onto mapped history. Avoid blanket “force pull” instructions: they can destroy unrelated work.
Retire the old endpoint later
A successful migration proves the new path. It does not authorize immediate deletion of the old LFS objects.
Keep the old refs, object inventory, and commit map through the rollback window. Remove old storage only after supported tags, CI, releases, and contributor recovery no longer need it—and run that deletion through its own preview and approval.
See the crab lfs reference for exact options before a rehearsal.
KNOWLEDGE PROOF
Check the decision, not your memory.
Which migration path keeps existing LFS pointer blobs and commit IDs unchanged?