Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | # |
| 3 | # This program resolves merge conflicts in git |
| 4 | # |
| 5 | # Copyright (c) 2006 Theodore Y. Ts'o |
| 6 | # |
| 7 | # This file is licensed under the GPL v2, or a later version |
Josh Triplett | 2571ac6 | 2007-06-05 21:24:19 -0700 | [diff] [blame] | 8 | # at the discretion of Junio C Hamano. |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 9 | # |
| 10 | |
Charles Bailey | 682b451 | 2008-11-13 12:41:14 +0000 | [diff] [blame] | 11 | USAGE='[--tool=tool] [-y|--no-prompt|--prompt] [file to merge] ...' |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 12 | SUBDIRECTORY_OK=Yes |
Junio C Hamano | 8f321a3 | 2007-11-06 01:50:02 -0800 | [diff] [blame] | 13 | OPTIONS_SPEC= |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 14 | TOOL_MODE=merge |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 15 | . git-sh-setup |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 16 | . git-mergetool--lib |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 17 | require_work_tree |
| 18 | |
| 19 | # Returns true if the mode reflects a symlink |
Theodore Ts'o | 262c981 | 2007-03-29 06:55:11 -0400 | [diff] [blame] | 20 | is_symlink () { |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 21 | test "$1" = 120000 |
| 22 | } |
| 23 | |
Jonathon Mah | ff7f089 | 2011-04-13 03:00:48 -0700 | [diff] [blame] | 24 | is_submodule () { |
| 25 | test "$1" = 160000 |
| 26 | } |
| 27 | |
Theodore Ts'o | 262c981 | 2007-03-29 06:55:11 -0400 | [diff] [blame] | 28 | local_present () { |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 29 | test -n "$local_mode" |
| 30 | } |
| 31 | |
Theodore Ts'o | 262c981 | 2007-03-29 06:55:11 -0400 | [diff] [blame] | 32 | remote_present () { |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 33 | test -n "$remote_mode" |
| 34 | } |
| 35 | |
Theodore Ts'o | 262c981 | 2007-03-29 06:55:11 -0400 | [diff] [blame] | 36 | base_present () { |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 37 | test -n "$base_mode" |
| 38 | } |
| 39 | |
| 40 | cleanup_temp_files () { |
| 41 | if test "$1" = --save-backup ; then |
Jonathon Mah | ff7f089 | 2011-04-13 03:00:48 -0700 | [diff] [blame] | 42 | rm -rf -- "$MERGED.orig" |
| 43 | test -e "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 44 | rm -f -- "$LOCAL" "$REMOTE" "$BASE" |
| 45 | else |
| 46 | rm -f -- "$LOCAL" "$REMOTE" "$BASE" "$BACKUP" |
| 47 | fi |
| 48 | } |
| 49 | |
Theodore Ts'o | 262c981 | 2007-03-29 06:55:11 -0400 | [diff] [blame] | 50 | describe_file () { |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 51 | mode="$1" |
| 52 | branch="$2" |
| 53 | file="$3" |
| 54 | |
Theodore Ts'o | 27090aa | 2007-03-29 11:39:46 -0400 | [diff] [blame] | 55 | printf " {%s}: " "$branch" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 56 | if test -z "$mode"; then |
Theodore Ts'o | 27090aa | 2007-03-29 11:39:46 -0400 | [diff] [blame] | 57 | echo "deleted" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 58 | elif is_symlink "$mode" ; then |
Theodore Ts'o | 27090aa | 2007-03-29 11:39:46 -0400 | [diff] [blame] | 59 | echo "a symbolic link -> '$(cat "$file")'" |
Jonathon Mah | ff7f089 | 2011-04-13 03:00:48 -0700 | [diff] [blame] | 60 | elif is_submodule "$mode" ; then |
| 61 | echo "submodule commit $file" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 62 | else |
| 63 | if base_present; then |
Jonathon Mah | ff7f089 | 2011-04-13 03:00:48 -0700 | [diff] [blame] | 64 | echo "modified file" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 65 | else |
Jonathon Mah | ff7f089 | 2011-04-13 03:00:48 -0700 | [diff] [blame] | 66 | echo "created file" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 67 | fi |
| 68 | fi |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | |
| 72 | resolve_symlink_merge () { |
Theodore Ts'o | d1dc695 | 2007-03-29 06:46:59 -0400 | [diff] [blame] | 73 | while true; do |
Theodore Ts'o | 27090aa | 2007-03-29 11:39:46 -0400 | [diff] [blame] | 74 | printf "Use (l)ocal or (r)emote, or (a)bort? " |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 75 | read ans |
| 76 | case "$ans" in |
| 77 | [lL]*) |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 78 | git checkout-index -f --stage=2 -- "$MERGED" |
| 79 | git add -- "$MERGED" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 80 | cleanup_temp_files --save-backup |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 81 | return 0 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 82 | ;; |
Theodore Ts'o | 5a174f1 | 2007-03-29 09:48:31 -0400 | [diff] [blame] | 83 | [rR]*) |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 84 | git checkout-index -f --stage=3 -- "$MERGED" |
| 85 | git add -- "$MERGED" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 86 | cleanup_temp_files --save-backup |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 87 | return 0 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 88 | ;; |
Theodore Ts'o | 5a174f1 | 2007-03-29 09:48:31 -0400 | [diff] [blame] | 89 | [aA]*) |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 90 | return 1 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 91 | ;; |
| 92 | esac |
| 93 | done |
| 94 | } |
| 95 | |
| 96 | resolve_deleted_merge () { |
Theodore Ts'o | d1dc695 | 2007-03-29 06:46:59 -0400 | [diff] [blame] | 97 | while true; do |
Theodore Ts'o | 27090aa | 2007-03-29 11:39:46 -0400 | [diff] [blame] | 98 | if base_present; then |
| 99 | printf "Use (m)odified or (d)eleted file, or (a)bort? " |
| 100 | else |
| 101 | printf "Use (c)reated or (d)eleted file, or (a)bort? " |
| 102 | fi |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 103 | read ans |
| 104 | case "$ans" in |
Theodore Ts'o | 27090aa | 2007-03-29 11:39:46 -0400 | [diff] [blame] | 105 | [mMcC]*) |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 106 | git add -- "$MERGED" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 107 | cleanup_temp_files --save-backup |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 108 | return 0 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 109 | ;; |
Theodore Ts'o | 5a174f1 | 2007-03-29 09:48:31 -0400 | [diff] [blame] | 110 | [dD]*) |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 111 | git rm -- "$MERGED" > /dev/null |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 112 | cleanup_temp_files |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 113 | return 0 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 114 | ;; |
Theodore Ts'o | 5a174f1 | 2007-03-29 09:48:31 -0400 | [diff] [blame] | 115 | [aA]*) |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 116 | return 1 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 117 | ;; |
| 118 | esac |
| 119 | done |
| 120 | } |
| 121 | |
Jonathon Mah | ff7f089 | 2011-04-13 03:00:48 -0700 | [diff] [blame] | 122 | resolve_submodule_merge () { |
| 123 | while true; do |
| 124 | printf "Use (l)ocal or (r)emote, or (a)bort? " |
| 125 | read ans |
| 126 | case "$ans" in |
| 127 | [lL]*) |
| 128 | if ! local_present; then |
| 129 | if test -n "$(git ls-tree HEAD -- "$MERGED")"; then |
| 130 | # Local isn't present, but it's a subdirectory |
| 131 | git ls-tree --full-name -r HEAD -- "$MERGED" | git update-index --index-info || exit $? |
| 132 | else |
| 133 | test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" |
| 134 | git update-index --force-remove "$MERGED" |
| 135 | cleanup_temp_files --save-backup |
| 136 | fi |
| 137 | elif is_submodule "$local_mode"; then |
| 138 | stage_submodule "$MERGED" "$local_sha1" |
| 139 | else |
| 140 | git checkout-index -f --stage=2 -- "$MERGED" |
| 141 | git add -- "$MERGED" |
| 142 | fi |
| 143 | return 0 |
| 144 | ;; |
| 145 | [rR]*) |
| 146 | if ! remote_present; then |
| 147 | if test -n "$(git ls-tree MERGE_HEAD -- "$MERGED")"; then |
| 148 | # Remote isn't present, but it's a subdirectory |
| 149 | git ls-tree --full-name -r MERGE_HEAD -- "$MERGED" | git update-index --index-info || exit $? |
| 150 | else |
| 151 | test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" |
| 152 | git update-index --force-remove "$MERGED" |
| 153 | fi |
| 154 | elif is_submodule "$remote_mode"; then |
| 155 | ! is_submodule "$local_mode" && test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" |
| 156 | stage_submodule "$MERGED" "$remote_sha1" |
| 157 | else |
| 158 | test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" |
| 159 | git checkout-index -f --stage=3 -- "$MERGED" |
| 160 | git add -- "$MERGED" |
| 161 | fi |
| 162 | cleanup_temp_files --save-backup |
| 163 | return 0 |
| 164 | ;; |
| 165 | [aA]*) |
| 166 | return 1 |
| 167 | ;; |
| 168 | esac |
| 169 | done |
| 170 | } |
| 171 | |
| 172 | stage_submodule () { |
| 173 | path="$1" |
| 174 | submodule_sha1="$2" |
| 175 | mkdir -p "$path" || die "fatal: unable to create directory for module at $path" |
| 176 | # Find $path relative to work tree |
| 177 | work_tree_root=$(cd_to_toplevel && pwd) |
| 178 | work_rel_path=$(cd "$path" && GIT_WORK_TREE="${work_tree_root}" git rev-parse --show-prefix) |
| 179 | test -n "$work_rel_path" || die "fatal: unable to get path of module $path relative to work tree" |
| 180 | git update-index --add --replace --cacheinfo 160000 "$submodule_sha1" "${work_rel_path%/}" || die |
| 181 | } |
| 182 | |
Charles Bailey | 0ec7b6c | 2009-01-21 22:57:48 +0000 | [diff] [blame] | 183 | checkout_staged_file () { |
| 184 | tmpfile=$(expr "$(git checkout-index --temp --stage="$1" "$2")" : '\([^ ]*\) ') |
| 185 | |
| 186 | if test $? -eq 0 -a -n "$tmpfile" ; then |
Charles Bailey | ff4a185 | 2009-01-30 23:20:11 +0000 | [diff] [blame] | 187 | mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3" |
Charles Bailey | 0ec7b6c | 2009-01-21 22:57:48 +0000 | [diff] [blame] | 188 | fi |
| 189 | } |
| 190 | |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 191 | merge_file () { |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 192 | MERGED="$1" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 193 | |
David Aguilar | 9a62d72 | 2009-04-06 01:31:28 -0700 | [diff] [blame] | 194 | f=$(git ls-files -u -- "$MERGED") |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 195 | if test -z "$f" ; then |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 196 | if test ! -f "$MERGED" ; then |
| 197 | echo "$MERGED: file not found" |
Theodore Ts'o | ce5b6d7 | 2007-03-27 18:00:03 -0400 | [diff] [blame] | 198 | else |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 199 | echo "$MERGED: file does not need merging" |
Theodore Ts'o | ce5b6d7 | 2007-03-27 18:00:03 -0400 | [diff] [blame] | 200 | fi |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 201 | return 1 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 202 | fi |
| 203 | |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 204 | ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')" |
Patrick Higgins | 641dba4 | 2008-06-16 17:33:41 -0600 | [diff] [blame] | 205 | BACKUP="./$MERGED.BACKUP.$ext" |
| 206 | LOCAL="./$MERGED.LOCAL.$ext" |
| 207 | REMOTE="./$MERGED.REMOTE.$ext" |
| 208 | BASE="./$MERGED.BASE.$ext" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 209 | |
David Aguilar | 9a62d72 | 2009-04-06 01:31:28 -0700 | [diff] [blame] | 210 | base_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}') |
| 211 | local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}') |
| 212 | remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}') |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 213 | |
Jonathon Mah | ff7f089 | 2011-04-13 03:00:48 -0700 | [diff] [blame] | 214 | if is_submodule "$local_mode" || is_submodule "$remote_mode"; then |
| 215 | echo "Submodule merge conflict for '$MERGED':" |
| 216 | local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}') |
| 217 | remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}') |
| 218 | describe_file "$local_mode" "local" "$local_sha1" |
| 219 | describe_file "$remote_mode" "remote" "$remote_sha1" |
| 220 | resolve_submodule_merge |
| 221 | return |
| 222 | fi |
| 223 | |
| 224 | mv -- "$MERGED" "$BACKUP" |
| 225 | cp -- "$BACKUP" "$MERGED" |
| 226 | |
Charles Bailey | ff4a185 | 2009-01-30 23:20:11 +0000 | [diff] [blame] | 227 | base_present && checkout_staged_file 1 "$MERGED" "$BASE" |
| 228 | local_present && checkout_staged_file 2 "$MERGED" "$LOCAL" |
| 229 | remote_present && checkout_staged_file 3 "$MERGED" "$REMOTE" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 230 | |
| 231 | if test -z "$local_mode" -o -z "$remote_mode"; then |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 232 | echo "Deleted merge conflict for '$MERGED':" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 233 | describe_file "$local_mode" "local" "$LOCAL" |
| 234 | describe_file "$remote_mode" "remote" "$REMOTE" |
| 235 | resolve_deleted_merge |
| 236 | return |
| 237 | fi |
| 238 | |
| 239 | if is_symlink "$local_mode" || is_symlink "$remote_mode"; then |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 240 | echo "Symbolic link merge conflict for '$MERGED':" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 241 | describe_file "$local_mode" "local" "$LOCAL" |
| 242 | describe_file "$remote_mode" "remote" "$REMOTE" |
| 243 | resolve_symlink_merge |
| 244 | return |
| 245 | fi |
| 246 | |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 247 | echo "Normal merge conflict for '$MERGED':" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 248 | describe_file "$local_mode" "local" "$LOCAL" |
| 249 | describe_file "$remote_mode" "remote" "$REMOTE" |
Charles Bailey | 682b451 | 2008-11-13 12:41:14 +0000 | [diff] [blame] | 250 | if "$prompt" = true; then |
| 251 | printf "Hit return to start merge resolution tool (%s): " "$merge_tool" |
| 252 | read ans |
| 253 | fi |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 254 | |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 255 | if base_present; then |
| 256 | present=true |
| 257 | else |
| 258 | present=false |
| 259 | fi |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 260 | |
| 261 | if ! run_merge_tool "$merge_tool" "$present"; then |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 262 | echo "merge of $MERGED failed" 1>&2 |
| 263 | mv -- "$BACKUP" "$MERGED" |
Charles Bailey | 162eba8 | 2008-12-12 21:48:41 +0000 | [diff] [blame] | 264 | |
| 265 | if test "$merge_keep_temporaries" = "false"; then |
| 266 | cleanup_temp_files |
| 267 | fi |
| 268 | |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 269 | return 1 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 270 | fi |
Charles Bailey | 44c36d1 | 2008-02-21 23:30:02 +0000 | [diff] [blame] | 271 | |
| 272 | if test "$merge_keep_backup" = "true"; then |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 273 | mv -- "$BACKUP" "$MERGED.orig" |
Charles Bailey | 44c36d1 | 2008-02-21 23:30:02 +0000 | [diff] [blame] | 274 | else |
| 275 | rm -- "$BACKUP" |
| 276 | fi |
| 277 | |
Charles Bailey | b3ea27e | 2008-02-21 23:30:34 +0000 | [diff] [blame] | 278 | git add -- "$MERGED" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 279 | cleanup_temp_files |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 280 | return 0 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 281 | } |
| 282 | |
Charles Bailey | 682b451 | 2008-11-13 12:41:14 +0000 | [diff] [blame] | 283 | prompt=$(git config --bool mergetool.prompt || echo true) |
| 284 | |
David Kastrup | 822f7c7 | 2007-09-23 22:42:08 +0200 | [diff] [blame] | 285 | while test $# != 0 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 286 | do |
| 287 | case "$1" in |
| 288 | -t|--tool*) |
| 289 | case "$#,$1" in |
| 290 | *,*=*) |
David Aguilar | 9a62d72 | 2009-04-06 01:31:28 -0700 | [diff] [blame] | 291 | merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 292 | ;; |
| 293 | 1,*) |
| 294 | usage ;; |
| 295 | *) |
| 296 | merge_tool="$2" |
| 297 | shift ;; |
| 298 | esac |
| 299 | ;; |
Charles Bailey | 682b451 | 2008-11-13 12:41:14 +0000 | [diff] [blame] | 300 | -y|--no-prompt) |
| 301 | prompt=false |
| 302 | ;; |
| 303 | --prompt) |
| 304 | prompt=true |
| 305 | ;; |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 306 | --) |
David Aguilar | ce2c3eb | 2008-12-19 17:01:01 -0800 | [diff] [blame] | 307 | shift |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 308 | break |
| 309 | ;; |
| 310 | -*) |
| 311 | usage |
| 312 | ;; |
| 313 | *) |
| 314 | break |
| 315 | ;; |
| 316 | esac |
| 317 | shift |
| 318 | done |
| 319 | |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 320 | prompt_after_failed_merge() { |
| 321 | while true; do |
| 322 | printf "Continue merging other unresolved paths (y/n) ? " |
| 323 | read ans |
| 324 | case "$ans" in |
| 325 | |
| 326 | [yY]*) |
| 327 | return 0 |
| 328 | ;; |
| 329 | |
| 330 | [nN]*) |
| 331 | return 1 |
| 332 | ;; |
| 333 | esac |
| 334 | done |
| 335 | } |
Steffen Prohaska | e3fa2c7 | 2007-10-17 19:16:11 +0200 | [diff] [blame] | 336 | |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 337 | if test -z "$merge_tool"; then |
| 338 | merge_tool=$(get_merge_tool "$merge_tool") || exit |
| 339 | fi |
Ferry Huberts | 70af4e9 | 2009-04-10 21:33:57 +0200 | [diff] [blame] | 340 | merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 341 | merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 342 | |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 343 | last_status=0 |
| 344 | rollup_status=0 |
David Aguilar | bb0a484 | 2010-08-17 02:22:46 -0700 | [diff] [blame] | 345 | rerere=false |
| 346 | |
| 347 | files_to_merge() { |
| 348 | if test "$rerere" = true |
| 349 | then |
Martin von Zweigbergk | 2f59c94 | 2011-02-16 05:47:45 -0500 | [diff] [blame] | 350 | git rerere remaining |
David Aguilar | bb0a484 | 2010-08-17 02:22:46 -0700 | [diff] [blame] | 351 | else |
| 352 | git ls-files -u | sed -e 's/^[^ ]* //' | sort -u |
| 353 | fi |
| 354 | } |
| 355 | |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 356 | |
| 357 | if test $# -eq 0 ; then |
David Aguilar | bb0a484 | 2010-08-17 02:22:46 -0700 | [diff] [blame] | 358 | cd_to_toplevel |
| 359 | |
| 360 | if test -e "$GIT_DIR/MERGE_RR" |
| 361 | then |
| 362 | rerere=true |
| 363 | fi |
| 364 | |
| 365 | files=$(files_to_merge) |
Charles Bailey | 0eea345 | 2008-11-13 12:41:13 +0000 | [diff] [blame] | 366 | if test -z "$files" ; then |
| 367 | echo "No files need merging" |
| 368 | exit 0 |
| 369 | fi |
Charles Bailey | af31471 | 2010-08-20 16:25:09 +0100 | [diff] [blame] | 370 | |
| 371 | # Save original stdin |
| 372 | exec 3<&0 |
| 373 | |
David Aguilar | bb0a484 | 2010-08-17 02:22:46 -0700 | [diff] [blame] | 374 | printf "Merging:\n" |
| 375 | printf "$files\n" |
| 376 | |
| 377 | files_to_merge | |
Charles Bailey | 0eea345 | 2008-11-13 12:41:13 +0000 | [diff] [blame] | 378 | while IFS= read i |
| 379 | do |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 380 | if test $last_status -ne 0; then |
Charles Bailey | af31471 | 2010-08-20 16:25:09 +0100 | [diff] [blame] | 381 | prompt_after_failed_merge <&3 || exit 1 |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 382 | fi |
Charles Bailey | 0eea345 | 2008-11-13 12:41:13 +0000 | [diff] [blame] | 383 | printf "\n" |
Charles Bailey | af31471 | 2010-08-20 16:25:09 +0100 | [diff] [blame] | 384 | merge_file "$i" <&3 |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 385 | last_status=$? |
| 386 | if test $last_status -ne 0; then |
| 387 | rollup_status=1 |
| 388 | fi |
Charles Bailey | 0eea345 | 2008-11-13 12:41:13 +0000 | [diff] [blame] | 389 | done |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 390 | else |
Charles Bailey | 0eea345 | 2008-11-13 12:41:13 +0000 | [diff] [blame] | 391 | while test $# -gt 0; do |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 392 | if test $last_status -ne 0; then |
| 393 | prompt_after_failed_merge || exit 1 |
| 394 | fi |
Charles Bailey | 0eea345 | 2008-11-13 12:41:13 +0000 | [diff] [blame] | 395 | printf "\n" |
| 396 | merge_file "$1" |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 397 | last_status=$? |
| 398 | if test $last_status -ne 0; then |
| 399 | rollup_status=1 |
| 400 | fi |
Charles Bailey | 0eea345 | 2008-11-13 12:41:13 +0000 | [diff] [blame] | 401 | shift |
| 402 | done |
Theodore Ts'o | c4b4a5a | 2007-03-06 00:05:16 -0500 | [diff] [blame] | 403 | fi |
Charles Bailey | b0169d8 | 2008-12-12 21:48:40 +0000 | [diff] [blame] | 404 | |
| 405 | exit $rollup_status |