Checkpoint Lab — Bundles, Mirrors, Repository Migration, Archival, and Offline Transfer
Checkpoint a production-style repository migration with branches, tags, notes, a full offline bundle, exact ref comparison, dry-run-first mirror cutover, source archive, external dependency inventory, and rollback runbook.
Learning objectives
- Predict and verify which refs and immutable commit identities survive bundle/mirror transfer.
- Produce and independently verify a self-contained offline bundle plus transport checksum.
- Perform initial and final local mirror updates only after full-ref inspection and dry runs.
- Compare a repository-complete transfer with a history-free source archive.
- Write a complete preflight, freeze, transfer, validation, cutover, rollback, and retirement runbook.
1. Checkpoint scenario — migrate a multi-ref repository through offline and mirror paths
You are moving a service repository during a restricted-network change window. The source has two branches, an annotated release tag, Git notes, and a custom release ref. You must first create a recoverable full bundle, prove it can reconstruct the visible refs offline, then mirror to a disposable destination and document production cutover/rollback controls.
2. Predict before executing
-
Will a full
--allbundle contain the note/custom refs created in this local lab? -
Will
clone --mirrorpreserve those refs under the same names? - Should a mirror push to an empty destination delete anything?
-
Can the source archive reproduce
git logwithout another repository artifact?
3. Build the source and a local bare “server”
mkdir git-migration-checkpoint
cd git-migration-checkpoint
git init --bare -b trunk source-server.git
git clone source-server.git source
git -C source config user.name "Migration Contributor"
git -C source config user.email "migration@example.invalid"
printf "service=inventory\nrelease=1\n" > source/service.conf
git -C source add service.conf
git -C source commit -m "seed inventory service"
git -C source push -u origin trunk
git -C source switch -c feature/audit
printf "audit=true\n" > source/audit.conf
git -C source add audit.conf
git -C source commit -m "add audit feature"
git -C source push -u origin feature/audit
git -C source switch trunk
git -C source tag -a v1.0 -m "checkpoint release"
git -C source push origin v1.0
git -C source notes add -m "migration-approved" HEAD
git -C source push origin refs/notes/commits
TRUNK_OID=$(git -C source rev-parse refs/heads/trunk)
git -C source update-ref refs/meta/release-candidate "$TRUNK_OID"
git -C source push origin refs/meta/release-candidate:refs/meta/release-candidate
4. Capture source-server baseline before any transfer
git -C source-server.git for-each-ref --sort=refname \
--format='%(refname) %(objectname)' > source-server-refs.txt
cat source-server-refs.txt
git -C source-server.git rev-list --count --all
git -C source-server.git fsck --full
git -C source remote -v
Save this file as the authoritative preflight snapshot for the checkpoint.
5. Create, inspect, and verify the full bundle
git -C source-server.git bundle create full.bundle --all
git -C source-server.git bundle list-heads full.bundle
git init --bare -b trunk bundle-verifier.git
git -C bundle-verifier.git bundle verify ../source-server.git/full.bundle
Because the bundle is self-contained, verification in an empty repository should succeed and report complete history.
6. Record transport integrity
sha256sum source-server.git/full.bundle > full.bundle.sha256
sha256sum --check full.bundle.sha256
PowerShell alternative:
Get-FileHash -Algorithm SHA256 source-server.git/full.bundle
In production, store the checksum in a controlled channel separate from the transported artifact when policy requires independent verification.
7. Clone the bundle offline as a mirror and compare refs
git clone --mirror source-server.git/full.bundle offline.git
git -C offline.git for-each-ref --sort=refname \
--format='%(refname) %(objectname)' > offline-refs.txt
git diff --no-index -- source-server-refs.txt offline-refs.txt
echo "offline ref comparison exit=$?"
git -C offline.git fsck --full
test "$(git -C offline.git rev-parse refs/heads/trunk)" = "$TRUNK_OID"
Expected: exact visible ref match and healthy connectivity.
8. Create the disposable migration destination
git init --bare -b trunk destination-server.git
git clone --mirror source-server.git migration-mirror.git
git -C migration-mirror.git remote add --mirror=push destination ../destination-server.git
git -C migration-mirror.git remote -v
git -C migration-mirror.git for-each-ref --sort=refname \
--format='%(refname) %(objectname)'
git -C destination-server.git for-each-ref --sort=refname \
--format='%(refname) %(objectname)'
9. Prediction check — dry-run mirror push before mutation
git -C migration-mirror.git push --mirror --dry-run --porcelain destination
Prediction: there should be creations and no unexpected deletion. If any deletion appears, stop and investigate.
10. Perform the controlled initial mirror
git -C migration-mirror.git push --mirror destination
git -C destination-server.git for-each-ref --sort=refname \
--format='%(refname) %(objectname)' > destination-refs.txt
git diff --no-index -- source-server-refs.txt destination-refs.txt
git -C destination-server.git fsck --full
11. Simulate final changes before freeze
printf "release=2\n" >> source/service.conf
git -C source add service.conf
git -C source commit -m "final pre-cutover update"
git -C source tag v1.1
git -C source notes add -m "cutover-ready" HEAD
git -C source push origin trunk v1.1
git -C source push origin refs/notes/commits
FINAL_OID=$(git -C source rev-parse HEAD)
12. Freeze simulation and capture the final authoritative snapshot
git -C source status --short --branch
git -C source-server.git for-each-ref --sort=refname \
--format='%(refname) %(objectname)' > final-source-refs.txt
cat final-source-refs.txt
In a real migration, “freeze” means the process/permissions prevent new writes while final synchronization and validation occur.
13. Refresh mirror with pruning, dry-run, then cut over the disposable destination
git -C migration-mirror.git remote update --prune origin
git -C migration-mirror.git push --mirror --dry-run --porcelain destination
git -C migration-mirror.git push --mirror destination
git -C destination-server.git for-each-ref --sort=refname \
--format='%(refname) %(objectname)' > final-destination-refs.txt
git diff --no-index -- final-source-refs.txt final-destination-refs.txt
test "$(git -C destination-server.git rev-parse refs/heads/trunk)" = "$FINAL_OID"
git -C destination-server.git fsck --full
14. Create a release archive and demonstrate its different contract
git -C source archive --format=tar --prefix=inventory-v1.1/ \
-o ../inventory-v1.1.tar v1.1
mkdir release-export
tar -xf inventory-v1.1.tar -C release-export
test -f release-export/inventory-v1.1/service.conf
test ! -d release-export/inventory-v1.1/.git
git -C release-export/inventory-v1.1 log --oneline
echo "archive Git query exit=$?"
The failed Git log is expected. The archive is a deliverable snapshot, while the bundle/mirror are repository-history transfer mechanisms.
15. External dependency checklist
Git refs/objects
- branches:
- tags:
- notes:
- custom refs:
- representative immutable commit IDs:
- fsck result:
Git LFS
- installed/used?
- source objects fully fetched/backed up?
- destination endpoint/upload verified?
Submodules
- each repository migrated?
- every gitlink commit exists at destination?
- .gitmodules URLs valid after cutover?
Server/hosting
- hooks:
- permissions:
- protected refs/rules:
- CI/webhooks/secrets:
- issues/PRs/reviews/releases/packages:
16. Production migration runbook
| Phase | Required evidence |
|---|---|
| Preflight | source URL/owner, Git version, full refs/OIDs, fsck, LFS/submodules, platform inventory |
| Backup | verified bundle/mirror + checksum + controlled storage |
| Freeze | write freeze confirmed; final source ref snapshot captured |
| Transfer | mirror/bundle operation logs; dry-run reviewed before destructive updates |
| Validation | exact refs/OIDs, connectivity, representative checkout/build, LFS/submodules, auth/policy |
| Cutover | new canonical URL communicated; CI/bots/submodule links updated |
| Rollback | old source remains read-only/recoverable; reversal owner and criteria documented |
| Retire | only after validation window; obsolete credentials/artifacts handled by policy |
17. Verification checklist
- Source branch/tag/note/custom-ref OIDs were captured before transfer.
- Full bundle verified in an empty recipient repository.
- Bundle checksum was recorded and rechecked.
- Offline mirror clone matched the source visible-ref snapshot.
-
Initial and final mirror pushes were preceded by
--dry-run --porcelain. - Destination final refs matched source final refs exactly.
- Representative trunk OID matched at source and destination.
-
git fsck --fullpassed on transferred repositories. - Archive extracted expected files and intentionally lacked Git history.
- LFS, submodules, hooks/policy, and hosted metadata were explicitly treated as separate workstreams.
18. Cleanup
cd ..
pwd
rm -rf git-migration-checkpoint
PowerShell equivalent:
Set-Location ..; Remove-Item -Recurse -Force
git-migration-checkpoint.
19. Knowledge check
Question 1. Why was an empty bare repository used to verify the full bundle?
Question 2. What would an unexpected deletion in the mirror dry-run mean?
Question 3. Why compare exact refname/OID snapshots before and after?
Question 4. Why is the archive still useful even though it
cannot run git log?
Question 5. Which migration dependencies remain outside the Git mirror itself?
20. What Chapter 24 adds to a production Git operating model
You can now choose among archive, bundle, bare clone, and mirror based on preservation requirements; bootstrap and increment offline transfers; inspect/prune mirror refs deliberately; dry-run destructive cutovers; validate immutable refs and connectivity; and integrate LFS, submodules, server policy, hosted metadata, offline-media security, and rollback into one migration plan.
21. Chapter checkpoint summary
A repository migration succeeds when the destination preserves the required Git identity and surrounding operational dependencies—not when a file copy merely finishes. The production discipline is inventory → backup → freeze → transfer → exact validation → controlled cutover → rollback window.
Authoritative references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.