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