git filter-repo

Table of contents
  1. Installation
  2. Set subdirectory as root of its own repo
    1. Clone a fresh copy of the repo
    2. Set the contents of subdirectory as the content of new repo
    3. Create a new remote and push
  3. Move multiple subdirectories to a new repo
  4. Delete files from all commit history

Installation

Install via Homebrew:

brew install git-filter-repo

Set subdirectory as root of its own repo

You could technically just copy over the directory and create a new repo. However, if you’d like to carry over commits that are relevant to the subdirectory to the new reoo, you can use git filter-repo to do so.

Suppose you have a repo named test-repo with the following structure:

.
├── dir1
├── dir2
└── dir3

And you want to move the contents of dir1 into a new repo named dir1-repo.

Clone a fresh copy of the repo

Cloning a fresh copy before running git filter-repo is a recommended practice.

git clone ${https_or_ssh_to_test_repo} dir1-repo

Set the contents of subdirectory as the content of new repo

cd dir1-repo
git filter-repo --subdirectory-filter dir1

Relevant commits should have been cherry picked as well.

Create a new remote and push

Create a new repo on GitHub. Suppose its name is dir1-repo.

First check if you still have the remote pointing to the original test-repo:

git remote -v

If you do, modify it:

Assuming origin is the name of the main upstream remote.

git remote set-url origin ${https_or_ssh_to_dir1_repo}
# OR if the remote settings were already purged
git add remote origin ${https_or_ssh_to_dir1_repo}

Verify that a new remote origin has been set and push:

git push -u origin ${branch}

Move multiple subdirectories to a new repo

Suppose you have a repo named test-repo with the following structure:

.
├── dir1
├── dir2
├── dir3
└── dir4

And you want to move dir1 and dir2 to a new repo named new-repo:

.
├── dir1
└── dir2

Steps are similar to above, except for the git filter-repo command:

git filter-repo --path dir1 --path dir2

Delete files from all commit history

To remove certain files from all commit history, use the following command:

git filter-repo --invert-paths --path <file1> --path <file2>

References