如何使用管道在git别名中添加shell函数

时间:2013-11-07 12:26:42

标签: git alias

我从Using git diff, how can I get added and modified lines numbers?找到了一个很好的shell函数 diff-lines()

我在我的.bashrc文件中添加了该功能,它可以在我的命令行中使用:

[marslo@mppdev ~/Tools/Git/LinuxStuff]
$ git diff -U0 | diff-lines
Scripts/.marslorc:29:-# Inspired from https://stackoverflow.com/questions/8259851/using-git-diff-how-can-i-get-added-and-modified-lines-numbers
Scripts/.marslorc:29:+# Inspired from https://stackoverflow.com/questions/8259851/using-git-diff-how-can-i-get-added-and-modified-lines-numbers/12179492#12179492

但是,当我尝试将命令添加为git别名时,出现了错误:

[marslo@mppdev ~/Tools/Git/LinuxStuff]
$ cat ~/.gitconfig | grep "ldiff ="
    ldiff = "!bash -c 'git diff -U0' | diff-lines"
[marslo@mppdev ~/Tools/Git/LinuxStuff]
$ git ldiff
sh: diff-lines: command not found
fatal: Failed to run 'bash -c 'git diff -U0' | diff-lines' when expanding alias 'ldiff'

并且bash -c 'git diff -U0' | diff-lines仍有效

[marslo@mppdev ~/Tools/Git/LinuxStuff]
$ bash -c 'git diff -U0' | diff-lines
Scripts/.marslorc:29:-# Inspired from https://stackoverflow.com/questions/8259851/using-git-diff-how-can-i-get-added-and-modified-lines-numbers
Scripts/.marslorc:29:+# Inspired from https://stackoverflow.com/questions/8259851/using-git-diff-how-can-i-get-added-and-modified-lines-numbers/12179492#12179492

这里的细节: ldff

2 个答案:

答案 0 :(得分:2)

问题是diff-lines是shell函数而不是实际的可执行文件。当您运行"!bash -c 'git diff -U0' | diff-lines"时,您会收到错误消息,因为您的~/.bashrc并未获取shell,因此它不了解diff-lines。这是shell的正常行为 - 它们仅在特定情况下获取这些设置,并且运行命令不是其中之一。

所以这里有一些建议。首先,如果行号特征在git之外很好,可以考虑将diff-lines设置为脚本而不仅仅是shell函数:

#!/bin/bash

diff-lines() {
    local path=
    local line=
    while read; do
        esc=$'\033'
        if [[ $REPLY =~ ---\ (a/)?.* ]]; then
            continue
        elif [[ $REPLY =~ \+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then
            path=${BASH_REMATCH[2]}
        elif [[ $REPLY =~ @@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+)(,[0-9]+)?\ @@.* ]]; then
            line=${BASH_REMATCH[2]}
        elif [[ $REPLY =~ ^($esc\[[0-9;]+m)*([\ +-]) ]]; then
            echo "$path:$line:$REPLY"
            if [[ ${BASH_REMATCH[2]} != - ]]; then
                ((line++))
            fi
        fi
    done
}

diff-lines

然后您可以将别名设置为:

ldiff = !sh -c 'git diff "$@" | diff-lines' -

这也允许您将参数传递给git ldiff,就像真正的diff命令一样。您也可以在diff-lines

中执行以下操作,将~/.gitconfig用作寻呼机
[pager]
    diff = diff-lines | less

然后,常规git diff命令将通过您的diff-lines脚本传输,最后通过less来获取分页。我使用相同的技巧来突出显示行中的单词变化。

另一个选择是Adam提到的:创建一个名为git-ldiff的脚本,它运行你的diff命令并通过diff-lines管道

#!/bin/bash

diff-lines() {
    local path=
    local line=
    while read; do
        esc=$'\033'
        if [[ $REPLY =~ ---\ (a/)?.* ]]; then
            continue
        elif [[ $REPLY =~ \+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then
            path=${BASH_REMATCH[2]}
        elif [[ $REPLY =~ @@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+)(,[0-9]+)?\ @@.* ]]; then
            line=${BASH_REMATCH[2]}
        elif [[ $REPLY =~ ^($esc\[[0-9;]+m)*([\ +-]) ]]; then
            echo "$path:$line:$REPLY"
            if [[ ${BASH_REMATCH[2]} != - ]]; then
                ((line++))
            fi
        fi
    done
}

git diff "$@" | diff-lines

注意:这与上面的脚本完全相同,对最后一行进行了少量修改。

答案 1 :(得分:1)

而不是使用别名:

  1. 将您的代码放入脚本
  2. 将脚本命名为git-ldiff
  3. 使用chmod +x script使其可执行,
  4. 将脚本放在PATH中的目录中。
  5. 现在,当您输入git ldiff时,git会找到并运行您的scipt。