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.
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
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.
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.