pre-commit: Stashed changes lost if hook fails

I’ve run into this particular (in my eyes, critical) bug. If I want to do a partial commit, e.g. I have 2 files but I only add 1 file to the staging area and the staged file will cause a hook to fail, I loose the changes in the 2nd file because pre-commit fails to reroll the patch it stashed before running.

Here’s my terminal log and the steps to reproduce:

Version

$ pre-commit -V pre-commit 0.3.0

Commands to reproduce

$ cat unstaged.py
"""I am unstaged"""
$ echo "'''I am unstaged, but I have changes'''" > unstaged.py
$ echo "x = 'This is the loooooooooooooooooooooooooooooooooooongest liiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiine eveeeeeeeeer'" > foo.py 
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   unstaged.py
    modified:   foo.py

no changes added to commit (use "git add" and/or "git commit -a")
$ git add foo.py 
$ git commit -m "Adding a long line"
[WARNING] Unstaged files detected.
[INFO] Stashing unstaged files to /home/k/.pre-commit/patch1412683352.
Flake8...............................................Failed
hookid: flake8

foo.py:1:80: E501 line too long (112 > 79 characters)

[WARNING] Stashed changes conflicted with hook auto-fixes... Rolling back fixes...
An unexpected error has occurred: CalledProcessError: Command: [u'git', u'apply', u'/home/k/.pre-commit/patch1412683352']
Return code: 128
Expected return code: 0
Output: (u'', u'fatal: unrecognized input\n')

Check the log at ~/.pre-commit/pre-commit.log
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   foo.py

$ echo "x = 'This is a shorter line, its better'" > foo.py
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   foo.py

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   foo.py

$ git add foo.py 
$ git commit -m "Fixed the error I got from the flake8 hook"
Flake8...............................................Passed
[master 78568e8] Fixed the error I got from the flake8 hook
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch master
nothing to commit, working directory clean
$ cat unstaged.py
"""I am unstaged"""

Log

$ cat ~/.pre-commit/pre-commit.log
Traceback (most recent call last):
  File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/error_handler.py", line 34, in error_handler
    yield
  File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/main.py", line 108, in main
    return run(runner, args)
  File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/commands/run.py", line 151, in run
    return _run_hooks(runner, args, write=write, environ=environ)
  File "/usr/lib/python2.7/contextlib.py", line 24, in __exit__
    self.gen.next()
  File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/staged_files_only.py", line 55, in staged_files_only
    cmd_runner.run(['git', 'apply', patch_filename])
  File "/home/k/.virtualenvs/pre-commit-test/local/lib/python2.7/site-packages/pre_commit/prefixed_command_runner.py", line 82, in run
    returncode, replaced_cmd, retcode, output=(stdout, stderr),
CalledProcessError: Command: [u'git', u'apply', u'/home/k/.pre-commit/patch1412683352']
Return code: 128
Expected return code: 0
Output: (u'', u'fatal: unrecognized input\n')

.pre-commit-config.yaml

$ cat .pre-commit-config.yaml 
- repo: git@github.com:pre-commit/pre-commit-hooks
  sha: 6343700aa063fe30acc319d2dc84353a35a3d6d0
  hooks:
  - id: flake8
    args: ['--ignore=E712,F821']

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Comments: 22 (11 by maintainers)

Commits related to this issue

Most upvoted comments

thank you. For future people that have the same problem:

Step 1: Checkout to the commit before you ran into the problem via

git checkout `your_commit_number`

Step 2: Run git apply using the path named in the pre-commit log.

git apply `path_to_cache`

Then all the changes will be restored again.