Skip to content

Instantly share code, notes, and snippets.

@gitcos
Last active August 12, 2022 19:16
Show Gist options
  • Select an option

  • Save gitcos/2219596b4445b9b26dc8406bcbd0fd3c to your computer and use it in GitHub Desktop.

Select an option

Save gitcos/2219596b4445b9b26dc8406bcbd0fd3c to your computer and use it in GitHub Desktop.
Splitting or Combining Repositories Preserving Change History
git-filter-repo is a tool that makes it easy to select subsets of commits in a Git repository and rewrite their paths,
which makes it easy to move folders between repos while preserving their commit histories.
https://github.com/newren/git-filter-repo
It is a single-file python script which can be installed with pip or brew; for more installation info, see the documentation.
# Splitting a subdirectory into a separate repo
Scenario: You want to take subdirectory some_project/ out of repo orgname/oldrepo and create a new repo orgname/some_project.
* Create a new local clone of the source repo and enter the top level directory.
cd /tmp
git clone [email protected]:username/oldrepo
cd oldrepo
* Filter this clone to include only the subdirectory you want,
and rewrite paths to move that subdirectory to the root directory.
git filter-repo --path some_project/ --path-rename some_project/:''
* Create a new empty repo named some_project on GitHub.
* Clone the new repo locally and enter it.
cd /tmp
git clone [email protected]:username/some_project
cd some_project
* Add the filtered repo as a remote for the new repo, pull its main branch, then force-push back to GHE.
git remote add oldrepo /tmp/oldrepo/
git pull oldrepo [master|main] --tags
git push origin [master|main] -f --tags
* Delete your filtered local clone of oldrepo.
Optionally, in an un-filtered clode of oldrepo, run 'git rm some_project' and commit that.
# Combining two repos into one
Scenario: You want make a new repo orgname/combined with two subdirectories named proj1 and proj2,
from two existing repos named orgname/proj1 and orgname/proj2
* Create new local clones of the two existing repos
cd /tmp
git clone [email protected]:username/proj1
git clone [email protected]:username/proj2
* Filter each repo's commit history to rewrite the root directory to a subdirectory.
Also, rewrite tag names to a namespace for each repo,
so that tags of the same name from the two repos will not collide when combined.
cd /tmp/proj1; git filter-repo --path '' --path-rename '':proj1/ --tag-rename '':'proj1-'
cd /tmp/proj2; git filter-repo --path '' --path-rename '':proj2/ --tag-rename '':'proj2-'
* Create a new repo named combined on GitHub, optionally with a README and .gitignore.
You don't need to start with an empty root directory because all the commits you will pull
into the repo will only affect subdirectories, not the repo root.
* Clone the new repo locally, and add the two pre-existing repos as remotes:
cd /tmp
git clone [email protected]:username/combined
cd combined
git remote add proj1 /tmp/proj1/
git remote add proj2 /tmp/proj2/
* Pull the two pre-existing repos' main branches into this new repo, then force-push to GHE:
git pull proj1 [master|main] --tags
git pull proj2 [master|main] --tags
git push origin [master|main] -f --tags
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment