Как установить kdiff3 в качестве инструмента слияния для SVN - PullRequest
27 голосов
/ 26 января 2011

Я хотел бы иметь возможность разрешать конфликты с помощью kdiff3, когда SVN уведомляет меня о конфликте.Как я могу установить его как инструмент по умолчанию для этого?

Ответы [ 4 ]

31 голосов
/ 26 января 2011

Перейдите в файл конфигурации Subversion (/etc/subversion/config или ~/.subversion/config) и установите переменную merge-tool-cmd с вашим любимым инструментом:

### Set merge-tool-cmd to the command used to invoke your external
### merging tool of choice. Subversion will pass 4 arguments to
### the specified command: base theirs mine merged
# merge-tool-cmd = merge_command

Хотя существует проблема с kdiff3, которая не поддерживаетчетыре простых аргумента (SVN передает четыре простых аргумента в kdiff3, и он не работает), поэтому он обычно вызывается с помощью простого скрипта для перевода аргументов, например, «kdiff3caller»:

#!/bin/sh
kdiff3 "$1" "$2" "$3" -o "$4"

This kdiff3проблема и решение объяснено здесь .

4 голосов
/ 27 мая 2014

Решение, которое короче и работает с более поздними версиями SVN (протестировано на SVN 1.7.7):

Создать скрипт ~ / svn-merge-kdiff

#!/bin/bash

# Useful when something fails
LOG=~/svn-merge-kdiff-last-run.log
echo "arguments passed to $0: $@" > $LOG

# Now, don't think you will get the $1, $2, etc... by referencing.
# At first, you have to copy it to an array
for i in $@; do
    args=( ${args[@]} $i )
done

echo "parsed args" >> $LOG
for i in ${args[@]}; do
    echo $i >> $LOG
done

# I keep it in case something changes
if [ "${args[1]}" == "-m" ] && [ "${args[2]}" == "-L" ] && [ "${args[3]}" == ".mine" ];then
    command="kdiff3 --L1 ${args[5]} --base ${args[9]} --L2 ${args[7]} ${args[10]} --L3 ${args[3]} ${args[8]} -o merged"
    $command
    if [[ $? -ne 0 ]]; then
        echo "$command failed" >> $LOG
        exit 1
    fi

    # You have to do this, otherwise after the merge you will see... empty file(?)
    cat merged

    rm merged
    exit 0
fi

exit -1

Свяжите его с SVN в ~ / .subversion / config

diff3-cmd = ~/svn-merge-kdiff
3 голосов
/ 02 декабря 2011

Сценарий из ответа yvoyer отлично работает для меня, и я использую SVN 1.4. Я думаю, что предыдущий ответ от Jon Ander Ortiz Durántez работает для SVN 1.5 и выше, и этот скрипт работает для версий SVN до 1.5. Похоже, что были изменения в --diff-cmd & --diff3-cmd для версии 1.5. Сравните сценарии в следующих двух документах SVN, чтобы увидеть некоторые различия:

Сценарий Майкла Брэдли действительно полезен, так как теперь, если я получаю конфликт во время svn update, он вставляет kdiff3 вместо того, чтобы разбирать весь файл с помощью маркеров конфликта ">>>>>>>>", которые так сложно решить, если у вас есть сложные конфликты. Diff3-cmd работает как для слияния, так и для обновления.

Я добавляю diff3-cmd = /usr/local/bin/svndiff3 к ~/.subversion/config (или использую --diff3-cmd в командной строке), так как я написал свой собственный скрипт для отправки svn diff в sdiff и указан --diff-cmd.

Этот скрипт размещен на yolinux , а слегка измененная версия (которая обрабатывает автоматическое объединение) размещена здесь Jawspeak .

3 голосов
/ 27 января 2011

Я нашел этот скрипт где-то, что не помню.но автор - Майкл Брэдли.

Мой ответ похож на ответы Джона Андера Ортиса Дурантеза.Так что, если его ответ не работает, у вас есть резервная копия.Однажды я попробовал что-то вроде того, что он предложил, но он всегда выводил какую-то ошибку с параметрами, пока не нашел этот сценарий, который разрешил все.

Создайте файл сценария и установите diff-cmd = /path/to/script.sh в вашем ~/.subversion/config

#!/bin/bash

# Return an errorcode of 0 on successful merge, 1 if unresolved conflicts
# remain in the result.  Any other errorcode will be treated as fatal.
# Author: Michael Bradley

#NOTE: all output must be redirected to stderr with "1>&2" as all stdout output is written to the output file

# Must be called by subversion in "~/.subversion/config" file
# Add config : "diff-cmd = /path/to/script/myKdiff3.sh" 

VDIFF3="kdiff3"
DIFF3="diff3" 
DIFF="kdiff3"  

promptUser ()
{
    read answer
    case "${answer}" in

        "M"         ) 
        echo "" 1>&2
        echo "Attempting to merge ${baseFileName} with ${DIFF}" 1>&2
        $VDIFF3 $older $mine $theirs --L1 $labelOlder --L2 $labelMine --L3 $labelTheirs -o $output 1>&2
        bLoop=1
        if [ -f $output ]; then
            if [ -s $output ]; then
                #output succesfully written
                bLoop=0
            fi
        fi
        if [ $bLoop = 0 ]; then
            cat $output
            rm -f $output
            exit 0
        else
            echo "Merge failed, try again" 1>&2
        fi

        ;;

        "m"         ) 
        echo "" 1>&2
        echo "Attempting to auto-merge ${baseFileName}" 1>&2
        diff3 -L $labelMine -L $labelOlder -L $labelTheirs -Em $mine $older $theirs > $output
        if [ $? = 1 ]; then
            #Can't auto merge
            rm -f $output
            $VDIFF3 $older $mine $theirs --L1 $labelOlder --L2 $labelMine --L3 $labelTheirs -o $output --auto 1>&2
            bLoop=1
            if [ -f $output ]; then
                if [ -s $output ]; then
                    #output succesfully written
                    bLoop=0
                fi
            fi
            if [ $bLoop = 0 ]; then
                cat $output
                rm -f $output
                exit 0
            else
                echo "Merge failed, try again" 1>&2
            fi
        else
            #We can automerge, and we already did it
            cat $output
            rm -f $output
            exit 0
        fi
        ;;

        "diff3" | "Diff3" | "DIFF3"  )
        echo "" 1>&2
        echo "Diffing..." 1>&2
        $VDIFF3 $older $mine $theirs --L1 $labelOlder --L2 $labelMine --L3 $labelTheirs 1>&2
        ;;

        "diff" | "Diff" | "DIFF"  )
        echo "" 1>&2
        echo "Diffing..." 1>&2
        $DIFF $mine $theirs -L $labelMine -L $labelTheirs 1>&2
        ;;

        "A" | "a"   ) 
        echo "" 1>&2
        echo "Accepting remote version of file..." 1>&2
        cat ${theirs}
        exit 0
        ;;

        "I" | "i"   ) 
        echo "" 1>&2
        echo "Keeping local modifications..." 1>&2
        cat ${mine}
        exit 0
        ;;

        "R" | "r"   ) 
        echo "" 1>&2
        echo "Reverting to base..." 1>&2
        cat ${older}
        exit 0
        ;;

        "D" | "d"   ) 
        echo "" 1>&2
        echo "Runnig diff3..." 1>&2
        diff3 -L $labelMine -L $labelOlder -L $labelTheirs -Em $mine $older $theirs
        #Exit with return vaule of the diff3 (to write out files if necessary)
        exit $?
        ;;

        "S" | "s"   ) 
        echo "" 1>&2
        echo "Saving for later..." 1>&2
        cat ${mine}
        #Exit with return vaule of 1 to force writting of files
        exit 1
        ;;

        "Fail" | "fail" | "FAIL"   ) 
        echo "" 1>&2
        echo "Failing..." 1>&2 
        exit 2
        ;;

        "H" | "h"   ) 
        echo "" 1>&2
        echo "USAGE OPTIONS:" 1>&2 
        echo "  [A]ccept    Accept $labelTheirs and throw out local modifications" 1>&2
        echo "  [D]efault   Use diff3 to merge files (same behavior as vanilla SVN)" 1>&2
        echo "  [Fail]      Kills the command (not suggested)" 1>&2
        echo "  [H]elp      Print this message" 1>&2
        echo "  [I]gnore    Keep your locally modified version as is" 1>&2
        echo "  [M]erge     Manually merge using ${VDIFF3}" 1>&2
        echo "  [m]erge     Same as "M" but attempts to automerge if possible" 1>&2
        echo "  [R]evert    Revert to base version (${labelOlder})" 1>&2
        echo "  [S]ave      Same as 'I' but writes out rold, rnew, and rmine files to deal with later" 1>&2
        echo "  [diff]      Type 'diff' to diff versions $labelMine and $labelTheirsthe before making a descision" 1>&2
        echo "  [diff3]     Type 'diff3' to diff all three versions before making a descision" 1>&2
        echo "" 1>&2
        ;;

        *   ) 
        echo "'${answer}' is not an option, try again." 1>&2
        ;;
    esac 
}

if [ -z $2 ]
then
    echo ERROR: This script expects to be called by subversion
    exit 1
fi

if [ $2 = "-m" ]
then
    #Setup vars
    labelMine=${4}
    labelOlder=${6}
    labelTheirs=${8}
    mine=${9}
    older=${10}
    theirs=${11}
    output=${9}.svnDiff3TempOutput
    baseFileName=`echo $mine | sed -e "s/.tmp$//"`

    #Prompt user for direction
    while [ 1 ]
    do
        echo "" 1>&2
        echo "${baseFileName} requires merging." 1>&2 
        echo "" 1>&2
        echo "What would you like to do?" 1>&2
        echo "[M]erge [A]ccept [I]gnore [R]evert [D]efault [H]elp" 1>&2 
        promptUser
    done
else
    L="-L"         #Argument option for left label
    R="-L"         #Argument option for right label
    label1=$3       #Left label
    label2=$5       #Right label
    file1=$6        #Left file
    file2=$7        #Right file

    $DIFF $file1 $file2 $L "$label1" $L "$label2" &
    #$DIFF $file1 $file2 &
    #wait for the command to finish
    wait
fi
exit 0
...