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