2 # git-mergetool--lib is a library for common merge tool functions
4 test "$TOOL_MODE" = diff
8 test "$TOOL_MODE" = merge
11 translate_merge_tool_path () {
32 if test "$MERGED" -nt "$BACKUP"; then
36 echo "$MERGED seems unchanged."
37 printf "Was the merge successful? [y/n] "
38 read answer < /dev/tty
40 y*|Y*) status=0; break ;;
41 n*|N*) status=1; break ;;
49 kdiff3 | tkdiff | xxdiff | meld | opendiff | \
50 emerge | vimdiff | gvimdiff | ecmerge | diffuse | araxis | p4merge)
63 if test -z "$(get_merge_tool_cmd "$1")"; then
70 get_merge_tool_cmd () {
71 # Prints the custom command for a merge tool
75 merge_tool="$(get_merge_tool)"
78 echo "$(git config difftool.$merge_tool.cmd ||
79 git config mergetool.$merge_tool.cmd)"
81 echo "$(git config mergetool.$merge_tool.cmd)"
86 merge_tool_path="$(get_merge_tool_path "$1")" || exit
93 if $base_present; then
94 ("$merge_tool_path" --auto \
95 --L1 "$MERGED (Base)" \
96 --L2 "$MERGED (Local)" \
97 --L3 "$MERGED (Remote)" \
99 "$BASE" "$LOCAL" "$REMOTE" \
102 ("$merge_tool_path" --auto \
103 --L1 "$MERGED (Local)" \
104 --L2 "$MERGED (Remote)" \
111 ("$merge_tool_path" --auto \
113 --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \
118 "$merge_tool_path" "$LOCAL" "$REMOTE"
122 if $base_present; then
123 "$merge_tool_path" -a "$BASE" \
124 -o "$MERGED" "$LOCAL" "$REMOTE"
127 -o "$MERGED" "$LOCAL" "$REMOTE"
131 "$merge_tool_path" "$LOCAL" "$REMOTE"
137 if $base_present; then
138 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
140 "$merge_tool_path" "$LOCAL" "$LOCAL" "$REMOTE" "$MERGED"
144 "$merge_tool_path" "$LOCAL" "$REMOTE"
150 "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
153 "$merge_tool_path" "$LOCAL" "$REMOTE"
159 if $base_present; then
161 "$LOCAL" "$MERGED" "$REMOTE" \
165 "$LOCAL" "$MERGED" "$REMOTE" | cat
169 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
175 "$merge_tool_path" -d -c "wincmd l" \
176 "$LOCAL" "$MERGED" "$REMOTE"
179 "$merge_tool_path" -d -c "wincmd l" \
186 "$merge_tool_path" -d -c "wincmd l" -f \
187 "$LOCAL" "$MERGED" "$REMOTE"
190 "$merge_tool_path" -d -c "wincmd l" -f \
197 if $base_present; then
198 "$merge_tool_path" -X --show-merged-pane \
199 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
200 -R 'Accel.Search: "Ctrl+F"' \
201 -R 'Accel.SearchForward: "Ctrl-G"' \
202 --merged-file "$MERGED" \
203 "$LOCAL" "$BASE" "$REMOTE"
205 "$merge_tool_path" -X $extra \
206 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
207 -R 'Accel.Search: "Ctrl+F"' \
208 -R 'Accel.SearchForward: "Ctrl-G"' \
209 --merged-file "$MERGED" \
215 -R 'Accel.Search: "Ctrl+F"' \
216 -R 'Accel.SearchForward: "Ctrl-G"' \
223 if $base_present; then
224 "$merge_tool_path" "$LOCAL" "$REMOTE" \
226 -merge "$MERGED" | cat
228 "$merge_tool_path" "$LOCAL" "$REMOTE" \
229 -merge "$MERGED" | cat
233 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
239 if $base_present; then
240 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
241 --default --mode=merge3 --to="$MERGED"
243 "$merge_tool_path" "$LOCAL" "$REMOTE" \
244 --default --mode=merge2 --to="$MERGED"
248 "$merge_tool_path" --default --mode=diff2 \
254 if $base_present; then
256 -f emerge-files-with-ancestor-command \
257 "$LOCAL" "$REMOTE" "$BASE" \
258 "$(basename "$MERGED")"
261 -f emerge-files-command \
263 "$(basename "$MERGED")"
267 "$merge_tool_path" -f emerge-files-command \
272 if $base_present; then
275 -base:"$BASE" -mine:"$LOCAL" \
276 -theirs:"$REMOTE" -merged:"$MERGED"
279 echo "TortoiseMerge cannot be used without a base" 1>&2
286 if $base_present; then
287 "$merge_tool_path" -wait -merge -3 -a1 \
288 "$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
291 "$merge_tool_path" -wait -2 \
292 "$LOCAL" "$REMOTE" "$MERGED" \
297 "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
302 merge_tool_cmd="$(get_merge_tool_cmd "$1")"
303 if test -z "$merge_tool_cmd"; then
310 trust_exit_code="$(git config --bool \
311 mergetool."$1".trustExitCode || echo false)"
312 if test "$trust_exit_code" = "false"; then
314 ( eval $merge_tool_cmd )
317 ( eval $merge_tool_cmd )
321 ( eval $merge_tool_cmd )
328 guess_merge_tool () {
330 tools="tortoisemerge"
334 if test -n "$DISPLAY"; then
335 if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
336 tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
338 tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
340 tools="$tools gvimdiff diffuse ecmerge p4merge araxis"
342 case "${VISUAL:-$EDITOR}" in
344 tools="$tools vimdiff emerge"
347 tools="$tools emerge vimdiff"
350 echo >&2 "merge tool candidates: $tools"
352 # Loop over each candidate and stop when a valid merge tool is found.
355 merge_tool_path="$(translate_merge_tool_path "$i")"
356 if type "$merge_tool_path" > /dev/null 2>&1; then
362 echo >&2 "No known merge resolution program available."
366 get_configured_merge_tool () {
367 # Diff mode first tries diff.tool and falls back to merge.tool.
368 # Merge mode only checks merge.tool
370 merge_tool=$(git config diff.tool || git config merge.tool)
372 merge_tool=$(git config merge.tool)
374 if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
375 echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
376 echo >&2 "Resetting to default..."
382 get_merge_tool_path () {
383 # A merge tool has been set, so verify that it's valid.
384 if test -n "$1"; then
387 merge_tool="$(get_merge_tool)"
389 if ! valid_tool "$merge_tool"; then
390 echo >&2 "Unknown merge tool $merge_tool"
394 merge_tool_path=$(git config difftool."$merge_tool".path ||
395 git config mergetool."$merge_tool".path)
397 merge_tool_path=$(git config mergetool."$merge_tool".path)
399 if test -z "$merge_tool_path"; then
400 merge_tool_path="$(translate_merge_tool_path "$merge_tool")"
402 if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
403 ! type "$merge_tool_path" > /dev/null 2>&1; then
404 echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
408 echo "$merge_tool_path"
412 # Check if a merge tool has been configured
413 merge_tool=$(get_configured_merge_tool)
414 # Try to guess an appropriate merge tool if no tool has been set.
415 if test -z "$merge_tool"; then
416 merge_tool="$(guess_merge_tool)" || exit