Chapter 24Lesson 01~130 minutes

Bundles, Mirrors, Repository Migration, Archival, and Offline Transfer: Concepts, Architecture, and Mental Model

Build a precise mental model for bare and mirror repositories, full and incremental Git bundles, source archives, ref namespaces, external LFS/submodule dependencies, and production migration completeness.

Migration mental modelBundlesMirrorsArchives

Learning objectives

  • Distinguish bare clones, mirror clones, bundles, and source archives by the state they preserve.
  • Explain bundle refs, objects, prerequisites, offline clone/fetch, and direct unbundle behavior.
  • Inventory branches, tags, notes, custom refs, LFS, submodules, hooks, and hosted metadata separately.
  • Explain why mirror pushes and pruning are production cutover operations with deletion risk.
  • Define validation and rollback checkpoints using immutable ref/object evidence.

1. “Copy the repository” is not one operation

Earlier chapters separated Git's working tree, index, objects, refs, signatures, maintenance structures, and patch artifacts. Migration adds another distinction: different copy mechanisms preserve different subsets of that state. A source-tree ZIP can reproduce files without history; a normal clone gives a developer-oriented view of advertised branches and tags; a mirror is intended to reproduce ref namespaces; and a bundle transports selected refs plus the objects needed to satisfy them without a live server.

The practical problem is therefore not “How do I copy a directory?” but “Which state must survive, what can remain external, what can be reconstructed, and how will I prove the new system is equivalent enough for production?”

2. Inspect the source before choosing a transfer mechanism

git --version
git status --short --branch
git remote -v
git show-ref
git for-each-ref --sort=refname --format='%(refname) %(objectname)'
git rev-list --count --all
git count-objects -vH
git notes list
git submodule status
git config --list --show-origin --show-scope

These commands are read-only. They establish the visible refs, commit/history scale, configured remotes, notes, submodule state, and local configuration. If Git LFS is installed, add git lfs env and git lfs ls-files; LFS content is not ordinary Git blob content and must be inventoried separately.

3. Bare repositories remove the working-tree layer

A bare repository stores Git administrative data directly in the repository directory and has no checked-out working tree. It is suitable for repository serving, transfer, and storage tasks where file checkout is unnecessary.

git clone --bare source-repo source-bare.git

