Merge branch 'master' of git://repo.or.cz/git/mergetool.git

* 'master' of git://repo.or.cz/git/mergetool.git:
  mergetool: Clean up description of files and prompts for merge resolutions
  mergetool: Make git-rm quiet when resolving a deleted file conflict
  mergetool: Add support for Apple Mac OS X's opendiff command
  mergetool: Fix abort command when resolving symlinks and deleted files
  mergetool: Remove spurious error message if merge.tool config option not set
  mergetool: factor out common code
  mergetool: portability fix: don't use reserved word function
  mergetool: portability fix: don't assume true is in /bin
  mergetool: Don't error out in the merge case where the local file is deleted
  mergetool: Replace use of "echo -n" with printf(1) to be more portable
  Fix minor formatting issue in man page for git-mergetool
maint
Junio C Hamano 2007-03-29 23:08:45 -07:00
commit 18acb3e6c7
2 changed files with 87 additions and 81 deletions

View File

@ -26,11 +26,11 @@ OPTIONS
Use the merge resolution program specified by <tool>. Use the merge resolution program specified by <tool>.
Valid merge tools are: Valid merge tools are:
kdiff3, tkdiff, meld, xxdiff, emerge, and vimdiff. kdiff3, tkdiff, meld, xxdiff, emerge, and vimdiff.

+
If a merge resolution program is not specified, 'git mergetool' If a merge resolution program is not specified, 'git mergetool'
will use the configuration variable merge.tool. If the will use the configuration variable merge.tool. If the
configuration variable merge.tool is not set, 'git mergetool' configuration variable merge.tool is not set, 'git mergetool'
will pick a suitable default. will pick a suitable default.


Author Author
------ ------

View File

@ -14,19 +14,19 @@ SUBDIRECTORY_OK=Yes
require_work_tree require_work_tree


# Returns true if the mode reflects a symlink # Returns true if the mode reflects a symlink
function is_symlink () { is_symlink () {
test "$1" = 120000 test "$1" = 120000
} }


function local_present () { local_present () {
test -n "$local_mode" test -n "$local_mode"
} }


function remote_present () { remote_present () {
test -n "$remote_mode" test -n "$remote_mode"
} }


function base_present () { base_present () {
test -n "$base_mode" test -n "$base_mode"
} }


@ -39,32 +39,29 @@ cleanup_temp_files () {
fi fi
} }


function describe_file () { describe_file () {
mode="$1" mode="$1"
branch="$2" branch="$2"
file="$3" file="$3"


echo -n " " printf " {%s}: " "$branch"
if test -z "$mode"; then if test -z "$mode"; then
echo -n "'$path' was deleted" echo "deleted"
elif is_symlink "$mode" ; then elif is_symlink "$mode" ; then
echo -n "'$path' is a symlink containing '" echo "a symbolic link -> '$(cat "$file")'"
cat "$file"
echo -n "'"
else else
if base_present; then if base_present; then
echo -n "'$path' was created" echo "modified"
else else
echo -n "'$path' was modified" echo "created"
fi fi
fi fi
echo " in the $branch branch"
} }




resolve_symlink_merge () { resolve_symlink_merge () {
while /bin/true; do while true; do
echo -n "Use (r)emote or (l)ocal, or (a)bort? " printf "Use (l)ocal or (r)emote, or (a)bort? "
read ans read ans
case "$ans" in case "$ans" in
[lL]*) [lL]*)
@ -79,7 +76,7 @@ resolve_symlink_merge () {
cleanup_temp_files --save-backup cleanup_temp_files --save-backup
return return
;; ;;
[qQ]*) [aA]*)
exit 1 exit 1
;; ;;
esac esac
@ -87,38 +84,69 @@ resolve_symlink_merge () {
} }


