5

I commit import pdb;pdb.set_trace() quite often.

Is there a convenient way of preventing me doing it?

I use emacs/git (magit).

eugene
  • 39,839
  • 68
  • 255
  • 489
  • 2
    Good example of how to do this. Almost the same use case, but with a ruby app. http://stackoverflow.com/questions/20278573/git-pre-commit-hook – David Nehme Jan 23 '14 at 02:18
  • Similar question: http://stackoverflow.com/questions/11560336/magit-how-to-see-pre-commit-hooks-before-editing-commit-log and implementation of hooks in Magit: https://github.com/vanicat/magit/commit/87ec17c46b156c8508a47aa6c9ba982ef8a61b4c – Ehvince Jan 23 '14 at 12:30

3 Answers3

4

For completeness, here's how to examine the contents of the version in the index, building off eugene's answer and with a few more changes (not tested as a complete hook, but should work):

#!/bin/sh

has_import=false
git diff --cached --no-renames --name-status --diff-filter=AM |
  while read st file; do
    case "$file" in
    *.py)
        if git show ":$file" |
          grep -E "^[^#]*\bimport[[:space:]]+pdb\b"; then
            echo "$file: has import pdb"
            exit 1
        fi;;
    esac
done || has_import=true

if $has_import; then
    exit 1
fi

The most important bit of change is the git show ":$file" trick, which uses git show to extract the staged version from the index.

I also:

  • added --no-renames to make renamed files show up as Added (dealing with R is harder, might as well just treat them as new);
  • removed C as it would fail if it triggered (because the "other" file name is also printed, just as for Renames, but I think it will not trigger here anyway);
  • removed some bash-specific syntax by using case; and
  • beefed up the grep expression a bit (it's still not perfect, you could do from pdb import ..., or more likely, something like import collections, pdb, which it would not catch; but now it handles multiple spaces after import, and avoids false hits on, e.g., import pdbase).
  • per Matthieu Moy's comment, beefed up the shell fragment to set a has_import variable you can use later. (If you don't intend to use anything later you can eliminate the variable and use exit 1 there directly, as he suggested.)

(This still has at least one minor flaw: the extracted file-contents do not have any smudge filters applied. But if your smudge and clean filters add and remove import lines, I suspect there's nothing a pre-commit hook can to do help you. :-) )

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
  • There's something fragile about this code: you're running "exit 1" on the right-hand side of a pipe, hence in a subshell. As a result, this "exit 1" won't quite the whole shell, but only the subshell. If you add anything after the last line, then the line will still be executed (and the return status of the subshell may be ignored). I'dd add a `|| exit 1` after the `done` keyword. – Matthieu Moy Apr 30 '15 at 14:11
  • @MatthieuMoy: good point, modified the example (slightly differently in case the user wants to go on to do other checks even in the case of detecting an import). – torek Apr 30 '15 at 19:44
  • fyi: the issue actually occured http://stackoverflow.com/questions/29969093/exit-1-in-pre-commit-doesnt-abort-git-commit/29972489#29972489 – Matthieu Moy Apr 30 '15 at 20:10
1

You can create .git/hooks/pre-commit

#!/bin/bash

git diff --cached --name-status --diff-filter=ACM | while read st file; do
    if [[ "$file" =~ .py$ ]] && grep "^[^#]*import pdb" "$file"; then
        echo "$file: has import pdb"
        exit 1
    fi
done

I just made it up. not sure if it's good enough for general use but works for me.

Thanks David

eugene
  • 39,839
  • 68
  • 255
  • 489
  • Not perfect (the grep checks the working directory version of the file, while the `git diff --cached` more properly looks at the staged, to-be-committed version) but will work as long as you don't let the staged and to-be-committed versions diverge. – torek Jan 23 '14 at 09:33
0

python3 -m pip install pre-commit (or use pipx)

cd my_repo

Create a file called .pre-commit-config.yaml with the following contents

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.0.1
    hooks:
    -   id: debug-statements

Run pre-commit install

The next time you run git commit it will fail with

(random) mark@DESKTOP:~/pytest-bdd$ git commit -am "Adding breakpoint"
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
Debug Statements (Python)................................................Failed
- hook id: debug-statements
- exit code: 1

setup.py:2:0 - pdb imported

And it will not allow you to commit until breakpoint() or import pdb is removed from the commit.

Note: if you just remove import pdb but not pdb.set_trace() e.g if you're in a rush and forget, it wont complain - but instead you now have introduced a syntax error.

See https://pre-commit.com for more information

See https://pre-commit.com/hooks.html for more hooks

Mark
  • 1,337
  • 23
  • 34