Filtering a diff with a regular expression

前端 未结 7 1201
逝去的感伤
逝去的感伤 2020-12-01 21:30

It seems that it would be extremely handy to be able to filter a diff so that trivial changes are not displayed. I would like to write a regular expression which would be ru

7条回答
  •  一生所求
    2020-12-01 21:59

    There does not seem to be any options to Git's diff command to support what you want to do. However, you could use the GIT_EXTERNAL_DIFF environment variable and a custom script (or any executable created using your preferred scripting or programming language) to manipulate a patch.

    I'll assume you are on Linux; if not, you could tweak this concept to suit your environment. Let's say you have a Git repo where HEAD has a file file05 that contains:

    line 26662: $my_array[my_key]
    

    And a file file06 that contains:

    line 19768: $my_array[my_key]
    line 19769: $my_array[my_key]
    line 19770: $my_array[my_key]
    line 19771: $my_array[my_key]
    line 19772: $my_array[my_key]
    line 19773: $my_array[my_key]
    line 19775: $my_array[my_key]
    line 19776: $my_array[my_key]
    

    You change file05 to:

    line 26662: $my_array["my_key"]
    

    And you change file06 to:

    line 19768: $my_array[my_key]
    line 19769: $my_array["my_key"]
    line 19770: $my_array[my_key]
    line 19771: $my_array[my_key]
    line 19772: $my_array[my_key]
    line 19773: $my_array[my_key]
    line 19775: $my_array[my_key2]
    line 19776: $my_array[my_key]
    

    Using the following shell script, let's call it mydiff.sh and place it somewhere that's in our PATH:

    #!/bin/bash
    echo "$@"
    git diff-files --patch --word-diff=porcelain "${5}" | awk '
    /^-./ {rec = FNR; prev = substr($0, 2);}
    FNR == rec + 1 && /^+./ {
        ln = substr($0, 2);
        gsub("\\[\"", "[", ln);
        gsub("\"\\]", "]", ln);
        if (prev == ln) {
            print " " ln;
        } else {
            print "-" prev;
            print "+" ln;
        }
    }
    FNR != rec && FNR != rec + 1 {print;}
    '
    

    Executing the command:

    GIT_EXTERNAL_DIFF=mydiff.sh git --no-pager diff
    

    Will output:

    file05 /tmp/r2aBca_file05 d86525edcf5ec0157366ea6c41bc6e4965b3be1e 100644 file05 0000000000000000000000000000000000000000 100644
    index d86525e..c2180dc 100644
    --- a/file05
    +++ b/file05
    @@ -1 +1 @@
     line 26662: 
     $my_array[my_key]
    ~
    file06 /tmp/2lgz7J_file06 d84a44f9a9aac6fb82e6ffb94db0eec5c575787d 100644 file06 0000000000000000000000000000000000000000 100644
    index d84a44f..bc27446 100644
    --- a/file06
    +++ b/file06
    @@ -1,8 +1,8 @@
     line 19768: $my_array[my_key]
    ~
     line 19769: 
     $my_array[my_key]
    ~
     line 19770: $my_array[my_key]
    ~
     line 19771: $my_array[my_key]
    ~
     line 19772: $my_array[my_key]
    ~
     line 19773: $my_array[my_key]
    ~
     line 19775: 
    -$my_array[my_key]
    +$my_array[my_key2]
    ~
     line 19776: $my_array[my_key]
    ~
    

    This output does not show changes for the added quotes in file05 and file06. The external diff script basically uses the Git diff-files command to create the patch and filters the output through a GNU awk script to manipulate it. This sample script does not handle all the different combinations of old and new files mentioned for GIT_EXTERNAL_DIFF nor does it output a valid patch, but it should be enough to get you started.

    You could use Perl regular expressions, Python difflib or whatever you're comfortable with to implement an external diff tool that suits your needs.

提交回复
热议问题