Current Git copies branch heads directly into local refs/heads/* for a bare clone. It does not create the ordinary developer clone's refs/remotes/origin/* tracking structure.

4. A mirror is a stricter ref-level replication configuration

git clone --mirror implies --bare, but it goes further: current Git maps all advertised refs—including branches, tags, notes, and other visible namespaces—and configures a forced fetch refspec such as +refs/*:refs/*. The mirror's ref names therefore align directly with the source ref names.

git clone --mirror source-repo source-mirror.git
git -C source-mirror.git config --get-all remote.origin.fetch
git -C source-mirror.git config --get remote.origin.mirror
git -C source-mirror.git for-each-ref --sort=refname --format='%(refname) %(objectname)'

A mirror is still bounded by what the source server advertises and what the caller is authorized to read. “Mirror” does not mean “bypass hidden server refs.”

5. Four transfer shapes solve four different problems

Repository-transfer mental model
flowchart LR
S[Source repository]
S -->|normal or bare clone| B[Common Git refs + objects]
S -->|mirror clone| M[Advertised refs/* + objects]
S -->|bundle create| U[Portable refs + prerequisite-aware object pack]
S -->|archive| A[One tree snapshot only]
M -->|mirror push| D[Destination repository refs]
U -->|clone/fetch/unbundle| O[Offline recipient]
A --> X[Release/source files without Git history]

The arrows represent preservation boundaries. Clone/mirror/bundle move Git objects and refs according to their own selection rules. Archive reads one tree and emits files. Mirror push can create, force-update, and delete remote refs, so it is a cutover operation rather than a harmless file copy.

6. A bundle is a portable Git repository data stream, not a ZIP of the working tree

A Git bundle contains a packfile plus a header describing refs and, for incremental bundles, prerequisite commits. It is designed for offline transport: the destination can clone or fetch from the bundle without an SSH/HTTPS server.

git bundle create full.bundle --all
git bundle list-heads full.bundle
git bundle verify full.bundle

--all selects refs using Git's revision machinery. The objects included are those reachable from the selected refs, subject to any exclusions. Per-repository config, server hooks, working-tree state, and hosting-platform database records are not reconstructed from a bundle.

7. Incremental bundles trade self-containment for smaller transfers

A full bundle can be self-contained. An incremental bundle such as old..new excludes objects reachable from old and declares that earlier history as a prerequisite. The receiving repository must already possess that prerequisite history.

git bundle create update.bundle last-transfer..trunk
git bundle verify update.bundle

The verification command checks both bundle structure and whether the current repository contains fully linked prerequisite commits. This is why verification belongs on the recipient side, not only on the producer side.

8. unbundle stores objects; it does not magically create local refs

git bundle unbundle is plumbing used by fetch. It passes bundle objects to the object database and prints the refs advertised by the bundle. If you invoke it directly, you still need an explicit ref update/fetch policy. For beginner and production workflows, clone or fetch from the bundle is usually clearer.

9. git archive exports a named tree, not repository history

git archive --format=tar --prefix=project-1.0/ -o project-1.0.tar v1.0

The archive contains files from the specified tree-ish. It does not contain the repository's .git directory, branches, reflogs, hooks, or the history needed for ordinary Git operations. A tar/zip from git archive is excellent for a release source snapshot; it is not a history-complete Git backup.

10. Migration completeness starts with namespaces

State Where it lives Normal clone Mirror/bundle planning
Branches refs/heads/* yes, developer mapping explicitly compare refs
Tags refs/tags/* normally transferred/followed compare exact names/OIDs
Notes refs/notes/* not part of default branch fetch mapping mirror/full-ref bundle can preserve visible refs
Custom refs project-specific refs/* often omitted by ordinary clone mapping inventory and verify explicitly
Remote-tracking refs refs/remotes/* reconstructed for the new remote a mirror can copy advertised refs directly

11. Git LFS introduces a second content store

Git LFS commits contain pointer files in ordinary Git history while the large object bytes live in LFS storage. A Git-only mirror can preserve pointer blobs and refs while the destination still lacks the actual LFS objects. Migration planning therefore inventories and transfers LFS objects separately using the official Git LFS tooling appropriate to the destination.

Official Git LFS documentation treats git lfs fetch --all as a backup/migration-oriented operation. If a migration also rewrites which files use LFS, that is a separate history-rewrite project and must not be conflated with a mirror transfer.

12. Submodules are separate repositories referenced by the superproject

A superproject tree stores a gitlink object ID for each submodule and usually a .gitmodules URL/path mapping. The submodule has its own object database and history. Migrating only the superproject does not migrate the submodule repository's history or server policy. Every submodule remote must have its own transfer and validation plan.

13. Hosting metadata is not part of ordinary Git object transfer

Issues, pull/merge requests, review comments, branch protection, merge queues, hosted releases, package registries, CI secrets, organization permissions, and repository rules live in hosting-platform databases/services. A mirror may copy the Git refs visible to it, but it does not migrate those platform records. Likewise, server-side hooks and server configuration must be moved/recreated separately.

14. Validate identity, reachability, and policy separately

A migration should compare representative immutable commit IDs, exact ref names/OIDs, object connectivity, and source-tree content. Then separately validate access control, hooks, LFS/submodule dependencies, CI integrations, and hosted metadata. A destination can have every Git commit yet still be operationally incomplete.

15. Cutover requires freeze and rollback points

For a real migration, define a write freeze or bounded synchronization window, record source and destination ref snapshots, take a recoverable transfer artifact, perform the final update, switch clients, and retain the old source read-only until validation is complete. “DNS/URL changed” is not proof that repository state is complete.

16. DevOps connection — migration is a production change

Repository URLs are dependencies in developer clones, CI runners, deployment agents, submodule URLs, package/release automation, and bots. Treat migration like any other production change: inventory, immutable checkpoints, dry runs, explicit blast radius, controlled cutover, verification, and rollback.

17. Knowledge check

Question 1. What is the key difference between --bare and --mirror?

Question 2. Why can an incremental bundle fail verification in an empty repository?

Question 3. Why is a git archive tarball not a Git backup?

Question 4. Why can a Git mirror be incomplete for a Git LFS project?

Question 5. Do pull requests and branch-protection rules migrate through git clone --mirror?

18. Summary

Choose the transfer mechanism from the state you must preserve. Bare clones remove the worktree, mirrors reproduce visible ref namespaces, bundles move selected refs/objects offline with prerequisite rules, and archives export source trees only. Production completeness also includes LFS, submodules, hooks/config, permissions, and hosting metadata.

Next

Build the transfer mechanisms locally

Lesson 2 constructs full and incremental repository artifacts, contrasts bare and mirror clones, performs an offline bundle clone/unbundle, runs a guarded local mirror push, and proves an archive lacks Git history.

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.