Detaching a subdirectory into a separate GIT repository

Working on a large project where the whole website is in a single GIT repository can be a real hassle. With the introduction of composer you might want to rethink the content of your repo.

At one of my clients we recently decided to start with composer as part of our deployment workflow. This means we had to split up the GIT repository. This repository is in use for almost 6 years and thousands of commits have been done. It contains of the complete website, build with TYPO3. It includes the core, extensions and configuration.

For the TYPO3 core and extensions coming from the TER this is not a big problem. Just add some lines to the composer.json file in the root and you're done.

A bigger problem was the amount of homebrew extensions. At this client we are using a lot of custom made extensions for connecting to other systems. This includes LDAP, Exchange Web Services and SOAP connections. These needed to be separated from the main repository.

GIT has support for this since version 1.7.11, released in May 2012. And it is called "git subtree".

Let's say we have the following project in our repository which is located at ~/Code/website

website
    typo3conf
        ext 
           extension_1
           extension_2
           extension_3
        LocalConfiguration.php
        PackageStates.php

In this repository we want to split our homebrew extensions 1 till 3 to a separate repository.

First make sure you have the 3 remote repositories ready and clone them to your own system. For this example I put them in ~/Code/extension_1, ~/Code/extension_2 and ~/Code/extension_3.

Get into the folder of the repository you want to split.

cd ~/Code/website

Then tell git to make a new branch, that only has commits from the folder extension_1.

git subtree split -P typo3conf/ext/extension_1 -b extension_1-only

You now have a branch called "extension_1-only". 

Let's go to the new repository for extension_1.

cd ~/Code/extension_1

and pull the branch of our website repository into the extension repository

git pull ~/Code/website extension_1-only

Push the new repository and you're done. Don't forget to remove the folder extension_1 from the website repository.

cd ~/Code/website
git rm -rf  extension_1

One more thing

The aforementioned delete history command still leaves behind a bunch of backup files - because git is all too kind in helping you to not ruin your repo by accident. It will eventually delete orphaned files over the days and months, but it leaves them there for a while in case you realize that you accidentally deleted something you didn't want to.

So if you really want to empty the trash to reduce the clone size of a repo immediately you have to do a manual cleanup in GIT. I'm not going into detail because this includes some weird stuff.