Building Better Teams

Articles and Posts

Blog

 

Transform a project folder into a package; collaborate on confidential work.

Great software that could be reused elsewhere is often bound in a larger repository (such as “the main project”). This binding can prevent code from being truly reused elsewhere. A typical solution to this problem is simply copying the files into a new repo and write a commit like git commit -m "Move everything from the old project". Unfortunately, the history of that new repository is entirely removed, and along with that, all the design opinions and context for why changes ended up how they did.

Wouldn't it be nice if we could move all those files into a new repo and keep the relevant history? It’s time for you to learn about subtree split.

repos.png
git subtree split --prefix=path/to/thatLibrary -b thatLibrary  

With this one command you've just created a branch that has all the history of your library, but also only the history of that library. It’s no longer related to master, but instead every commit was re-built to be just the contents of that folder.

The next step is ofcourse moving it from a single branch and into a proper repository. This is also quite easy. From a directory outside of your project create a new bare repository (it just stores history, you are expecting to work in it).

git init a --bare library-name

Now return to your original repo and, push your branch ”thatLibrary” into your new repo.

git push ~/path-to-that-new-library thatLibrary:master

Now you can introduce a few minor tweaks and meta-files to create your npm package. Best of all, you get to keep all the history, and authors of the repo get their hard-earned credit for their work.

Lastly, in your original repo, you can now remove the library from your code base and import it as a package.

And now in reverse…

You can also do the inverse of this. If you're working on a sensitive project base and need to hire a third-party contractor to do some web design work, you can let them work out of their own repo which has none of your confidential code in it. You can later add their repository as an additional remote, and merge that remote into your project.

git remote add contractor git@example.com:ContractorOrg/Contractor.git  
git fetch contractor
git merge contractor/master
repos.png

Your project will have a history that looks like this. Two original commits that do not share a common history.

*   687b67c  (HEAD -> master) Merge remote-tracking branch 'contractor/master'
|\
| * e604fdf  (contractor/master)
* 446f3ac 

And if you want to put the new commit tree into a specific subfolder instead of the default project root, check out the documentation for git subtree add and git subtree merge.

Brian Graham