1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano 4# 5 6USAGE='[-n] [--no-commit] [--squash] [-s <strategy>]... <merge-message> <head> <remote>+' 7. git-sh-setup 8 9LF=' 10' 11 12all_strategies='recur recursive recursive-old octopus resolve stupid ours' 13default_twohead_strategies='recursive' 14default_octopus_strategies='octopus' 15no_trivial_merge_strategies='ours' 16use_strategies= 17 18index_merge=t 19iftest"@@NO_PYTHON@@";then 20 all_strategies='recur recursive resolve octopus stupid ours' 21fi 22 23dropsave() { 24rm-f --"$GIT_DIR/MERGE_HEAD""$GIT_DIR/MERGE_MSG" \ 25"$GIT_DIR/MERGE_SAVE"||exit1 26} 27 28savestate() { 29# Stash away any local modifications. 30 git-diff-index -z --name-only$head| 31cpio-0 -o>"$GIT_DIR/MERGE_SAVE" 32} 33 34restorestate() { 35iftest -f"$GIT_DIR/MERGE_SAVE" 36then 37 git reset--hard$head 38cpio-iuv<"$GIT_DIR/MERGE_SAVE" 39 git-update-index --refresh>/dev/null 40fi 41} 42 43finish_up_to_date () { 44case"$squash"in 45 t) 46echo"$1(nothing to squash)";; 47'') 48echo"$1";; 49esac 50 dropsave 51} 52 53squash_message () { 54echo Squashed commit of the following: 55echo 56 git-log --no-merges ^"$head"$remote 57} 58 59finish () { 60iftest''="$2" 61then 62 rlogm="$rloga" 63else 64echo"$2" 65 rlogm="$rloga:$2" 66fi 67case"$squash"in 68 t) 69echo"Squash commit -- not updating HEAD" 70 squash_message >"$GIT_DIR/SQUASH_MSG" 71;; 72'') 73case"$merge_msg"in 74'') 75echo"No merge message -- not updating HEAD" 76;; 77*) 78 git-update-ref -m"$rlogm" HEAD "$1""$head"||exit1 79;; 80esac 81;; 82esac 83case"$1"in 84'') 85;; 86 ?*) 87case"$no_summary"in 88'') 89 git-diff-tree --stat --summary -M"$head""$1" 90;; 91esac 92;; 93esac 94} 95 96case"$#"in0) usage ;;esac 97 98rloga= 99while case"$#"in0)break;;esac 100do 101case"$1"in 102-n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\ 103--no-summa|--no-summar|--no-summary) 104 no_summary=t ;; 105--sq|--squ|--squa|--squas|--squash) 106 squash=t no_commit=t ;; 107--no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit) 108 no_commit=t ;; 109-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ 110--strateg=*|--strategy=*|\ 111-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) 112case"$#,$1"in 113*,*=*) 114 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'`;; 1151,*) 116 usage ;; 117*) 118 strategy="$2" 119shift;; 120esac 121case"$all_strategies"in 122*"$strategy"*) 123 use_strategies="$use_strategies$strategy";; 124*) 125 die "available strategies are:$all_strategies";; 126esac 127;; 128--reflog-action=*) 129 rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'` 130;; 131-*) usage ;; 132*)break;; 133esac 134shift 135done 136 137merge_msg="$1" 138shift 139head_arg="$1" 140head=$(git-rev-parse --verify "$1"^0)|| usage 141shift 142 143# All the rest are remote heads 144test"$#"=0&& usage ;# we need at least one remote head. 145test"$rloga"=''&& rloga="merge: $@" 146 147remoteheads= 148for remote 149do 150 remotehead=$(git-rev-parse --verify "$remote"^0)|| 151 die "$remote- not something we can merge" 152 remoteheads="${remoteheads}$remotehead" 153done 154set x $remoteheads;shift 155 156case"$use_strategies"in 157'') 158case"$#"in 1591) 160 use_strategies="$default_twohead_strategies";; 161*) 162 use_strategies="$default_octopus_strategies";; 163esac 164;; 165esac 166 167for s in$use_strategies 168do 169case"$s"in 170*"$no_trivial_merge_strategies"*) 171 index_merge=f 172break 173;; 174esac 175done 176 177case"$#"in 1781) 179 common=$(git-merge-base --all $head "$@") 180;; 181*) 182 common=$(git-show-branch --merge-base $head "$@") 183;; 184esac 185echo"$head">"$GIT_DIR/ORIG_HEAD" 186 187case"$index_merge,$#,$common,$no_commit"in 188f,*) 189# We've been told not to try anything clever. Skip to real merge. 190;; 191?,*,'',*) 192# No common ancestors found. We need a real merge. 193;; 194?,1,"$1",*) 195# If head can reach all the merge then we are up to date. 196# but first the most common case of merging one remote. 197 finish_up_to_date "Already up-to-date." 198exit0 199;; 200?,1,"$head",*) 201# Again the most common case of merging one remote. 202echo"Updating$(git-rev-parse --short $head)..$(git-rev-parse --short $1)" 203 git-update-index --refresh2>/dev/null 204 new_head=$(git-rev-parse --verify "$1^0")&& 205 git-read-tree -u -v -m$head"$new_head"&& 206 finish "$new_head""Fast forward" 207 dropsave 208exit0 209;; 210?,1,?*"$LF"?*,*) 211# We are not doing octopus and not fast forward. Need a 212# real merge. 213;; 214?,1,*,) 215# We are not doing octopus, not fast forward, and have only 216# one common. See if it is really trivial. 217 git var GIT_COMMITTER_IDENT >/dev/null ||exit 218 219echo"Trying really trivial in-index merge..." 220 git-update-index --refresh2>/dev/null 221if git-read-tree --trivial -m -u -v$common $head"$1"&& 222 result_tree=$(git-write-tree) 223then 224echo"Wonderful." 225 result_commit=$( 226echo"$merge_msg"| 227 git-commit-tree$result_tree-p HEAD -p"$1" 228) ||exit 229 finish "$result_commit""In-index merge" 230 dropsave 231exit0 232fi 233echo"Nope." 234;; 235*) 236# An octopus. If we can reach all the remote we are up to date. 237 up_to_date=t 238for remote 239do 240 common_one=$(git-merge-base --all $head $remote) 241iftest"$common_one"!="$remote" 242then 243 up_to_date=f 244break 245fi 246done 247iftest"$up_to_date"= t 248then 249 finish_up_to_date "Already up-to-date. Yeeah!" 250exit0 251fi 252;; 253esac 254 255# We are going to make a new commit. 256git var GIT_COMMITTER_IDENT >/dev/null ||exit 257 258# At this point, we need a real merge. No matter what strategy 259# we use, it would operate on the index, possibly affecting the 260# working tree, and when resolved cleanly, have the desired tree 261# in the index -- this means that the index must be in sync with 262# the $head commit. The strategies are responsible to ensure this. 263 264case"$use_strategies"in 265?*' '?*) 266# Stash away the local changes so that we can try more than one. 267 savestate 268 single_strategy=no 269;; 270*) 271rm-f"$GIT_DIR/MERGE_SAVE" 272 single_strategy=yes 273;; 274esac 275 276result_tree= best_cnt=-1 best_strategy= wt_strategy= 277merge_was_ok= 278for strategy in$use_strategies 279do 280test"$wt_strategy"=''|| { 281echo"Rewinding the tree to pristine..." 282 restorestate 283} 284case"$single_strategy"in 285 no) 286echo"Trying merge strategy$strategy..." 287;; 288esac 289 290# Remember which strategy left the state in the working tree 291 wt_strategy=$strategy 292 293 git-merge-$strategy $common--"$head_arg""$@" 294exit=$? 295iftest"$no_commit"= t &&test"$exit"=0 296then 297 merge_was_ok=t 298exit=1;# pretend it left conflicts. 299fi 300 301test"$exit"=0|| { 302 303# The backend exits with 1 when conflicts are left to be resolved, 304# with 2 when it does not handle the given merge at all. 305 306iftest"$exit"-eq1 307then 308 cnt=`{ 309 git-diff-files --name-only 310 git-ls-files --unmerged 311 } | wc -l` 312iftest$best_cnt-le0-o$cnt-le$best_cnt 313then 314 best_strategy=$strategy 315 best_cnt=$cnt 316fi 317fi 318continue 319} 320 321# Automerge succeeded. 322 result_tree=$(git-write-tree)&&break 323done 324 325# If we have a resulting tree, that means the strategy module 326# auto resolved the merge cleanly. 327iftest''!="$result_tree" 328then 329 parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /') 330 result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents)||exit 331 finish "$result_commit""Merge made by$wt_strategy." 332 dropsave 333exit0 334fi 335 336# Pick the result from the best strategy and have the user fix it up. 337case"$best_strategy"in 338'') 339 restorestate 340echo>&2"No merge strategy handled the merge." 341exit2 342;; 343"$wt_strategy") 344# We already have its result in the working tree. 345;; 346*) 347echo"Rewinding the tree to pristine..." 348 restorestate 349echo"Using the$best_strategyto prepare resolving by hand." 350 git-merge-$best_strategy $common--"$head_arg""$@" 351;; 352esac 353 354iftest"$squash"= t 355then 356 finish 357else 358for remote 359do 360echo$remote 361done>"$GIT_DIR/MERGE_HEAD" 362echo"$merge_msg">"$GIT_DIR/MERGE_MSG" 363fi 364 365iftest"$merge_was_ok"= t 366then 367echo>&2 \ 368"Automatic merge went well; stopped before committing as requested" 369exit0 370else 371{ 372echo' 373Conflicts: 374' 375 git ls-files --unmerged| 376sed-e's/^[^ ]* / /'| 377uniq 378} >>"$GIT_DIR/MERGE_MSG" 379iftest -d"$GIT_DIR/rr-cache" 380then 381 git-rerere 382fi 383 die "Automatic merge failed; fix conflicts and then commit the result." 384fi