git
repository
version control
software development
git migration

Moving Git repository content to another repository preserving history

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Migrating one Git repository into another while keeping full commit history is a common engineering task during monorepo moves, project splits, or ownership changes. The migration is straightforward when you choose the right strategy and verify results before cutover. This guide covers safe methods with concrete commands and rollback-friendly checks.

Core Topic Sections

Pick the migration goal first

Different goals need different Git flows:

  1. Replace destination repository entirely.
  2. Import source history into a subdirectory of destination.
  3. Combine both histories while keeping existing destination commits.

Do not start command execution before deciding which target state you want.

Strategy 1: full mirror replacement

If destination should become an exact copy of source, mirror push is the cleanest method.

bash
1# clone source with all refs
2git clone --mirror [email protected]:org/source-repo.git
3cd source-repo.git
4
5# point mirror to destination
6git remote set-url --push origin [email protected]:org/destination-repo.git
7
8# push all refs, branches, and tags
9git push --mirror

This rewrites destination refs to match source exactly. Use only when replacement is intentional.

Strategy 2: import source history under subdirectory

When destination already has content and you want source imported under a folder, rewrite source paths before merge.

Using git filter-repo:

bash
1# in a fresh clone of source
2git clone [email protected]:org/source-repo.git source-repo
3cd source-repo
4
5git filter-repo --to-subdirectory-filter imported/source

Then merge into destination:

bash
1cd ..
2git clone [email protected]:org/destination-repo.git destination-repo
3cd destination-repo
4
5git remote add source ../source-repo
6git fetch source
7
8git merge --allow-unrelated-histories source/main -m "Import source history under imported/source"

This keeps both histories and avoids root-level file collisions.

Strategy 3: simple unrelated-history merge

If directory conflict risk is low and you want two histories joined quickly:

bash
1git clone [email protected]:org/destination-repo.git
2cd destination-repo
3
4git remote add source [email protected]:org/source-repo.git
5git fetch source
6
7git merge --allow-unrelated-histories source/main -m "Merge source repository"

Resolve conflicts, run tests, and push merged branch after review.

Validate migrated history before push

Run structural checks locally:

bash
1git log --oneline --decorate --graph --all | head -n 50
2git tag -l | wc -l
3git branch -a
4git fsck

Validation focus:

  1. Expected commit lineage exists.
  2. Critical tags are present.
  3. Branch mapping is correct.
  4. Working tree builds successfully.

Preserve authorship and commit identity

Git history naturally preserves author and committer fields unless rewritten intentionally. If rewriting with filters, verify author metadata still looks correct on representative commits.

bash
git show --quiet --format=fuller <commit-sha>

This check is important for audit and compliance-heavy repositories.

Handle large files and LFS carefully

If repository uses Git LFS, migrate LFS objects in addition to normal refs.

bash
git lfs fetch --all
git lfs push --all origin

For large monorepo migrations, verify storage quotas before final push to avoid partial transfer failures.

Cutover and communication plan

Technical migration is only half the job. Operationally:

  1. Freeze write activity on source during final sync window.
  2. Announce new remote URL and branch policy.
  3. Archive or protect old repository to prevent accidental continued commits.

Without communication controls, teams can split work across old and new repositories.

Rollback strategy

Always keep a rollback path:

  1. Push migration to a temporary branch first.
  2. Review and test before updating default branch.
  3. Keep source repository intact until stabilization period ends.

This reduces risk of irreversible mistakes during repository restructuring.

Common Pitfalls

  • Using mirror push when destination should have retained existing history.
  • Merging unrelated histories without first deciding directory layout.
  • Forgetting tag and LFS object migration checks.
  • Performing cutover without a source-repository write freeze.
  • Skipping pre-push validation of commit graph and build behavior.

Summary

  • Repository migration with preserved history is safe when strategy matches goal.
  • Use mirror push for full replacement and filter plus merge for subdirectory imports.
  • Validate commit graph, refs, tags, and build integrity before cutover.
  • Include LFS migration and team communication in execution plan.
  • Stage migration through review branches to keep rollback options available.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.