1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano 4# 5 6. git-sh-setup|| die "Not a git archive" 7 8LF=' 9' 10 11usage () { 12 die "git-merge [-n] [-s <strategy>]... <merge-message> <head> <remote>+" 13} 14 15# all_strategies='resolve recursive stupid octopus' 16 17all_strategies='recursive octopus resolve stupid' 18default_strategies='resolve octopus' 19use_strategies= 20 21dropsave() { 22rm-f --"$GIT_DIR/MERGE_HEAD""$GIT_DIR/MERGE_MSG" \ 23"$GIT_DIR/MERGE_SAVE"||exit1 24} 25 26savestate() { 27# Stash away any local modifications. 28 git-diff-index -r -z --name-only$head| 29cpio-0 -o>"$GIT_DIR/MERGE_SAVE" 30} 31 32restorestate() { 33iftest -f"$GIT_DIR/MERGE_SAVE" 34then 35 git reset--hard$head 36cpio-iuv<"$GIT_DIR/MERGE_SAVE" 37 git-update-index --refresh>/dev/null 38fi 39} 40 41summary() { 42case"$no_summary"in 43'') 44 git-diff-tree -p -M$head"$1"| 45 git-apply --stat --summary 46;; 47esac 48} 49 50while case"$#"in0)break;;esac 51do 52case"$1"in 53-n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\ 54--no-summa|--no-summar|--no-summary) 55 no_summary=t ;; 56-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ 57--strateg=*|--strategy=*|\ 58-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) 59case"$#,$1"in 60*,*=*) 61 strategy=`expr "$1" : '-[^=]*=\(.*\)'`;; 621,*) 63 usage ;; 64*) 65 strategy="$2" 66shift;; 67esac 68case"$all_strategies"in 69*"$strategy"*) 70 use_strategies="$use_strategies$strategy";; 71*) 72 die "available strategies are:$all_strategies";; 73esac 74;; 75-*) usage ;; 76*)break;; 77esac 78shift 79done 80 81case"$use_strategies"in 82'') 83 use_strategies=$default_strategies 84;; 85esac 86test"$#"-le2&& usage ;# we need at least two heads. 87 88merge_msg="$1" 89shift 90head_arg="$1" 91head=$(git-rev-parse --verify "$1"^0)|| usage 92shift 93 94# All the rest are remote heads 95for remote 96do 97 git-rev-parse --verify"$remote"^0>/dev/null || 98 die "$remote- not something we can merge" 99done 100 101common=$(git-show-branch --merge-base $head "$@") 102echo"$head">"$GIT_DIR/ORIG_HEAD" 103 104case"$#,$common"in 105*,'') 106# No common ancestors found. We need a real merge. 107;; 1081,"$1") 109# If head can reach all the merge then we are up to date. 110# but first the most common case of merging one remote 111echo"Already up-to-date. Yeeah!" 112 dropsave 113exit0 114;; 1151,"$head") 116# Again the most common case of merging one remote. 117echo"Updating from$headto$1." 118 git-update-index --refresh2>/dev/null 119 git-read-tree -u -m$head"$1"&& 120 new_head=$(git-rev-parse --verify "$1^0")&& 121 git-update-ref HEAD "$new_head""$head"||exit1 122 summary "$1" 123 dropsave 124exit0 125;; 1261,?*"$LF"?*) 127# We are not doing octopus and not fast forward. Need a 128# real merge. 129;; 1301,*) 131# We are not doing octopus, not fast forward, and have only 132# one common. See if it is really trivial. 133echo"Trying really trivial in-index merge..." 134 git-update-index --refresh2>/dev/null 135if git-read-tree --trivial -m -u$common $head"$1"&& 136 result_tree=$(git-write-tree) 137then 138echo"Wonderful." 139 result_commit=$( 140echo"$merge_msg"| 141 git-commit-tree$result_tree-p HEAD -p"$1" 142) ||exit 143 git-update-ref HEAD $result_commit $head 144 summary $result_commit 145 dropsave 146exit0 147fi 148echo"Nope." 149;; 150*) 151# An octopus. If we can reach all the remote we are up to date. 152 up_to_date=t 153for remote 154do 155 common_one=$(git-merge-base $head $remote) 156iftest"$common_one"!="$remote" 157then 158 up_to_date=f 159break 160fi 161done 162iftest"$up_to_date"= t 163then 164echo"Already up-to-date. Yeeah!" 165 dropsave 166exit0 167fi 168;; 169esac 170 171# At this point, we need a real merge. No matter what strategy 172# we use, it would operate on the index, possibly affecting the 173# working tree, and when resolved cleanly, have the desired tree 174# in the index -- this means that the index must be in sync with 175# the $head commit. The strategies are responsible to ensure this. 176 177case"$use_strategies"in 178?*' '?*) 179# Stash away the local changes so that we can try more than one. 180 savestate 181 single_strategy=no 182;; 183*) 184rm-f"$GIT_DIR/MERGE_SAVE" 185 single_strategy=yes 186;; 187esac 188 189result_tree= best_cnt=-1 best_strategy= wt_strategy= 190for strategy in$use_strategies 191do 192test"$wt_strategy"=''|| { 193echo"Rewinding the tree to pristine..." 194 restorestate 195} 196case"$single_strategy"in 197 no) 198echo"Trying merge strategy$strategy..." 199;; 200esac 201 202# Remember which strategy left the state in the working tree 203 wt_strategy=$strategy 204 205 git-merge-$strategy $common--"$head_arg""$@"|| { 206 207# The backend exits with 1 when conflicts are left to be resolved, 208# with 2 when it does not handle the given merge at all. 209 210exit=$? 211iftest"$exit"-eq1 212then 213 cnt=`{ 214 git-diff-files --name-only 215 git-ls-files --unmerged 216 } | wc -l` 217iftest$best_cnt-le0-o$cnt-le$best_cnt 218then 219 best_strategy=$strategy 220 best_cnt=$cnt 221fi 222fi 223continue 224} 225 226# Automerge succeeded. 227 result_tree=$(git-write-tree)&&break 228done 229 230# If we have a resulting tree, that means the strategy module 231# auto resolved the merge cleanly. 232iftest''!="$result_tree" 233then 234 parents="-p$head" 235for remote 236do 237 parents="$parents-p$remote" 238done 239 result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents)||exit 240echo"Committed merge$result_commit, made by$wt_strategy." 241 git-update-ref HEAD $result_commit $head 242 summary $result_commit 243 dropsave 244exit0 245fi 246 247# Pick the result from the best strategy and have the user fix it up. 248case"$best_strategy"in 249'') 250 restorestate 251 die "No merge strategy handled the merge." 252;; 253"$wt_strategy") 254# We already have its result in the working tree. 255;; 256*) 257echo"Rewinding the tree to pristine..." 258 restorestate 259echo"Using the$best_strategyto prepare resolving by hand." 260 git-merge-$best_strategy $common--"$head_arg""$@" 261;; 262esac 263for remote 264do 265echo$remote 266done>"$GIT_DIR/MERGE_HEAD" 267echo$merge_msg>"$GIT_DIR/MERGE_MSG" 268 269die "Automatic merge failed; fix up by hand"