Skip to content

Instantly share code, notes, and snippets.

@kch kch/modsux.rb
Created Nov 3, 2009

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

commented Dec 28, 2013

Thanks for this - supremely useful.

@csu

This comment has been minimized.

Copy link

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
You can’t perform that action at this time.