1 # git-mergetool--lib is a library for common merge tool functions
3 test "$TOOL_MODE" = diff
7 test "$TOOL_MODE" = merge
10 translate_merge_tool_path () {
28 if test "$MERGED" -nt "$BACKUP"; then
32 echo "$MERGED seems unchanged."
33 printf "Was the merge successful? [y/n] "
34 read answer < /dev/tty
36 y*|Y*) status=0; break ;;
37 n*|N*) status=1; break ;;
45 kdiff3 | tkdiff | xxdiff | meld | opendiff | \
46 emerge | vimdiff | gvimdiff | ecmerge | diffuse)
59 if test -z "$(get_merge_tool_cmd "$1")"; then
66 get_merge_tool_cmd () {
67 # Prints the custom command for a merge tool
71 merge_tool="$(get_merge_tool)"
74 echo "$(git config difftool.$merge_tool.cmd ||
75 git config mergetool.$merge_tool.cmd)"
77 echo "$(git config mergetool.$merge_tool.cmd)"
82 merge_tool_path="$(get_merge_tool_path "$1")" || exit
89 if $base_present; then
90 ("$merge_tool_path" --auto \
91 --L1 "$MERGED (Base)" \
92 --L2 "$MERGED (Local)" \
93 --L3 "$MERGED (Remote)" \
95 "$BASE" "$LOCAL" "$REMOTE" \
98 ("$merge_tool_path" --auto \
99 --L1 "$MERGED (Local)" \
100 --L2 "$MERGED (Remote)" \
107 ("$merge_tool_path" --auto \
109 --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \
114 "$merge_tool_path" "$LOCAL" "$REMOTE"
118 if $base_present; then
119 "$merge_tool_path" -a "$BASE" \
120 -o "$MERGED" "$LOCAL" "$REMOTE"
123 -o "$MERGED" "$LOCAL" "$REMOTE"
127 "$merge_tool_path" "$LOCAL" "$REMOTE"
133 "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
136 "$merge_tool_path" "$LOCAL" "$REMOTE"
142 if $base_present; then
144 "$LOCAL" "$MERGED" "$REMOTE" \
148 "$LOCAL" "$MERGED" "$REMOTE" | cat
152 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
158 "$merge_tool_path" -d -c "wincmd l" \
159 "$LOCAL" "$MERGED" "$REMOTE"
162 "$merge_tool_path" -d -c "wincmd l" \
169 "$merge_tool_path" -d -c "wincmd l" -f \
170 "$LOCAL" "$MERGED" "$REMOTE"
173 "$merge_tool_path" -d -c "wincmd l" -f \
180 if $base_present; then
181 "$merge_tool_path" -X --show-merged-pane \
182 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
183 -R 'Accel.Search: "Ctrl+F"' \
184 -R 'Accel.SearchForward: "Ctrl-G"' \
185 --merged-file "$MERGED" \
186 "$LOCAL" "$BASE" "$REMOTE"
188 "$merge_tool_path" -X $extra \
189 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
190 -R 'Accel.Search: "Ctrl+F"' \
191 -R 'Accel.SearchForward: "Ctrl-G"' \
192 --merged-file "$MERGED" \
198 -R 'Accel.Search: "Ctrl+F"' \
199 -R 'Accel.SearchForward: "Ctrl-G"' \
206 if $base_present; then
207 "$merge_tool_path" "$LOCAL" "$REMOTE" \
209 -merge "$MERGED" | cat
211 "$merge_tool_path" "$LOCAL" "$REMOTE" \
212 -merge "$MERGED" | cat
216 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
222 if $base_present; then
223 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
224 --default --mode=merge3 --to="$MERGED"
226 "$merge_tool_path" "$LOCAL" "$REMOTE" \
227 --default --mode=merge2 --to="$MERGED"
231 "$merge_tool_path" --default --mode=diff2 \
237 if $base_present; then
239 -f emerge-files-with-ancestor-command \
240 "$LOCAL" "$REMOTE" "$BASE" \
241 "$(basename "$MERGED")"
244 -f emerge-files-command \
246 "$(basename "$MERGED")"
250 "$merge_tool_path" -f emerge-files-command \
255 if $base_present; then
258 -base:"$BASE" -mine:"$LOCAL" \
259 -theirs:"$REMOTE" -merged:"$MERGED"
262 echo "TortoiseMerge cannot be used without a base" 1>&2
267 merge_tool_cmd="$(get_merge_tool_cmd "$1")"
268 if test -z "$merge_tool_cmd"; then
275 trust_exit_code="$(git config --bool \
276 mergetool."$1".trustExitCode || echo false)"
277 if test "$trust_exit_code" = "false"; then
279 ( eval $merge_tool_cmd )
282 ( eval $merge_tool_cmd )
286 ( eval $merge_tool_cmd )
293 guess_merge_tool () {
295 tools="tortoisemerge"
299 if test -n "$DISPLAY"; then
300 if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
301 tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
303 tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
305 tools="$tools gvimdiff diffuse ecmerge"
307 if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then
308 # $EDITOR is emacs so add emerge as a candidate
309 tools="$tools emerge vimdiff"
310 elif echo "${VISUAL:-$EDITOR}" | grep vim > /dev/null 2>&1; then
311 # $EDITOR is vim so add vimdiff as a candidate
312 tools="$tools vimdiff emerge"
314 tools="$tools emerge vimdiff"
316 echo >&2 "merge tool candidates: $tools"
318 # Loop over each candidate and stop when a valid merge tool is found.
321 merge_tool_path="$(translate_merge_tool_path "$i")"
322 if type "$merge_tool_path" > /dev/null 2>&1; then
328 echo >&2 "No known merge resolution program available."
332 get_configured_merge_tool () {
333 # Diff mode first tries diff.tool and falls back to merge.tool.
334 # Merge mode only checks merge.tool
336 merge_tool=$(git config diff.tool || git config merge.tool)
338 merge_tool=$(git config merge.tool)
340 if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
341 echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
342 echo >&2 "Resetting to default..."
348 get_merge_tool_path () {
349 # A merge tool has been set, so verify that it's valid.
350 if test -n "$1"; then
353 merge_tool="$(get_merge_tool)"
355 if ! valid_tool "$merge_tool"; then
356 echo >&2 "Unknown merge tool $merge_tool"
360 merge_tool_path=$(git config difftool."$merge_tool".path ||
361 git config mergetool."$merge_tool".path)
363 merge_tool_path=$(git config mergetool."$merge_tool".path)
365 if test -z "$merge_tool_path"; then
366 merge_tool_path="$(translate_merge_tool_path "$merge_tool")"
368 if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
369 ! type "$merge_tool_path" > /dev/null 2>&1; then
370 echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
374 echo "$merge_tool_path"
378 # Check if a merge tool has been configured
379 merge_tool=$(get_configured_merge_tool)
380 # Try to guess an appropriate merge tool if no tool has been set.
381 if test -z "$merge_tool"; then
382 merge_tool="$(guess_merge_tool)" || exit