JFlo
JFlo

Reputation: 718

Partial git clone with relevant history

Let's say I've written a zillion puppet modules and I have their entire history within a single git repo, but now I really wished I had made one repo per module. Divvying up the file structure is easy because each is wholly contained within their own directory and are organized like GIT_ROOT/modules/NAME.

Is there a way that I can divide this repo up and not loose the history for each module? Ideally each repo would only have history relevant to the module it represents. I tried cloning the entire thing and git rm -rf everything that's irrelevant but that retains irrelevant history.

I plan to glue them back together with git submodules, FWIW.

Upvotes: 3

Views: 902

Answers (1)

larsks
larsks

Reputation: 312760

I've been playing with this a little bit, and it looks like the easiest way to split this up is using git subtree split:

split

Extract a new, synthetic project history from the history of the subtree. The new history includes only the commits (including merges) that affected , and each of those commits now has the contents of at the root of the project instead of in a subdirectory. Thus, the newly created history is suitable for export as a separate git repository.

So, for example, if I start with the openstack-puppet-modules repository, which includes a bunch of individual puppet modules, I could split them up first into individual branches like this (I am only using eight modules here to keep things short):

for x in apache aviator ceilometer certmonger cinder common \
    concat firewall; do
  git subtree split -P $x -b split-$x
done

Once this is finished running, I have:

$ git branch | grep split-
split-apache
split-aviator
split-ceilometer
split-certmonger
split-cinder
split-common
split-concat
split-firewall
split-pacemaker

Each of those branches contains only the history for the specific directory. If I want to transform these into separate repositories, I could do this:

for x in apache aviator ceilometer certmonger cinder common \
    concat firewall; do
  git init --bare ../repos/repo-$x
  git push ../repos/repo-$x split-$x:master
done

Now I have a collection of repositories:

$ ls ../repos/
repo-apache  repo-aviator  repo-ceilometer  repo-certmonger
repo-cinder  repo-common  repo-concat  repo-firewall  work-cinder

And I think we've achieved your goal.

Upvotes: 8

Related Questions