【问题标题】:Search for text in git commit range在 git commit range 中搜索文本
【发布时间】:2016-08-01 07:34:40
【问题描述】:

我需要在过去 20 次 git 提交(或范围)中搜索文本“TEXT”
我需要查看匹配的文件名和行号。

注意:
我想搜索提交内容,但不是像 git grep 那样在该提交上进行项目。
提交内容是指使用git diff HEAD^^^..HEAD可以看到的内容

我得到的最接近的是使用git log --raw -GTEXT,它向我显示提交内容中包含“TEXT”的提交并显示文件名。但是仍然没有行号。

还有一些管道
git diff $(git log -n 20 --pretty=format:%h -GTEXT) | grep -E 'TEXT|\+\+\+|@@\s'
还是有点啰嗦,杂音很多,如果有更好的解决方案,请回答。

【问题讨论】:

  • 我想像git diff 这样的提交范围,然后通过管道将其传递给grep
  • git log -g --grep=TEXT 怎么样?
  • @Shravan40 你错过了--grep?
  • @cricket_007 git diff 默认不显示文件名和行号,你能详细说明一下吗?
  • 相反,它确实显示文件名和行号。 --- a/file.txt 用于删除的行。 +++ b/file.txt 用于添加行,@@ start, stop @@ 用于显示更改的位置

标签: git


【解决方案1】:

获取最近 20 次提交:

git log -n 20

把每个都放到一个关联数组中:

declare -A COMMITS # Declare associative array
COMMITNUMBER=0

while read -r line; do # For each line, do
    # Add 1 to COMMITNUMBER, if the current line contains "commit [0-9a-f]* (e.g., new associative array index for each commit)
    # As this'll happen straight way, our array is technically 1-indexed (starts from "${COMMITS[1]}", not "${COMMITS[0]}")
    REGEX="commit\s[0-9a-f]*"
    [[ "$line" =~ $REGEX ]] && COMMITNUMBER=$(( COMMITNUMBER+1 ))

    # Append the commit line to the index
    COMMITS[$COMMITNUMBER]="${COMMITS[$COMMITNUMBER]} $line"
done < <(git log -n 20)

然后迭代:

for i in "${!COMMITS[@]}"
do
  echo "key  : $i"
  echo "value: ${COMMITS[$i]}"
done

这给出了与以下类似的输出:

key  : 1
value:  commit 778f88ec8ad4f454aa5085cd0c8d51441668207c Author: Nick <nick.bull@jgregan.co.uk> Date:   Sun Aug 7 11:43:24 2016 +0100  Second commit 
key  : 2
value:  commit a38cd7b2310038af180a548c03b086717d205a61 Author: Nick <nick.bull@jgregan.co.uk> Date:   Sun Aug 7 11:25:31 2016 +0100  Some commit

现在您可以使用grep 或其他任何内容搜索循环中的每个,并匹配您需要的内容:

for i in "${!COMMITS[@]}"
do
    REGEX="Date:[\s]*Sun\sAug\7"
    if [[ "${COMMITS[$i]}" =~ $REGEX ]]; then
        echo "The following commit matched '$REGEX':"
        echo "${COMMITS[$i]}"
    fi
done

总共:

search_last_commits() {
    [[ -z "$1" ]] && echo "Arg #1: No search pattern specified" && return 1
    [[ -z "$2" ]] && echo "Arg #2: Number required for number of commits to return" && return 1

declare -A COMMITS # Declare associative array
COMMITNUMBER=0

    while read -r line; do # For each line, do
        # Add 1 to COMMITNUMBER, if the current line contains "commit [0-9a-f]* (e.g., new associative array index for each commit)
        # As this'll happen straight way, our array is technically 1-indexed (starts from "${COMMITS[1]}", not "${COMMITS[0]}")
        REGEX="commit\s[0-9a-f]*"
        [[ "$line" =~ $REGEX ]] && COMMITNUMBER=$(( COMMITNUMBER+1 ))

        # Append the commit line to the index
        COMMITS[$COMMITNUMBER]="${COMMITS[$COMMITNUMBER]} $line"
    done < <(git log -n $2)

    for i in "${!COMMITS[@]}"
    do
        REGEX="$1"
        if [[ "${COMMITS[$i]}" =~ $REGEX ]]; then
            echo "The following commit matched '$REGEX':"
            echo "${COMMITS[$i]}"
        fi
    done
}

编辑:

用法:

search_last_commits <search-term> <last-commits-quantity>

例子:

search_last_commits "Aug" 20

【讨论】:

    【解决方案2】:

    如果您想搜索范围内修改过的文件(并且不关心在这些提交中实际未修改的文件的匹配行),您可以运行:

    git grep TEXT -- $(git diff --name-only RANGE)
    

    【讨论】:

      【解决方案3】:

      最简单的方法:GIT_SEQUENCE_EDITOR=: git rebase --exec "git rev-parse HEAD; git --no-pager grep -n 'TEXT_TO_FIND'; echo " -i HEAD~20

      详情:

      git rev-parse HEAD - 显示当前 sha1

      git --no-pager grep -n 'TEXT_TO_FIND' - 用于查找文本的 grep 命令,您可以在此处使用任何其他命令(如常规 grep 等)

      echo - 在每次提交之间打印空行的命令,并确保返回值始终正确

      HEAD~20 - 你想搜索多少次提交(这里我做了 20 个)

      一些有用的答案:link1link2

      【讨论】:

      • 为什么里面有rebase?
      • 我实际上是基于“我自己”,所以所有的提交都将保持不变。这只是在每次提交和提交时运行命令的技巧..
      • 你知道这将为这 20 个提交创建新的哈希值,对吧?
      • 那些“新”提交将与旧提交完全相同,因为我们不会更改任何内容。因此,您将获得与以前完全相同的 sha1。
      • @logcat 试试这个,你会看到完全相同的哈希值。
      【解决方案4】:

      试试这个:

      echo `git log --raw --pretty=format:%h -GTEXT | xargs | awk '{print $NF}'` ;grep -ni 'MAX_STR_LEN' $(git log --raw --pretty=format:%h -GMAX_STR_LEN | xargs | awk '{print $NF}')
      

      这对我来说适用于单一提交版本。可能你可以循环 n 次来实现你的目标。

      【讨论】:

        【解决方案5】:
        git grep SEARCH `git rev-list HEAD~20..HEAD`
        

        指定您需要的任何范围。

        结果将是每个修订版的 grep。 也就是说,您会在每个修订中看到 所有 项。您看不到相对于先前版本的变化。 (其他通过将自己与上一版本列出的行进行比较)

        而且速度很慢。因为它会对范围内的每个修订版进行完整的 grep。


        或者,您可以将其限制为与搜索词相关的更改(在范围内)。

        git grep SEARCH  `git log -G SEARCH  --format=%H HEAD~20..HEAD`
        

        虽然仅限于具有相关搜索的修订版,但在每个此类修订版中,您都会获得 所有 行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-03-11
          • 1970-01-01
          • 1970-01-01
          • 2017-03-19
          • 2012-01-18
          • 1970-01-01
          相关资源
          最近更新 更多