gitgit-filter-repofilter-repo

Use git filter-repo to keep only two directories and move one to the root


I have a repository with a lot of projects, and I would like to keep only two components and move one of them to the root.

   cmake/
     ...
   src/
     module1/
       contrib/
       src/
       ... (more stuff)
     module2/
       ...
     module3/
       ...
   ci/
     ...
   doc/
     ...

The result I want is to keep cmake, move src/module1/* to the root, remove everything else (ci/, doc/, src/module2, src/module3):

   cmake/
     ...
   contrib/
   src/
   ... (more stuff)

Currently I'm using this awfully slow git filter-branch command on the master branch:

FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch \
    --index-filter 'git ls-files \
                        | grep -v "^cmake\|^src/module1" \
                        | xargs -I{} git rm -q --cached {};
                    git ls-files -s \
                        | sed "s%src/module1/%%" \
                        | git update-index --index-info;
                    git rm -rq --cached --ignore-unmatch src/module1' \
    --prune-empty -- --all

Is there a way to do this faster with filter-repo? It is easy to find code examples that do any of the two operations, but I'm not sure if both can be done in one go.

The goal is to keep a sub-repository synchronized with the commits from the main mono-repository, so this will run once a day. The existing solution takes multiple hours to run.

I tried this:

git filter-repo --path cmake --path src/module1 --path-rename src/module1:

But it fails with error:

Parsed 3450 commitsfatal: Empty path component found in input

Solution

  • I found the issue looking at more examples in various examples posted in other questions.

    I almost had the right solution, I just needed an extra slash in the --path-rename string

    git filter-repo --path src/module1 --path cmake --path-rename src/module1/: