【问题标题】:Find out all GIT changes in a certain line in a file找出文件中某一行的所有 GIT 更改
【发布时间】:2014-12-12 12:11:15
【问题描述】:

我有一行代码最近更改为非工作状态。

我如何找出谁以及在哪个提交中更改了这一特定行?

我试过了

git log -some_distinct_string_from_that_line --pretty=format:'%h %an -- %s -- %ad'

其中显示了 cmets 和作者的所有提交,这些提交更改了一行包含“one_distinct_string_from_that_line”的任何内容,但我如何才能看到他们所做的实际更改?

编辑:
我还安装了git-gui 并查看了带有git gui blame filename 的行,但显示的该行只有一个提交更改,尽管肯定有更多更改。

我检查了图形 gui smartgit 以手动查看对该文件所做的所有更改,我发现了 3 个提交,其中该行肯定被编辑(首先删除了 #,然后再次添加了另一个提交)

是否有另一种方式不中继 git blame 功能,并且不中继假设,即该行位于 commit-diff 中?

【问题讨论】:

  • 为什么要排除git blame? “[...] doesn't relay on the assumption, that the line is in the commit-diff”是什么意思?每一行都必须出现在差异中。
  • 到目前为止,我能找到的唯一方法是使用图形 gui smartgit,它告诉我,几个月前该文件中还有一个变化,那就是删除了该行开头的#。但是其他方法(使用责备)都没有向我展示特定的提交。我想也许另一种方法会让我发现变化。也许我们在这里发现了一个错误?
  • 可能不会。 Git blame 可以很好地找出哪个提交引入/修改了一行。 Git blame 将打印提交 ID。手动方法是将该行定位在HEAD,查找提交ID,然后使用该修订的前身执行另一个blame,例如git blame 0deadbee~1 -- <FILE>。重复此步骤。如果您在<REV>~1 中找不到该行,<REV> 可能是引入提交。 Git show 可以帮助识别一行在删除或修改之前的外观。由于没有程序/脚本理解您检查的代码,因此很难以编程方式执行这些步骤。
  • 但是为什么 smartgit 发现了那个 commit 而 git 没有责备呢?

标签: git


【解决方案1】:

git blame。 -L 选项采用一系列行,您可以选择一个文件作为 git log。所以git blame -L 10,20 -- my/file.txt 将显示最近的 git 提交,它触及了该文件中的每一行。 git gui blame my/file.txt 做同样的工作,但有一个 UI 可以让你及时浏览。

【讨论】:

  • 这实际上比我的回答要好得多。 git gui blame yourfile.txt 然后转到有问题的线路。您可以单击左侧的提交 SHA1 及时移动并查看对这些行的连续更改。
  • 你是怎么得到git gui的?
  • 它包含在 git 源代码分发版和适用于 Windows 的 Git 中。在基于 Debian 的 Linux 上,您将添加 git-gui 包,我确信大多数发行版都存在类似的包。由于对 UI 包(Tcl/Tk、X 等)的额外依赖,它通常与命令行 git 分开。
  • 我安装了 apt-get install git-gui 并查看了带有 git blame file 的行,但显示的该行只有一个提交更改,尽管肯定有更多更改。
  • git blamegit gui blame 都显示了 most recent 提交以触及每一行。在 GUI 中,您单击提交链接,它使用该提交作为新参考重新生成显示,现在将显示影响该行的先前提交。顶部的后退箭头可让您在必要时再次及时前进。
【解决方案2】:

您可以将以下行添加到您的.git/config 文件的[alias] 部分:

findchange = !sh -c \"git log --pretty=format:'COMMIT %C(yellow)%h %an -- %s -- %ad%C(reset)' -G'$1' -p --word-diff-regex='[A-Za-z0-9]+|[^A-Za-z0-9]|$1' --color=always ${@:2} | egrep '$1|^COMMIT|-{3} a\\/|\\+{3} b\\/' \"

然后,只需在命令行执行以下命令:

git findchange 'yourText'

解释:

  • 我稍微修改了您漂亮的格式,以便您能够发现每个提交的开头。
  • 对日志使用 -p 选项,该选项会为每个提交显示一个补丁,因此显示 p。
  • 使用--word-diff-regex 选项定义一个词。这将显示按整个单词或单个非单词字符分组的内联更改。
    • 将搜索文本本身作为正则表达式的一部分;否则,它不会捕获更改跨越单词的情况
  • --color=always 即使在管道到 egrep 时也会保留颜色。
  • egrep 查找属于以下之一的所有行:
    • 提交信息
    • 您正在搜索的文本(删除或添加)
    • 更改文件的原始名称
    • 更改文件的新名称

【讨论】:

  • 感谢您的精细改进,但是,这似乎并没有找到该行的所有更改
  • @rubo77 你能举个例子吗?
  • 没有。我得到-: Bad substitution
  • @rubo77 尝试用 sh 替换 /bin/bash 或 /bin/ksh。它在我的系统上与 sh 一起工作,但不同类型的 shell 以不同的方式工作。
  • 最后的破折号 (-) 不需要缝合。 (它没有给我带来问题,但也许那是你的问题。)我把它包括在内是因为我看到很多地方说它是必要的,但我没有最后的破折号就试过了,它似乎不是一个问题。
【解决方案3】:

使用gitk,你可以这样做:

gitk -Sone_distinct_string_from_that_line -- /some_sub_dir/containing/the/file

您将获得部分历史记录,其中仅包含 one_distinct_string_from_that_line 在差异中的提交。 对于每个提交,您可以查看作者、cmets、上下文,并检查确切的更改内容。

-- 之后的部分是可选的,它将研究限制在存储库的子目录中。

【讨论】:

  • 这看起来不错,它是我在控制台上看到的 git -S 的 gui,但只包含第一个提交。我刚刚提交的最后一次提交也不见了
  • 哼..那你有问题了=)。但请查看@patthoyts 答案
  • 您也可以将--all 添加到gitk 的选项中。你确定你的最后一次提交是在同一个分支上吗?
  • 肯定在同一个分支(主干)上,我在那一行有更多的编辑。也许问题是,在其他提交中删除并添加了评论 #
  • Git 对 cme​​ts 或语言特性一无所知。据我所知,git 会逐行处理更改(实际上是内容)。也就是说,如果您更改包含字符串whatever 的行上的一个字符,则整行都会添加到差异中。因此gitk -Swhatever 应该接受它。
【解决方案4】:

执行下面的命令

cd repo<Project>
git config --global core.autocrlf true

修改几行代码

与分支、标签等比较

【讨论】:

    【解决方案5】:

    如果你使用 pycharm 的 git 集成,你可以选择感兴趣的行并使用 git-show history 从上下文菜单中进行选择

    【讨论】:

      猜你喜欢
      • 2020-12-09
      • 2015-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 2011-03-01
      • 2013-04-02
      • 1970-01-01
      相关资源
      最近更新 更多