Skip to content

Instantly share code, notes, and snippets.

@kch
Created November 3, 2009 22:27
Show Gist options
  • Save kch/225509 to your computer and use it in GitHub Desktop.
Save kch/225509 to your computer and use it in GitHub Desktop.
Assimilates git submodules' files, gets properly rid of the submodule metadata.
#!/usr/bin/env ruby
require 'yaml'
require 'pathname'
require 'shellwords'
module_url_by_path = Dir['**/.gitmodules'].inject({}) do |h, path|
IO.read(path).scan(/^\[submodule .*\].*\n((?:\s+.*\n)+)/).flatten.each do |s_attrs|
h_attrs = s_attrs.strip.split(/\n/).inject({}) do |h_attrs, s_attr_line|
k, v = s_attr_line.strip.split(/\s+=\s+/, 2)
h_attrs[k.to_sym] = v
h_attrs
end
h[Pathname.new(File.dirname(path)).join(h_attrs[:path]).to_s] = h_attrs[:url]
end
h
end
submodules = `git submodule status --recursive`.scan(/^(.)(\w+) (.*) \((.*)\)$/).map do |status, commit, path, ref|
{ :status => status, :commit => commit, :path => path, :ref => ref, :url => module_url_by_path[path] }
end
if submodules.any? { |h| h[:status] != ' ' }
puts "Status failed for some submodules. Fix and try again."
exit 1
end
# config cleanup
f_config = ".git/config"
in_sub = false
lines = ""
IO.read(f_config).lines.each do |line|
next in_sub = true if line =~ /^\[submodule /
next lines << line unless in_sub
next if line =~ /^\s/
in_sub = false
redo
end
open(f_config, "w") { |f| f.write(lines) }
# fs, index cleanup
submodules.each { |h| h.delete :status }
submodules.each do |h|
path = Pathname.new(h[:path])
puts `rm -rf #{path.join(".git").to_s.shellescape}`
puts `rm -f #{path.join(".gitmodules").to_s.shellescape}`
puts `git rm --ignore-unmatch --cached #{path.to_s.shellescape}`
end
puts `git rm .gitmodules`
# add it all
submodules.each do |h|
path = Pathname.new(h[:path])
puts `git add #{path.to_s.shellescape}`
end
# commit it all
msg = "Assimilated all submodules:\n\n#{submodules.to_yaml}"
puts `git commit -m #{msg.shellescape}`
@conatus
Copy link

conatus commented Dec 28, 2013

Thanks for this - supremely useful.

@csu
Copy link

csu commented Jun 30, 2014

Does this maintain the git log/commits that were in the submodules?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment