Skip to content

Instantly share code, notes, and snippets.

@jrsmith3
Last active August 29, 2015 13:56
Show Gist options
  • Save jrsmith3/9250710 to your computer and use it in GitHub Desktop.
Save jrsmith3/9250710 to your computer and use it in GitHub Desktop.
Split a monolithic git repo into several small ones
# -*- coding: utf-8 -*-
"""
I used the following script to convert each subdirectory of work.git into its own git repo. The one exception was paper-2013.01.16_nea_collector which I did by hand using essentially the same method as below, except I skipped the part where I removed the tags. I used the procedure found at [1] and slightly modified it. I also used the solution in [2] to convert non-bare repos to bare. Note also that I first cloned work from its bare git repo on the SD card, removed the remote, and tarred the result to work.tar.
[1] http://stackoverflow.com/questions/359424/detach-subdirectory-into-separate-git-repository
[2] http://stackoverflow.com/questions/1784506/when-creating-a-git-repository-that-will-be-on-the-server-can-i-convert-it-to-a
"""
import os
import subprocess
import shutil
subprocess.call(["tar","xf","work.tar"])
contents = os.listdir("work")
for dirname in contents:
if dirname[0] is not ".":
os.chdir("work")
# Remove the tags.
print("=" * 50)
print "="*5, dirname, "="*5
print("removing tags")
git_tag = subprocess.Popen(["git","tag","-l"],stdout=subprocess.PIPE)
git_tag.wait()
xargs = subprocess.Popen(["xargs","git","tag","-d"],stdin=git_tag.stdout)
xargs.wait()
print("git filter-branch")
subprocess.call(["git","filter-branch","--tag-name-filter","cat","--prune-empty","--subdirectory-filter",dirname,"--","--all"])
print("deleting the backup reflogs")
subprocess.call(["git","reset","--hard"])
git_foreach = subprocess.Popen(["git","for-each-ref",'--format="%(refname)"',"refs/original/"], stdout=subprocess.PIPE)
xargs = subprocess.Popen(["xargs","-n","1","git","update-ref","-d"], stdin = git_foreach.stdout)
subprocess.call(["git","reflog","expire","--expire=now","--all"])
subprocess.call(["git","gc","--aggressive","--prune=now"])
print("Moving newly filter-branched repo to its own folder")
os.chdir("..")
shutil.move("work","split_repos/"+dirname)
print("Turning repo to bare, then removing the non-bare copy.")
os.chdir("split_repos")
subprocess.call(["git", "clone", "--bare", "-l", dirname, dirname + ".git"])
shutil.rmtree(dirname)
os.chdir("..")
print("Un-taring the work git repo again.")
subprocess.call(["tar","xf","work.tar"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment