svn diff 包括注释/类似指责信息,包括何时、谁进行了更改

svn diff 包括注释/类似指责信息,包括何时、谁进行了更改

您能否向 svn diff 添加注释/类似指责信息,以便每个更改的行都包括哪个用户和修订版本更改了该行?

例如,比较修订版本 8-10 的 annotate-diff 可能会输出类似以下内容:

9    user1   - some line that user1 deleted in revision 9
10   user2   + some line that user2 added in revision 10

上下文以及周围的未发生改变的线条可能会被包括在内,也可能会不包括,这并不重要。

这不仅仅是“快速”编写一个结合 svn diff 和 svn annotate 输出的 shell 脚本的问题。例如,annotate 永远不会显示谁删除了一行。这也不是对过去的修订进行注释的问题:我们不关心最初是谁添加了被删除的行(这不是“导致”差异的人),我们想知道是谁删除了它。我怀疑实现这一点的唯一方法是检查被比较的两个修订之间的每个提交(并以某种方式将单独差异中的所有更改映射到总差异中的行)...

是否存在可以做类似事情的工具?

答案1

我不完全确定我理解了你想要什么,但我用 TortoiseSVN 做到了这一点:

  1. 创建从修订版本 1 到修订版本 A 的追溯 - 保存为 A.txt
  2. 创建从修订版本 1 到修订版本 B 的追溯 - 保存为 B.txt
  3. 从两个文本文件中删除第一列(行)(我使用 Pspad 编辑器,它可以删除文本文件的一列)
  4. 合并 A.txt 和 B.txt (TortoiseMerge.exe /base:"a.txt" /mine:"b.txt" )

它显示了修订 A 和 B 之间的更改、添加和删除的行以及日期、用户和分支,我认为这就是您想要的。

答案2

SVN diff 只接受两个修订版本并即时生成输出。SVN annotate 只接受一个修订版本。您怀疑提议的实用程序需要迭代 N 个修订版本,这是正确的;SVN 将修订状态存储为整个对象。

您可能更愿意使用 git 和 git-svn 网关......

答案3

是否存在可以做类似事情的工具?

嗯,我想现在有的。

用法;blameDiff <path> [rev1] [rev2]

bash 函数

function blameDiff() {
    file="$1"
    rev1="$2"
    rev2="$3"

    #default to HEAD if omitted
    if [ -n "$rev1" ]
    then
        title1="(revision $rev1)"
    else
        title1="(working copy)"
        rev1='HEAD'
    fi
    if [ -n "$rev2" ]
    then
        title2="(revision $rev2)"
    else
        title2="(working copy)"
        rev2='HEAD'
    fi

    #check that the svn urls are the same
    tmp1="$(svn info -r $rev1 "$file" |\
        grep '^Relative URL' |\
        sed 's/Relative URL: //' \
    )"
    tmp2="$(svn info -r $rev2 "$file" |\
        grep '^Relative URL' |\
        sed 's/Relative URL: //' \
    )"
    if [ "$tmp1" != "$tmp2" ]
    then
        #if not, then one of these revisions is in another branch
        #lets have this in the output
        title1="($tmp1) $title1"
        title2="($tmp2) $title2"
    fi

#can just print this but you wont get deleted revision/blame
#    diff -u \
#        <(svn blame -r "$rev1" "$file") \
#        <(svn blame -r "$rev2" "$file") \
#    | sed "s|^--- .*$|--- $file $title1|" \
#    | sed "s|^+++ .*$|+++ $file $title2|"
#    return 0

    #an array of commitNumber|committer pairs for the file
    history=()
    #a map between elements in `history` and a list of line numbers changed.
    #each item in the list is a lineNumber|newLineNumber pair
    declare -A revisions

    #the sed match and replace expressions to pull data from the
    #diff-line-number&cat-line-number combo and give it to the cache
    grabData='^ *\([0-9]\+\)\t\([0-9]\+\)$'
    formatData='\2 \1'

    #for each revision between the ones given
    last=''
    while read -r line
    do
        #read in the revision number and submitter
        IFS=' |' read next by tmp <<<"$line"

        if [ -n "$last" ]
        then
            #save them
            history+=("$next $by")
            #associate and format the list
            revisions["${history[-1]}"]="$(\
                diff \
                    --unchanged-line-format="%dn%c'\012'" \
                    --new-line-format="?%c'\012'" \
                    --old-line-format='' \
                    <(svn cat -r "$last" "$file") \
                    <(svn cat -r "$next" "$file") \
                | cat -n \
                | grep -v '?$' \
                | sed "s/$grabData/$formatData/" \
            )"
        fi

        #remember the last revision looked at
        last="$next"
    done <<<"$(
        svn log -r "$rev1:$rev2" "$file" \
        | grep '^r[0-9]\+ | ' \
        | sed 's/^r//' \
    )"

    #pull the full diff
    diff \
        --new-line-format='+%L' \
        --old-line-format='-%L' \
        --unchanged-line-format='=%L' \
        <(svn blame -r "$rev1" "$file") \
        <(svn blame -r "$rev2" "$file") \
    | {
        #header stuff
        echo "Index: $file"
        echo '==================================================================='
        echo "--- $file $title1"
        echo "+++ $file $title2"

        #count the line number we're up to for the original file
        origLine=0
        #count the line number we're up to for the new file
        newLine=0

        #keep a few of the output lines, and their line number contexts
        buffer=()
        origContext=()
        newContext=()

        #tells the script to print the buffer if <3;
        #the context lines around real differences
        printing=4
        #whether or not the next print needs to show line numbers
        needsContext=true

        #the sed match and replace expressions to pull data from diff
        #and give it to read
        grabData='^\([+=-]\)\( *[0-9]\+\)\( *[^ ]\+\)\(.*\)$'
        formatData='\1\v\2\v\3\v\4'

        #for each line in the full diff
        while read -r data
        do
            IFS=$'\v' read flag committed who line <<<"$(\
                sed $'s/\t/    /g' \
                <<<"$data" \
                | sed "s/$grabData/$formatData/" \
            )"
            #the last surviving revision of the line
            edited="$rev2"
            #who killed this line
            by=''

            case "$flag" in
            +)
                #a new line was introduced
                ((++newLine))
                printing=0
            ;;
            -)
                #an old line was removed
                ((++origLine))
                printing=0
                #the line number that changes throughout history
                number="$origLine"
                #for each commit
                for revision in "${history[@]}"
                do
                    #read in the two line numbers from the matching change
                    number="$(grep "^$number " <<<"${revisions["$revision"]}")"
                    IFS=' ' read edited by <<<"$revision"

                    #not present; this was the revision where it was destroyed
                    if [ -z "$number" ]
                    then
                        break
                    fi

                    #pull the new line number for the next revision
                    IFS=' ' read tmp number <<<"$number"
                done
            ;;
            =)
                #an old line continues to exist in the new file
                ((++newLine))
                ((++origLine))
                flag=' '
                ((++printing))
            ;;
            esac

            #format the line to print
            buffer+=("$(printf "%s %s:%-${#committed}s%s:%-${#who}s%s" \
                "$flag" \
                "$committed" \
                "$edited" \
                "$who" \
                "$by" \
                "$line" \
            )")
#can just end it here, but it will print the whole file/s
#            echo "${buffer[-1]}"
#            buffer=()
#            continue
            #and add the context
            origContext+=("$origLine")
            newContext+=("$newLine")

            if ((printing < 4))
            then
                if $needsContext
                then
                    echo "@@ -${origContext[0]} +${newContext[0]} @@"
                    needsContext=false
                fi

                #print all lines in the buffer
                for line in "${buffer[@]}"
                do
                    echo "$line"
                done

                #and reset it
                origContext=()
                newContext=()
                buffer=()
            fi

            #if there are too many lines in the buffer
            if ((${#buffer[@]} > 3))
            then
                #remove the overflow
                origContext=("${origContext[@]:1}")
                newContext=("${newContext[@]:1}")
                buffer=("${buffer[@]:1}")
                #and note that we now need to show the context because of this
                needsContext=true
            fi
        done
    }
}

我添加了注释作为解释,因此这里就不深入讨论了。在我的系统上
测试了diff(fedora 27)、svn info(1.10.2) 的输出,YMMV(但尽管我付出了这么多努力,但我希望结果不会那么好!)。

它基本上重新实现了svn diff使用 justsvn cat和 regulardiff来考虑修订和行号,准确跟踪历史记录中某一行被删除的位置。
甚至考虑文件是否位于不同的分支中,并将其显示为 svn 所为。

以下是两个命令的屏幕截图,其中的代码因工作原因已被删除。

~/data/<redacted>/svn-2.4.2/$ svn diff -r 6600 services/<redacted>.w3p | gvim -
~/data/<redacted>/svn-2.4.2/$ blameDiff services/<redacted>.w3p 6600 | gvim -

在此处输入图片描述

如您所见,右侧的新格式提供了大量额外信息;第一列显示 ashley 在 r6631 中添加了几行,并在 r6639 中删除了一大堆很久以前由 zes 提交的 @r6466&6483。

答案4

这并不是你想要的,但你可以得到一个注释视图来查看更改OpenGrok

相关内容