【问题标题】:How can I add a shell function in git alias with pipe如何使用管道在 git 别名中添加 shell 函数
【发布时间】:2013-11-19 02:20:25
【问题描述】:

我从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

这里有详细信息:

【问题讨论】:

    标签: git alias


    【解决方案1】:

    而不是使用别名:

    1. 将您的代码放入脚本中,
    2. 将脚本命名为git-ldiff
    3. 使用chmod +x <em>script</em> 使其可执行,并且
    4. 将脚本放在 PATH 中的目录中。

    现在,当你输入 git ldiff 时,git 会找到并运行你的 scipt。

    【讨论】:

    • 嗨@Adam,感谢您的评论。但是,我不想单独创建脚本文件(即使我知道这种方式有效)。我的.bashrc 有很多功能,管理起来不方便。而且我的路径会很长..
    【解决方案2】:

    问题在于diff-lines 是一个shell 函数,而不是一个实际的可执行文件。当你运行"!bash -c 'git diff -U0' | diff-lines" 时,你会得到一个错误,因为shell 没有获取你的~/.bashrc,所以它不知道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 命令一样。您还可以通过在您的~/.gitconfig 中执行以下操作,将diff-lines 用作您的寻呼机:

    [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
    

    注意:这与上面的脚本完全相同,只是对最后一行稍作修改。

    【讨论】:

    • 嗨@jszkmeister,差异行不能设置在.bashrc 的末尾。否则,当我打开终端时,bash 总是在等待读取。
    • 嗨,我厌倦了你所有的方法,除了创建一个新脚本并将位置添加到 $PATH 之外,它们都无法工作。有没有办法在不创建新文件的情况下进行别名?谢谢
    • @MarsloJiao 正如我在帖子中所说,您需要将 diff-lines 设为脚本——这是最好的方法。还有其他选择,但由于各种原因,我认为它们低于标准。例如,您可以手动获取 .bashrc 或强制登录 shell。第一个选择看起来像这样:ldiff = !bash -c '. ~/.bashrc &amp;&amp; git diff "$@" | diff-lines' -。您也可以这样做:ldiff = !bash -l -c 'git diff "$@" | diff-lines' - 使其成为登录 shell(它将读取您的 ~/.bashrc)。最好的选择是创建一个脚本。
    • 哦,是的!!!!有用!!别名就是ldiff = !bash -c '. ~/.bashrc &amp;&amp; git diff "$@" | diff-lines' -。非常感谢!
    • 但是,我有一个问题,.bashrc 将在我登录时执行。它确实有效(我可以在命令行中使用差异行)。为什么这个文件需要再次作为源文件?
    猜你喜欢
    • 2019-01-10
    • 2013-10-31
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    相关资源
    最近更新 更多