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