Git hook to reject commits where files contain a specific string

前端 未结 3 502
花落未央
花落未央 2020-12-16 16:37

I am using Guard with Rspec; I use focus: true to force it run only tests I am working on. But sometimes I forget to remove focu

相关标签:
3条回答
  • 2020-12-16 17:16

    Building off the existing answers, here is the version I am using with support for multiple strings.

    #!/bin/sh
    
    declare -a arr=("This is the first string." "This is the second string.")
    
    for i in "${arr[@]}"
    do
        git diff --cached --name-only | xargs grep --with-filename -n $i && echo "COMMIT REJECTED! Found '$i' references. Please remove them before commiting." && exit 1
    done
    
    exit 0
    
    0 讨论(0)
  • 2020-12-16 17:32

    Server-Side Git Hooks

    I came up with this example for the use case of code formatting, but pretty much if you just replace the usage of Prettier with grep -r 'bad-thing' it should work as well:

    ref_name=$1
    new_rev=$3
    
    # only check branches, not tags or bare commits
    if [ -z $(echo $ref_name | grep "refs/heads/") ]; then
      exit 0
    fi
    
    # don't check empty branches
    if [ "$(expr "${new_rev}" : '0*$')" -ne 0 ]; then
      exit 0
    fi
    
    # Checkout a copy of the branch (but also changes HEAD)
    my_work_tree=$(mktemp -d -t git-work-tree.XXXXXXXX) 2>/dev/null
    git --work-tree="${my_work_tree}" --git-dir="." checkout $new_rev -f >/dev/null
    
    # Do the formatter check
    echo "Checking code formatting..."
    pushd ${my_work_tree} >/dev/null
    prettier './**/*.{js,css,html,json,md}' --list-different
    my_status=$?
    popd >/dev/null
    
    # reset HEAD to master, and cleanup
    git --work-tree="${my_work_tree}" --git-dir="." checkout master -f >/dev/null
    rm -rf "${my_work_tree}"
    
    # handle error, if any
    if [ "0" != "$my_status" ]; then
      echo "Please format the files listed above and re-commit."
      echo "(and don't forget your .prettierrc, if you have one)"
      exit 1
    fi
    

    There are some limitations to this, so I'd recommend taking a look at the "more complete" version as well:

    • Reject Ugly Commits with Server-Side Git Hooks

    The Gist of it...

    If you want to do this server-side you'll be working with a bare repository (most likely), so you have to do a little bit of extra work to create a temporary place to check things out (as shown above).

    Basically, this is the process:

    • use a server-side update hook (similar to pre-receive)
    • inspect the branch and commit
    • checkout the bare repo to a temp folder
    • run the check for specific string (grep -r 'bad-thing' .)
    • exit non-zero if there are offending files

    And I would have adjusted the script to do the greping, but it's late (or rather very early) and I don't trust myself to not make a typo that breaks everything in trying to make a "simple" change. I know that the above works (because I've used it), so I'll leave at that.

    HTH (not the OP per se, but others in the future - and perhaps myself again)

    0 讨论(0)
  • 2020-12-16 17:33

    A good source of information is the book at git-scm.

    You want the pre-commit hook. To return a non-zero value (and thus abort the commit), you'd want something along these lines:

    FILES_PATTERN='\.rb(\..+)?$'
    FORBIDDEN='focus: true'
    git diff --cached --name-only | \
      grep -spec/ | \
      grep -E $FILES_PATTERN | \
      xargs grep --with-filename -n $FORBIDDEN && echo "COMMIT REJECTED Found '$FORBIDDEN' references. Please remove them before commiting" && exit 1
    

    That's lifted from this rather good tips site. I haven't tested the tweaks I made.

    0 讨论(0)
提交回复
热议问题