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