Skip to content

Instantly share code, notes, and snippets.

@zachfi
Last active February 28, 2018 20:54
Show Gist options
  • Save zachfi/8966079 to your computer and use it in GitHub Desktop.
Save zachfi/8966079 to your computer and use it in GitHub Desktop.
git-split: Break off a sub directory into its own repo, keeping history.
#! /usr/bin/env ruby
require 'tmpdir'
require 'fileutils'
require 'pp'
def main()
directory = ARGV.shift
unless File.exists?(directory)
puts "directory #{directory} does not exist"
exit 1
end
dirname=%x{basename #{directory}}.chomp
git_dir=%x{git rev-parse --show-toplevel}.chomp
branch=%x{git symbolic-ref --short -q HEAD}.chomp
Dir.mktmpdir(nil, '/var/tmp') {|dir|
dst = "#{dir}/#{dirname}"
FileUtils.mkdir_p(dst)
#FileUtils.copy_entry(git_dir,dst)
%x{git clone #{git_dir} #{dst}}
FileUtils.cd(dst)
puts "working in #{dst}"
remotes=[%x{git remote}.split("\n").map{|r| r.chomp}].flatten.reject{|r| r.empty? }
# Remove all remotes
remotes.each {|r|
%x{git remote remove #{r}}
%x{git remote set-head -d #{r}}
}
# rename the branch
if branch != 'master'
%x{git br -m #{branch} master}
end
%x{git filter-branch -f --tag-name-filter cat --prune-empty --subdirectory-filter #{directory}}
#%x{git filter-branch -f --subdirectory-filter #{directory}}
#%x{git filter-branch -f --subdirectory-filter #{directory}}
%x{git reset --hard}
%x{git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d}
%x{git reflog expire --expire=now --all}
%x{git gc --aggressive --prune=now}
FileUtils.cd(dir)
finaldir = "#{git_dir}/#{directory}.split"
begin
FileUtils.mv(dirname,finaldir)
rescue Errno::EEXIST
puts "Final directory #{finaldir} already exists, aborting!"
exit 1
end
}
end
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment