You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Git仅在新增或删除行中搜索指定字符串?

如何在Git提交历史中仅搜索新增或删除行中的特定字符串

我可以使用git log -S "text to find" --stat在变更内容中搜索字符串,但如何实现仅在新增行或删除行(而非同时在两者中)搜索该字符串?--diff-filter选项似乎是过滤整个文件而非单独行。


更新

我基于@LeGEC的答案编写了一个bash脚本,虽设计过度且效率较低(尤其在Cygwin中),但运行正常。将脚本保存为git-xlog可作为Git的xlog子命令使用,Linux系统需设置可执行权限。

示例命令

git xlog --diff-type=added --log-opt='--author=someone -S "sometext"' --diff-opt='--stat'

完整脚本

#!/usr/bin/env bash

app_name="$(basename "${BASH_SOURCE[0]}")"

USAGE=$(cat << EOF
Usage:
    $app_name
        Search history for string only in added or removed lines.

Options:
    -t, --diff-type=<A|R|Added|Removed>
        Whether to search in added or removed lines.

    -l, --log-opt=<LOG_OPTIONS>
        Options to pass on to git log commands.

    -d, --diff-opt=<DIFF_OPTIONS>
        Options to pass on to git diff commands.

    --help
        Show this help information and exit.
EOF
)

getopt -q -T
if [[ $? -ne 4 ]]; then
    echo "$app_name: This script requires an enhanced getopt version." >&2
    exit 1
fi

opts=$(getopt -o 't:l:d:' --long 'help,diff-type:,log-opt:,diff-opt:' -n "$app_name" -- "$@") || exit $?

eval "opts=($opts)"

for ((i=0; i < ${#opts[@]}; i++)); do
    opt="${opts[$i]}"
    case "$opt" in
        --help)
            echo "$USAGE"
            exit 0
            ;;
        -t|--diff-type)
            diff_type="${opts[++i]}"
            ;;
        -l|--log-opt)
            log_opt="${opts[++i]}"
            ;;
        -d|--diff-opt)
            diff_opt="${opts[++i]}"
            ;;
        --)
            break
            ;;
        *)
            echo 'Internal error!' >&2
            exit 1
            ;;
    esac
done

if [[ ! -v diff_type ]]; then
    echo "$app_name: Missing '--diff-type' argument." >&2
    exit 1
elif [[ -z $diff_type ]]; then
    echo "$app_name: Missing value for argument '--diff-type'." >&2
    exit 1
elif [[ ${diff_type@U} == 'A' || ${diff_type@U} == "ADDED" ]]; then
    diff_mark='>'
elif [[ ${diff_type@U} == 'R' || ${diff_type@U} == "REMOVED" ]]; then
    diff_mark='<'
else
    echo "$app_name: Unrecognized diff-type: '$diff_type'. Accepted values: 'A', 'Added', 'R', 'Removed'." >&2
    exit 1
fi

if [[ ! -v log_opt ]]; then
    echo "$app_name: Missing '--log-opt' argument." >&2
    exit 1
elif [[ -z $log_opt ]]; then
    echo "$app_name: Missing value for argument '--log-opt'." >&2
    exit 1
fi

opts=$(eval getopt -q -o 'S:G:' -n "$app_name" -- "$log_opt")

eval "opts=($opts)"

for ((i=0; i < ${#opts[@]}; i++)); do
    opt="${opts[$i]}"
    case "$opt" in
        -S)
            search_text="${opts[++i]}"
            ;;
        -G)
            search_regex="${opts[++i]}"
            ;;
        --)
            break
            ;;
        *)
            echo 'Internal error!' >&2
            exit 1
            ;;
    esac
done

if [[ ! -v search_text && ! -v search_regex ]]; then
    echo "$app_name: No '-S' or '-G' found in log options." >&2
    exit 1
elif [[ -z $search_text && -z $search_regex ]]; then
    echo "$app_name: Missing value for argument '-S' or '-G' in log options." >&2
    exit 1
fi

trap interrupt INT

interrupt () {
    echo "$app_name: Interrupted." >&2
    exit 1
}

if [[ -t 1 ]]; then 
    git_color="--color"
    less_color="-r"
fi

if [[ -n $search_regex ]]; then
    grep_opt='-E "$search_regex"'
elif [[ -n $search_text ]]; then
    grep_opt='"$search_text"'
fi

set -e

eval git log "$log_opt" --no-patch --format=%H |
while read -r sha; do
    eval git diff -U0 "$sha~" "$sha" --output-indicator-new='\>' --output-indicator-old='\<' |
    grep -E "^$diff_mark" |
    eval grep -q "$grep_opt" &&
    eval git --no-pager log "$git_color" --no-walk "$sha" "$log_opt" "$diff_opt"
done | less -deFX $less_color

内容的提问来源于stack exchange,提问作者Ahmet Sait

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:14:51