Bash function to find all Git commits in which a file (whose name matches a regex) has *changed*

前端 未结 4 1718
渐次进展
渐次进展 2021-01-06 01:40

I have the following bash function, which searches for all files in a repository, whose filename matches a regular expression. It currently finds all commits in which a file

相关标签:
4条回答
  • 2021-01-06 01:49

    Use git diff-tree -r --name-only --no-commit-id (perhaps with --stdin) instead of git ls-tree -r --name-only. Use -m or -c if you are interested in merges, -M or -C if you want to take into account respectively, rename and copy detection.

    Or better parse output of git diff-tree -r.

    Nb. the code given in question is seriously suboptimal (among others you check multiple times the same commits).

    0 讨论(0)
  • 2021-01-06 01:51

    You could go through and use git diff to look at what changed between each of the commits. Something like this:

    for branch in `git for-each-ref --format="$ref" $LOC`;
    do
        previous_commit=""
        for commit in `git rev-list $branch | grep -oP ^.\{7\}`;
        do
            if [ "$previous_commit" != "" ];
            then
                found=$(git diff --name-only $previous_commit $commit | grep "$param")
                if [ $? -eq 0 ];
                then
                    echo "${branch#$LOC/}: $commit:"
                    while read line;
                    do
                        echo "  $line"
                    done < <(echo "$found")
                    echo
                    wasFound="1";
                fi
            fi
            previous_commit="$commit"
        done
    done
    
    0 讨论(0)
  • 2021-01-06 01:55

    If you can live with a shell glob pattern rather than a full-blown regex, consider

    git log -p --diff-filter=AMD --branches --tags -- "foo*bar.sh"
    

    With -p, you see the deltas along with the commit message, author, SHA1, etc. The --diff-filter=AMD option selects only those commits in which the files in question were Added, Modified, or Deleted. To search remotes as well as local branches and tags, use --all rather than --branches --tags. Finally, note the -- that introduces path patterns, which you will want to quote to allow git to perform glob matching.

    0 讨论(0)
  • 2021-01-06 01:59

    I came up with this function, which is based on Greg Bacon's answer. I originally wanted regex, but globs fit the bill nicely. I also expected that a looping function would be required, but the single git log line is all that's needed.

    First, a utility function:

    #https://stackoverflow.com/questions/369758/how-to-trim-whitespace-from-bash-variable#comment21953456_3232433
    alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"
    

    Documentation header:

    :<<COMMENT
       Searches all commits in the current git repository containing a file
       that has *changed*, whose name matches a glob. If the glob does not
       contain any asterisks, then it is surrounded by them on both sides.
    
    
       Usage:
          gitf "05"     #Equivalent to "*05*"
          gitf "05_*"
    
       Parameter is required, and must be at least one non-whitespace character.
    
       See:
       - https://stackoverflow.com/questions/28119379/bash-function-to-find-all-git-commits-in-which-a-file-whose-name-matches-a-rege/28120305
       - https://stackoverflow.com/questions/28094136/bash-function-to-search-git-repository-for-a-filename-that-matches-regex/28095750
       - https://stackoverflow.com/questions/372506/how-can-i-search-git-branches-for-a-file-or-directory/372654#372654
    
       The main "git log" line is based on this answer
       - https://stackoverflow.com/a/28119940/2736496
       by Stack Overflow user Greg Bacon
       - https://stackoverflow.com/users/123109/greg-bacon
    
       With thanks to SwankSwashbucklers
       - https://stackoverflow.com/users/2615252/swankswashbucklers
    
       Short description: Stored in GITF_DESC
    COMMENT
    #GITF_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
    GITF_DESC="gitf [glob]: Searches all commits in the current git repository containing a file that has *changed*, whose name matches a glob.\n"
    

    Body:

    gitf()  {
       #Exit if no parameter is provided (if it's the empty string)
          param=$(echo "$1" | trim)
          echo "$param"
          if [ -z "$param" ]  #http://tldp.org/LDP/abs/html/comparison-ops.html
          then
            echo "Required parameter missing. Cancelled"; return
          fi
    
       #https://stackoverflow.com/questions/229551/string-contains-in-bash/229606#229606
       if [[ $param != *"*"* ]]
       then
         param="*$param*"
       fi
    
       echo "Searching for \"$param\"..."
    
       git log -p --name-only --oneline --diff-filter=AMD --branches --tags -- "$param"
    }
    

    Example output:

    $ gitf 05_
    05_
    Searching for "*05_*"...
    14e5cdd Quick save (no message): 01-21-2015__14_36_11
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    2efdeb1 Part four final. Changed auth/tests in post to auth/tests_login_basic.
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    526ca01 Part four final. Renamed auth/tests to test_basic_login, so Java doesn't need to parse the py file in future par
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    7c227f3 Escaped unescaped dollar-signs in initial_script_sh snippet, and added delete-all-but-.git command in comment at
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    e68a30a Part four final, moved post output folder into wordpress_posts.
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    3c5e4ec Part two final. Corrections/minor changes to all posts.
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    3a7dac9 Finished part one.
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    f87540e Initial commit
    non_django_files/wordpress_posts/templates/05_login_remember_me.html
    
    0 讨论(0)
提交回复
热议问题