diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index e846c2ed7f..3622d66488 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -79,6 +79,13 @@ success of the resolution after the custom tool has exited. Prompt before each invocation of the merge resolution program to give the user a chance to skip the path. +-O:: + Process files in the order specified in the + , which has one shell glob pattern per line. + This overrides the `diff.orderFile` configuration variable + (see linkgit:git-config[1]). To cancel `diff.orderFile`, + use `-O/dev/null`. + TEMPORARY FILES --------------- `git mergetool` creates `*.orig` backup files while resolving merges. diff --git a/git-mergetool.sh b/git-mergetool.sh index bf862705d8..e52b4e4f24 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -3,12 +3,13 @@ # This program resolves merge conflicts in git # # Copyright (c) 2006 Theodore Y. Ts'o +# Copyright (c) 2009-2016 David Aguilar # # This file is licensed under the GPL v2, or a later version # at the discretion of Junio C Hamano. # -USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [file to merge] ...' +USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [-O] [file to merge] ...' SUBDIRECTORY_OK=Yes NONGIT_OK=Yes OPTIONS_SPEC= @@ -365,51 +366,6 @@ merge_file () { return 0 } -prompt=$(git config --bool mergetool.prompt) -guessed_merge_tool=false - -while test $# != 0 -do - case "$1" in - --tool-help=*) - TOOL_MODE=${1#--tool-help=} - show_tool_help - ;; - --tool-help) - show_tool_help - ;; - -t|--tool*) - case "$#,$1" in - *,*=*) - merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') - ;; - 1,*) - usage ;; - *) - merge_tool="$2" - shift ;; - esac - ;; - -y|--no-prompt) - prompt=false - ;; - --prompt) - prompt=true - ;; - --) - shift - break - ;; - -*) - usage - ;; - *) - break - ;; - esac - shift -done - prompt_after_failed_merge () { while true do @@ -426,57 +382,113 @@ prompt_after_failed_merge () { done } -git_dir_init -require_work_tree - -if test -z "$merge_tool" -then - # Check if a merge tool has been configured - merge_tool=$(get_configured_merge_tool) - # Try to guess an appropriate merge tool if no tool has been set. - if test -z "$merge_tool" - then - merge_tool=$(guess_merge_tool) || exit - guessed_merge_tool=true - fi -fi -merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" -merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" - -files= - -if test $# -eq 0 -then - cd_to_toplevel - - if test -e "$GIT_DIR/MERGE_RR" - then - files=$(git rerere remaining) - else - files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u) - fi -else - files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u) -fi - -if test -z "$files" -then +print_noop_and_exit () { echo "No files need merging" exit 0 -fi +} -printf "Merging:\n" -printf "%s\n" "$files" +main () { + prompt=$(git config --bool mergetool.prompt) + guessed_merge_tool=false + orderfile= -rc=0 -for i in $files -do - printf "\n" - if ! merge_file "$i" + while test $# != 0 + do + case "$1" in + --tool-help=*) + TOOL_MODE=${1#--tool-help=} + show_tool_help + ;; + --tool-help) + show_tool_help + ;; + -t|--tool*) + case "$#,$1" in + *,*=*) + merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') + ;; + 1,*) + usage ;; + *) + merge_tool="$2" + shift ;; + esac + ;; + -y|--no-prompt) + prompt=false + ;; + --prompt) + prompt=true + ;; + -O*) + orderfile="$1" + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift + done + + git_dir_init + require_work_tree + + if test -z "$merge_tool" then - rc=1 - prompt_after_failed_merge || exit 1 + # Check if a merge tool has been configured + merge_tool=$(get_configured_merge_tool) + # Try to guess an appropriate merge tool if no tool has been set. + if test -z "$merge_tool" + then + merge_tool=$(guess_merge_tool) || exit + guessed_merge_tool=true + fi fi -done + merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" + merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" -exit $rc + if test $# -eq 0 && test -e "$GIT_DIR/MERGE_RR" + then + set -- $(git rerere remaining) + if test $# -eq 0 + then + print_noop_and_exit + fi + fi + + files=$(git -c core.quotePath=false \ + diff --name-only --diff-filter=U \ + ${orderfile:+"$orderfile"} -- "$@") + + cd_to_toplevel + + if test -z "$files" + then + print_noop_and_exit + fi + + printf "Merging:\n" + printf "%s\n" "$files" + + rc=0 + for i in $files + do + printf "\n" + if ! merge_file "$i" + then + rc=1 + prompt_after_failed_merge || exit 1 + fi + done + + exit $rc +} + +main "$@" diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 7217f3968d..6d9f21511f 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -606,4 +606,64 @@ test_expect_success MKTEMP 'temporary filenames are used with mergetool.writeToT git reset --hard master >/dev/null 2>&1 ' +test_expect_success 'diff.orderFile configuration is honored' ' + test_config diff.orderFile order-file && + test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" && + test_config mergetool.myecho.trustExitCode true && + echo b >order-file && + echo a >>order-file && + git checkout -b order-file-start master && + echo start >a && + echo start >b && + git add a b && + git commit -m start && + git checkout -b order-file-side1 order-file-start && + echo side1 >a && + echo side1 >b && + git add a b && + git commit -m side1 && + git checkout -b order-file-side2 order-file-start && + echo side2 >a && + echo side2 >b && + git add a b && + git commit -m side2 && + test_must_fail git merge order-file-side1 && + cat >expect <<-\EOF && + Merging: + b + a + EOF + git mergetool --no-prompt --tool myecho >output && + git grep --no-index -h -A2 Merging: output >actual && + test_cmp expect actual && + git reset --hard >/dev/null +' +test_expect_success 'mergetool -Oorder-file is honored' ' + test_config diff.orderFile order-file && + test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" && + test_config mergetool.myecho.trustExitCode true && + test_must_fail git merge order-file-side1 && + cat >expect <<-\EOF && + Merging: + a + b + EOF + git mergetool -O/dev/null --no-prompt --tool myecho >output && + git grep --no-index -h -A2 Merging: output >actual && + test_cmp expect actual && + git reset --hard >/dev/null 2>&1 && + + git config --unset diff.orderFile && + test_must_fail git merge order-file-side1 && + cat >expect <<-\EOF && + Merging: + b + a + EOF + git mergetool -Oorder-file --no-prompt --tool myecho >output && + git grep --no-index -h -A2 Merging: output >actual && + test_cmp expect actual && + git reset --hard >/dev/null 2>&1 +' + test_done