Lab: Git LFS, recovery, and safe history repair
Outcome
Use a disposable repository to track a binary with Git LFS, inspect the committed pointer, recover a deleted file locally, and identify when a shared-history repair requires coordination. This lab never uses a real secret, a production remote, or an irreversible rewrite.
Before you begin
Create a throwaway local repository and install Git LFS from its official distribution or your package manager. Confirm it before proceeding:
git lfs install
git init azlearn-lfs && cd azlearn-lfs
git config user.name 'Training User'
git config user.email '[email protected]'git-fat is historical/tool-selection context, not the path this lab uses. Use Git LFS where your Git host supports it; use a package registry or release asset when you need versioned distribution rather than source-tree storage.
Do
-
Create a harmless binary-sized file and track its type before adding it:
mkdir assets dd if=/dev/zero of=assets/demo.bin bs=1M count=2 git lfs track '*.bin' git add .gitattributes assets/demo.bin git commit -m 'Add LFS training binary' git lfs ls-files -
Inspect what ordinary Git committed, rather than assuming it contains the binary:
git show HEAD:assets/demo.bin git check-attr filter -- assets/demo.binThe committed content is an LFS pointer containing an object identifier and size. The LFS client resolves that pointer to the binary for a capable clone.
-
If you use a disposable GitHub repository, push it and inspect both the LFS transfer output and the repository’s
.gitattributes. Clone it into a second directory after temporarily disabling LFS smudging (GIT_LFS_SKIP_SMUDGE=1 git clone ...) to observe the pointer-only state. Re-enable LFS and rungit lfs pullto fetch the object. Never perform this test against a repository you need.
Verify
Record the git lfs ls-files output, the committed pointer text, .gitattributes, and—if you used a remote—the fresh clone before and after git lfs pull. You should now understand that Git tracks a pointer while LFS stores the object separately; a collaborator without LFS cannot use the original binary merely because they cloned the repository.
Break and fix
- In a second disposable repository, commit a
.binfile before runninggit lfs track.git lfs ls-filesshould omit it. Do not force-push a rewrite. Remove that local repository and repeat the correct sequence instead. - Delete
assets/demo.bin, stage and commit the deletion, then recover it withgit restore --source=HEAD~1 -- assets/demo.bin. Verify the recovered file and commit it. This is local/safe recovery, not shared-history rewriting. - Explain the response if a large file or secret already reached a shared remote: stop normal pushes, assess clones/forks and credential exposure, revoke any secret, follow the host’s history-removal procedure, coordinate a force-update, and require collaborators to reclone or repair. Removing a file in a new commit does not remove it from old commits.
Scenario practice
- Configure: A repository stores a 500 MB model artifact. Choose Git LFS, a package feed, or a release asset and state the consumer and retention requirement that drives your choice.
- Diagnose: A fresh clone displays pointer text instead of the binary. Which client capability and commands do you check before declaring the object lost?
- Distinguish: Contrast
git restore/git revertwith a history rewrite. Which is appropriate for an accidental deletion already pulled by other developers?
Clean up
Delete the two local training repositories. If you created a disposable remote, delete it only after confirming it contains no work you need. Do not assume deleting one LFS pointer immediately removes remote LFS storage; follow your host’s documented retention/removal process.
Sources and re-audit
- Configure Git Large File Storage, checked 2026-08-22.
- About Git LFS and pointer files, checked 2026-08-22.
- Move existing files to Git LFS, checked 2026-08-22.
Re-audit when host limits, LFS retention, or sensitive-data removal guidance changes.