Chapter 24Lesson 05~210 minutes

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.

CheckpointMigration runbookCutoverRollback

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

  1. Will a full --all bundle contain the note/custom refs created in this local lab?
  2. Will clone --mirror preserve those refs under the same names?
  3. Should a mirror push to an empty destination delete anything?
  4. Can the source archive reproduce git log without 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

Mirror push is the checkpoint's highest-risk command. The destination is intentionally empty and disposable; production requires a freeze/backup/ref-snapshot approval before equivalent execution.
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 --full passed 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

Only remove the disposable checkpoint after all predictions and validation evidence have been reviewed.
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.

Next chapter

Git in CI/CD, Infrastructure as Code, Release Automation, and GitOps

Chapter 25 uses the immutable commit/ref model you just migrated as the provenance substrate for pipelines, release automation, bot updates, and desired-state reconciliation.

Authoritative references

 git-bundle
 git-clone
 git-push
 git-archive
 gitsubmodules

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.