Created
September 14, 2010 23:35
-
-
Save TylerRick/579963 to your computer and use it in GitHub Desktop.
An early version of git-merge-better, part of http://github.com/TylerRick/tyler-git
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
#--------------------------------------------------------------------------------------------------- | |
# TODO: | |
# doesn't handle if multiple conflict markers!! | |
#--------------------------------------------------------------------------------------------------- | |
require 'pathname' | |
require 'facets/file/rewrite' | |
require 'quality_extensions/pathname' | |
#--------------------------------------------------------------------------------------------------- | |
# Parse args | |
require 'optparse' | |
@options = { | |
:use => 'conflicted' | |
} | |
def parse_args | |
ARGV.options do |opts| | |
opts.banner = <<End | |
Usage: #{File.basename($0)} [options] file_with_conflict | |
An alternative to git mergetool. | |
End | |
opts.on("--use which", "'conflicted' (default) to use conflicted file and strip out conflict versions") {|v| @options[:use] = v } | |
opts.on("-n", "--no-act", "Don't create/copy/modify files or open the editor") { @options[:no_act] = true } | |
opts.on("-v", "--verbose", "Be more verbose") { @options[:verbose] = true } | |
opts.on("-h", "--help", "Show this help message.") { puts opts; exit } | |
opts.parse! | |
end | |
end | |
parse_args | |
if ARGV.size == 0 | |
ARGV.unshift '--help' | |
parse_args | |
end | |
#--------------------------------------------------------------------------------------------------- | |
@file = Pathname.new(ARGV[0]) | |
ext = @file.extname | |
#--------------------------------------------------------------------------------------------------- | |
if (file = Pathname.new('.git/rebase-apply/onto')).exist? | |
upstream = file.read.chomp | |
upstream = `git name-rev --name-only --always --no-undefined #{upstream}`.chomp | |
merge_type = :rebase | |
end | |
if (file = Pathname.new('.git/rebase-apply/orig-head')).exist? | |
mine = file.read.chomp | |
mine = `git name-rev --name-only --always --no-undefined #{mine}`.chomp | |
end | |
merge_type ||= :merge | |
upstream ||= 'MERGE_HEAD' | |
mine ||= 'HEAD' | |
#merge_base = `git merge-base MERGE_HEAD HEAD`.chomp | |
merge_base = `git merge-base #{upstream} #{mine}`.chomp | |
merge_base = `git name-rev --name-only --always --no-undefined #{merge_base}`.chomp | |
#merge_head = `git rev-parse MERGE_HEAD`.chomp | |
puts "upstream=#{upstream.inspect}" | |
puts "mine=#{mine.inspect}" | |
puts "merge_base=#{merge_base.inspect}" | |
#--------------------------------------------------------------------------------------------------- | |
# TODO: how do we know? | |
# differs if doing rebase master vs merge master | |
# look at strings after <<<<<<<? | |
# perhaps MERGE_HEAD is missing/different for rebase? | |
mine_section = :top | |
def remove_section(s, section) | |
puts "removing #{section.inspect}" | |
if section == :top | |
s[/<<<<<<<.*=======/m] = '' | |
s[/>>>>>>>.*$/] = '' | |
else | |
s[/<<<<<<<.*$/] = '' | |
s[/=======.*>>>>>>>[^\n]*$/m] = '' | |
end | |
s | |
end | |
#--------------------------------------------------------------------------------------------------- | |
files = {'actual' => @file} | |
['mine_conflicted', 'upstream_conflicted'].each do |suffix| | |
unless @options[:no_act] | |
#if @options[:use] == 'conflicted' | |
new_file = @file.add_suffix(".#{suffix}#{ext}") | |
files[suffix] = new_file | |
@file.cp new_file | |
File.rewrite new_file do |s| | |
if suffix =~ /upstream/ | |
section_to_remove = mine_section == :top ? :top : :bottom | |
else | |
section_to_remove = mine_section == :top ? :bottom : :top | |
end | |
s = remove_section(s.dup, section_to_remove) | |
s | |
end | |
#end | |
end | |
end | |
['mine_actual', 'upstream_actual'].each do |suffix| | |
unless @options[:no_act] | |
#if @options[:use] == 'git show' | |
new_file = @file.add_suffix(".#{suffix}#{ext}") | |
files[suffix] = new_file | |
if suffix =~ /upstream/ | |
command = "git show #{upstream}:'#{@file}' >> '#{new_file}'" | |
else | |
command = "git show #{mine}:'#{@file}' >> '#{new_file}'" | |
end | |
files[suffix].open('w') {|f| f.puts command } | |
system command | |
#end | |
end | |
end | |
# TODO: can we do git checkout --theirs? | |
# or git cat-save commit:file ? | |
# > git-cat-save -c MERGE_HEAD:app/views/events/show.html.erb | |
# git show MERGE_HEAD:'app/views/events/show.html.erb' > 'app/views/events/show.html.erb.MERGE_HEAD.erb' | |
if merge_type == :rebase | |
upstream_from = "#{upstream}~15" | |
mine_from = "#{upstream}" | |
else | |
upstream_from = "#{merge_base}^" | |
mine_from = "#{merge_base}^" | |
end | |
[['upstream', upstream_from, upstream], | |
['mine', mine_from, mine] | |
].each do |suffix, from, up_to| | |
#--reverse | |
puts command = "git log -p #{from}..#{up_to} -- #{@file}" | |
#system command | |
files["#{suffix}.diff"] = @file.add_suffix(".#{suffix}.diff") | |
files["#{suffix}.diff"].open('w') {|f| f.puts command } | |
system "#{command} >> #{files["#{suffix}.diff"]}" | |
end | |
#gitk MERGE_HEAD | |
#puts command="vimdiff #{files['upstream']} #{files['mine']}" | |
puts command="vim -c 'e #{files['mine_conflicted']} | vert diffsplit #{files['upstream_conflicted']} | " + | |
# in their own window: | |
"tabedit #{files['mine_actual']} | vert diffsplit #{files['upstream_actual']} | wincmd w | " + | |
# diffs above main files (total of 4 buffers in window): | |
#"split #{files['upstream.diff']} | wincmd w | wincmd w | split #{files['mine.diff']} | wincmd w | " + | |
# diffs in their own window: | |
"tabedit #{files['mine.diff']} | vert split #{files['upstream.diff']} | wincmd w | " + | |
"tabedit #{@file} | vert diffsplit #{files['mine']} | wincmd w | " + | |
"tabnext 1 '" | |
exec command unless @options[:no_act] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment