Distilled from a question thread (which I found a little too confusing) on Stack Overflow. matli writes:

Just to make it clear, I have the following structure:

XYZ/
    .git/
    XY1/
    ABC/
    XY2

But I would like:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/

See the original thread for details.


  1. Backup XYZ. I use rsync, just to spread my risk around, but you can git clone if you prefer.

     rsync -ahz --progress XYZ/ XYZ.git.bak/
    
  2. Create the repository you want to be ABC-only by cloning it from XYZ.

     git clone --no-hardlinks XYZ ABC
    
  3. In ABC, remove all history outside the ABC hierarchy.

     git filter-branch --subdirectory-filter ABC HEAD -- --all
    
  4. Clean up references…

     git remote rm origin
     git update-ref -d refs/original/refs/heads/master
    
  5. …and then objects.

     git reset --hard
     git reflog expire --expire=now --all
     git gc --aggressive
     git prune
     git repack -ad
    
  6. In XYZ, remove all history belonging to the ABC hierarchy.

     git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ABC" --prune-empty HEAD
    

    Alternatively, if you’re not worried about ABC’s history cluttering up XYZ, just delete the ABC hierarchy and commit.

     git rm -rf ABC
     git commit
    
  7. Clean up: repeat Step 5 in XYZ.