git diff:忽略某些正则表达式的删除或插入 [英] git diff: ignore deletion or insertion of certain regex

查看:239
本文介绍了git diff:忽略某些正则表达式的删除或插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果添加或删除了以下表达式,我尝试使用 git diff 查找某个文件类型的两个版本之间的差异:


(****)


根据 git diff文档参数 -G 是我想要的。因此,我尝试了以下操作:

  git diff -G'\(\ * \ * \ * \ * \)'-* .fileEnding 

不幸的是,它不起作用,并且所有其他区别文件也被返回。我对正则表达式btw不太熟悉。



编辑:我认为需要对我的问题更具体一些:现在我有以下情况:一个文件具有与正则表达式匹配的更改,而与正则表达式匹配的更改。在我的脚本中,我正在尝试执行以下操作(伪代码):

  if(((git diff -G'\ (\ * \ * \ * \ * \)'-* .fileEnding)==(git diff-* .fileEnding))打印仅(****)中的更改; 

如果某些文件仅在(****)中有更改,而其他文件具有不同,则可以正常工作变化。但是,一旦一个文件同时具有这两个文件,它将无法正常工作

解决方案

TL; DR



Git的 git diff 只是不这样做。



详细说明



文档具有误导性。



-G 参数完全没有作用为 git diff 。相反, -G 实际上是 git log 的一个参数(及其姐妹命令 git rev-list ,以及调用这些其他命令的任何命令;但我认为最好是根据 git log 来考虑它。) / p>

git diff git log 命令共享他们的一些文档(足够合理-他们共享一些代码,特别是 git log 用于比较任何提交与其差异的差异生成代码



git log 选择提交时,您可以告诉它选择一些特定提交(在修订说明者已经做出的选择中)。 -G 自变量就是这样的选择器,非常相似的 -S 自变量也是如此。 -S 默认情况下使用字符串而不是正则表达式;但是您可以添加-pickaxe-regex 来使 -S 使用正则表达式。文档中有一个示例,该示例直接引用了 git log


-G® regex>



查找差异,其补丁文本包含与< regex>相匹配的添加/删除的行



为了说明 -S®正则表达式之间的区别, --pickaxe-regex
-G< regex> ,考虑在同一文件中包含以下差异的提交:

  + return!regexec(regexp,2-> ptr,1,& regmatch,0); 
...
-命中=!regexec(regexp,mf2.ptr,1,& regmatch,0);

而git log -G regexec\(regexp 将显示此提交,
git log -S regexec\(regexp --pickaxe-regex 不会(因为出现的次数该字符串不变)。


git diff 命令,不是 git log 命令。



git log 的工作原理是向它传递一个起始提交(例如,哈希ID或分支或标记名),并且它是:




  • 向您显示该提交,然后

  • 向您显示该提交的父级,然后

  • 向您显示该提交的父级。 ..



依此类推,一直返回到第一次提交(或者当您厌倦了寻找并退出时换句话说,至少在这些简单情况下,存在一个循环:

  while(有一个提交$ commit)
父母= resolve_hash_id ($ commit + ^)
show($ commit)
commit = $ parent

如果添加 -p ,则显示步骤包括 git diff $ parent $ commit 。



请注意, git diff 恰好是两个提交进行比较(嗯,有一种特殊的diff,称为 combined diff ,用于合并提交,但是 git log 不会默认显示它们,并且正常使用 git diff 都不是)。 git log 的两个提交是父母和孩子。如果您自己运行 git diff ,则可以选择任意两个提交...但是当您执行此操作时, git diff 完全忽略任何 -G -S 参数。(它可能会抱怨



-G -S 将影响 git log 的正常行为。通常,当我们一次查看一次提交时,就像 git log 那样,我们对特定更改更感兴趣特定文件(或文件集)。我们可以使用 -G -S 来告诉 git log 生成diff,但是如果它没有更改,则根本不显示提交。这样,我们只能看到那些具有更改的提交。 (添加文件名,例如 git log stop..start-path / to / file1.txt ,也将差异限制为这些文件。与 -S -G 部分可以使用的 $ c> git diff 。)



您可以做什么



如果您不知道需要哪个修订,可以使用 git log (或其面向脚本的姐妹命令 git rev-list )以筛选候选人。在这里,您可以使用 -G 。您不必现在就获得差异,尽管您可以根据需要。如果 -G 不仅使您成为可能的候选人,而且实际上使您获得正确的候选人,那么您就完成了您可以在这里停止。



如果您仍然有太多的求职者,并且需要完整的差异以进一步降低它们,现在可以运行 git diff 第一步获得的哈希ID( git log git rev-list )。对于这些提交中的每一个,您都必须选择将其与之进行比较的提交:可能是候选列表中的某个提交,或者可能恰好在此特定候选之前或之后的提交。现在您不再具有 -G 工具:要搜索差异,您将需要一些外部搜索工具,例如 grep 。由您决定编写此部分。


I'm trying to use git diff to find differences between two version of a certain file type if the following expression has been added or deleted:

(****)

According to the git diff Documentation the parameter -G is what I'm looking for. So I tried the following:

git diff -G '\(\*\*\*\*\)' -- *.fileEnding

Unfortunately it doesn't work and all other differences in the files are returned too. I'm not very familiar with regexs btw.

EDIT: I think need to be a little more specific about my issues: Right now I have the following case: One file has changes which match the regex and changes which doesn't. In my script I'm trying to do something like this (Pseudocode):

if((git diff -G '\(\*\*\*\*\)' -- *.fileEnding)==(git diff -- *.fileEnding)) print "Only changes in (****)";

It works fine if some files only have changes in (****) and other file have different changes. But it doesn't work as soon one file has both

解决方案

TL;DR

Git's git diff just doesn't do that.

Long explanation

The documentation is misleading.

The -G argument does absolutely nothing for git diff. Instead, -G is actually an argument to git log (and its sister command, git rev-list, and any command that invokes these others; but best to just think of it in terms of git log, I think).

The git diff and git log commands share some of their documentation (reasonably enough—they share some of their code, specifically the diff-generating code that git log uses to compare any one commit to its parent(s)).

When git log is selecting commits, you can tell it to select some specific commits (out of the selection already made by revision specifiers). The -G argument is one such selector, as is the very similar -S argument. -S takes a string, rather than a regular expression, by default; but you can add --pickaxe-regex to make -S take a regular expression. The documentation has an example, and the example literally refers directly to git log:

-G<regex>

Look for differences whose patch text contains added/removed lines that match <regex>.

To illustrate the difference between -S<regex> --pickaxe-regex and -G<regex>, consider a commit with the following diff in the same file:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

While git log -G"regexec\(regexp" will show this commit,
git log -S"regexec\(regexp" --pickaxe-regex will not (because the number of occurrences of that string did not change).

The git diff command, though, is not the git log command.

The way git log works, in general, is that you pass it a starting commit—a hash ID, for instance, or a branch or tag name—and it:

  • shows you that commit, then
  • shows you the parent of that commit, then
  • shows you the parent of the parent ...

and so on, all the way back to the very first commit (or when you get tired of looking and quit out of the pager). In other words, at least for these simple cases, there is a loop:

while (there is a commit $commit)
    parent = resolve_hash_id($commit + "^")
    show($commit)
    commit = $parent

If you add -p, the "show" step includes the output of git diff $parent $commit.

Note that git diff compares exactly two commits (well, there is a special kind of diff called a combined diff for merge commits, but git log does not show them by default, and normal usage of git diff doesn't either). The two commits for git log are the parent and the child. If you run git diff yourself, you can pick any two arbitrary commits ... but when you do that, git diff completely ignores any -G or -S arguments. (It probably should complain about their presence.)

The point of -G and -S is to affect the normal behavior of git log. Often, when we're looking at commits one at a time, in sequence, the way git log does, we're more interested in a particular change to a particular file (or set of files). We can use -G or -S to tell git log: Generate the diff, but then if it doesn't have the change, don't show the commit at all. That way we see only those commits that have those changes. (Adding file names, e.g., git log stop..start -- path/to/file1.txt, limits the diff to those files as well. Unlike -S and -G, that part does work with git diff.)

What you can do

If you don't know which revisions you want, you can use git log (or its script-oriented sister command git rev-list) to screen candidates. Here, you can use -G. You don't have to get the diff now, though you can if you want. If -G not only gets you the possible candidates, but in fact gets you the right ones, you are done and you can stop here.

If you still have too many candidates and need full diffs to whittle them down further, you can now run git diff on the hash IDs obtained by the first step (git log or git rev-list). For each of these commits, you must choose which commit to compare it to: perhaps some commit from the candidate list, or perhaps a commit just before or just after this particular candidate. Now you no longer have the -G tool: to search the diff, you will need some external searching tool, such as grep. It's up to you to write this part.

这篇关于git diff:忽略某些正则表达式的删除或插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