resolve_deleted_merge () { resolve_deleted_merge () {
while /bin/true; do while true; do
echo -n "Use (m)odified or (d)eleted file, or (a)bort? " if base_present; then
printf "Use (m)odified or (d)eleted file, or (a)bort? "
else
printf "Use (c)reated or (d)eleted file, or (a)bort? "
fi
read ans read ans
case "$ans" in case "$ans" in
[mM]*) [mMcC]*)
git-add -- "$path" git-add -- "$path"
cleanup_temp_files --save-backup cleanup_temp_files --save-backup
return return
;; ;;
[dD]*) [dD]*)
git-rm -- "$path" git-rm -- "$path" > /dev/null
cleanup_temp_files cleanup_temp_files
return return
;; ;;
[qQ]*) [aA]*)
exit 1 exit 1
;; ;;
esac esac
done done
} }


check_unchanged () {
if test "$path" -nt "$BACKUP" ; then
status=0;
else
while true; do
echo "$path seems unchanged."
printf "Was the merge successful? [y/n] "
read answer < /dev/tty
case "$answer" in
y*|Y*) status=0; break ;;
n*|N*) status=1; break ;;
esac
done
fi
}

save_backup () {
if test "$status" -eq 0; then
mv -- "$BACKUP" "$path.orig"
fi
}

remove_backup () {
if test "$status" -eq 0; then
rm "$BACKUP"
fi
}

