Tim Dysinger RSS

Apr
29th
Tue
permalink

Replacing Braid or Piston (for Git) with 40 lines of Rake

I was playing around with Braid and Piston for Git and didn't like either of them. I didn't feel like Piston was ready for Git andBraid seemed to complex. I just wanted git subtrees. Braid is doing the same thing but with more code around it. I like simple. It actually turns out that Git has all the tools built in to do sub-tree merging and updating. It's really easy with a few sake (or rake) tasks. I am using this on a rails project with more than a dozen plugins and vendor/rails. Update 6/7: I added a diff task and corrected a typo
# Git Sub-Trees Sake Tasks
# http://rubyurl.com/BwnY < - Read about the technique vs submodules
#
# This works super good with Rails plugins or when you are actively working
# on two related projects.
#
# Add these tasks with:
#   sake -i http://pastie.caboo.se/213492.rb
#
# Example Usage:
#
#   sake git:subtree:remote
#     Git Repo Url? git://github.com/mislav/will_paginate.git
#     Remote Name? vendor/plugins/will_paginate
#   sake git:subtree:merge
#     Branch? will_paginate/tags/2.2.2
#     Destination? vendor/plugins/will_paginate
#   git commit
#
# From time to time update your remotes:
#   git remote update
#   -or-
#   git fetch vendor/plugins/will_paginate
#
# View diffs:
#
#   sake git:subtree:diff
#     Branch? vendor/plugins/will_paginate/tags/2.2.3
#
# Merge in updates:
#
#   sake git:subtree:update
#     Branch? vendor/plugins/will_paginate/tags/2.2.3
#   git commit

desc 'Add an external project as a remote'
task 'git:subtree:remote' do
  require "readline"
  url = begin
    print "Git Repo Url? "
    Readline.readline.chomp
  end
  name = begin
    print "Remote Name? "
    Readline.readline.chomp
  end
  `git remote add #{name} #{url}`
  `git config remote.#{name}.fetch refs/heads/*:refs/remotes/#{name}/*`
  `git config --add remote.#{name}.fetch refs/tags/*:refs/remotes/#{name}/tags/*`
  `git config remote.#{name}.tagopt --no-tags`
  `git fetch #{name}`
end

desc 'Merge an external project as a sub-tree'
task 'git:subtree:merge' do
  require "readline"
  branch = begin
    print "Branch? "
    Readline.readline.chomp
  end
  dest = begin
    print "Destination? "
    Readline.readline.chomp
  end
  `git merge --squash -s ours --no-commit #{branch}`
  `git read-tree --prefix=#{dest} -u #{branch}`
end

desc 'Update an existing subtree project'
task 'git:subtree:update' do
  require "readline"
  branch = begin
    print "Branch? "
    Readline.readline.chomp
  end
  `git merge --squash -s subtree --no-commit #{branch}`
end

desc 'Show subtree diff against remote'
task 'git:subtree:diff' do
  require "readline"
  branch = begin
    print "Branch? "
    Readline.readline.chomp
  end
  puts `git-diff-tree -p #{branch}`
end