merge_file () { merge_file () {
path="$1" path="$1"


if test ! -f "$path" ; then
echo "$path: file not found"
exit 1
fi

f=`git-ls-files -u -- "$path"` f=`git-ls-files -u -- "$path"`
if test -z "$f" ; then if test -z "$f" ; then
if test ! -f "$path" ; then
echo "$path: file not found"
else
echo "$path: file does not need merging" echo "$path: file does not need merging"
fi
exit 1 exit 1
fi fi


@ -139,7 +167,7 @@ merge_file () {
remote_present && git cat-file blob ":3:$path" > "$REMOTE" 2>/dev/null remote_present && git cat-file blob ":3:$path" > "$REMOTE" 2>/dev/null


if test -z "$local_mode" -o -z "$remote_mode"; then if test -z "$local_mode" -o -z "$remote_mode"; then
echo "Deleted merge conflict for $path:" echo "Deleted merge conflict for '$path':"
describe_file "$local_mode" "local" "$LOCAL" describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE" describe_file "$remote_mode" "remote" "$REMOTE"
resolve_deleted_merge resolve_deleted_merge
@ -147,17 +175,17 @@ merge_file () {
fi fi


if is_symlink "$local_mode" || is_symlink "$remote_mode"; then if is_symlink "$local_mode" || is_symlink "$remote_mode"; then
echo "Symlink merge conflict for $path:" echo "Symbolic link merge conflict for '$path':"
describe_file "$local_mode" "local" "$LOCAL" describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE" describe_file "$remote_mode" "remote" "$REMOTE"
resolve_symlink_merge resolve_symlink_merge
return return
fi fi


echo "Normal merge conflict for $path:" echo "Normal merge conflict for '$path':"
describe_file "$local_mode" "local" "$LOCAL" describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE" describe_file "$remote_mode" "remote" "$REMOTE"
echo -n "Hit return to start merge resolution tool ($merge_tool): " printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
read ans read ans


case "$merge_tool" in case "$merge_tool" in
@ -170,9 +198,7 @@ merge_file () {
-o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1) -o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1)
fi fi
status=$? status=$?
if test "$status" -eq 0; then remove_backup
rm "$BACKUP"
fi
;; ;;
tkdiff) tkdiff)
if base_present ; then if base_present ; then
@ -181,29 +207,13 @@ merge_file () {
tkdiff -o "$path" -- "$LOCAL" "$REMOTE" tkdiff -o "$path" -- "$LOCAL" "$REMOTE"
fi fi
status=$? status=$?
if test "$status" -eq 0; then save_backup
mv -- "$BACKUP" "$path.orig"
fi
;; ;;
meld|vimdiff) meld|vimdiff)
touch "$BACKUP" touch "$BACKUP"
$merge_tool -- "$LOCAL" "$path" "$REMOTE" $merge_tool -- "$LOCAL" "$path" "$REMOTE"
if test "$path" -nt "$BACKUP" ; then check_unchanged
status=0; save_backup
else
while true; do
echo "$path seems unchanged."
echo -n "Was the merge successful? [y/n] "
read answer < /dev/tty
case "$answer" in
y*|Y*) status=0; break ;;
n*|N*) status=1; break ;;
esac
done
fi
if test "$status" -eq 0; then
mv -- "$BACKUP" "$path.orig"
fi
;; ;;
xxdiff) xxdiff)
touch "$BACKUP" touch "$BACKUP"
@ -220,22 +230,18 @@ merge_file () {
-R 'Accel.SearchForward: "Ctrl-G"' \ -R 'Accel.SearchForward: "Ctrl-G"' \
--merged-file "$path" -- "$LOCAL" "$REMOTE" --merged-file "$path" -- "$LOCAL" "$REMOTE"
fi fi
if test "$path" -nt "$BACKUP" ; then check_unchanged
status=0; save_backup
;;
opendiff)
touch "$BACKUP"
if base_present; then
opendiff "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$path" | cat
else else
while true; do opendiff "$LOCAL" "$REMOTE" -merge "$path" | cat
echo "$path seems unchanged."
echo -n "Was the merge successful? [y/n] "
read answer < /dev/tty
case "$answer" in
y*|Y*) status=0; break ;;
n*|N*) status=1; break ;;
esac
done
fi
if test "$status" -eq 0; then
mv -- "$BACKUP" "$path.orig"
fi fi
check_unchanged
save_backup
;; ;;
emerge) emerge)
if base_present ; then if base_present ; then
@ -244,9 +250,7 @@ merge_file () {
emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$path" emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$path"
fi fi
status=$? status=$?
if test "$status" -eq 0; then save_backup
mv -- "$BACKUP" "$path.orig"
fi
;; ;;
esac esac
if test "$status" -ne 0; then if test "$status" -ne 0; then
@ -289,7 +293,7 @@ done
if test -z "$merge_tool"; then if test -z "$merge_tool"; then
merge_tool=`git-config merge.tool` merge_tool=`git-config merge.tool`
case "$merge_tool" in case "$merge_tool" in
kdiff3 | tkdiff | xxdiff | meld | emerge | vimdiff) kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | "")
;; # happy ;; # happy
*) *)
echo >&2 "git config option merge.tool set to unknown tool: $merge_tool" echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
@ -308,6 +312,8 @@ if test -z "$merge_tool" ; then
merge_tool=xxdiff merge_tool=xxdiff
elif type meld >/dev/null 2>&1 && test -n "$DISPLAY"; then elif type meld >/dev/null 2>&1 && test -n "$DISPLAY"; then
merge_tool=meld merge_tool=meld
elif type opendiff >/dev/null 2>&1; then
merge_tool=opendiff
elif type emacs >/dev/null 2>&1; then elif type emacs >/dev/null 2>&1; then
merge_tool=emerge merge_tool=emerge
elif type vimdiff >/dev/null 2>&1; then elif type vimdiff >/dev/null 2>&1; then
@ -319,7 +325,7 @@ if test -z "$merge_tool" ; then
fi fi


case "$merge_tool" in case "$merge_tool" in
kdiff3|tkdiff|meld|xxdiff|vimdiff) kdiff3|tkdiff|meld|xxdiff|vimdiff|opendiff)
if ! type "$merge_tool" > /dev/null 2>&1; then if ! type "$merge_tool" > /dev/null 2>&1; then
echo "The merge tool $merge_tool is not available" echo "The merge tool $merge_tool is not available"
exit 1 exit 1
@ -346,12 +352,12 @@ if test $# -eq 0 ; then
echo Merging the files: $files echo Merging the files: $files
git ls-files -u | sed -e 's/^[^ ]* //' | sort -u | while read i git ls-files -u | sed -e 's/^[^ ]* //' | sort -u | while read i
do do
echo "" printf "\n"
merge_file "$i" < /dev/tty > /dev/tty merge_file "$i" < /dev/tty > /dev/tty
done done
else else
while test $# -gt 0; do while test $# -gt 0; do
echo "" printf "\n"
merge_file "$1" merge_file "$1"
shift shift
done done