We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Occasional flakiness of staged file stasher
It appears `git diff-files` is returning incorrectly in some case that I haven't been able to pinpoint.

It results in something like this (you can see however that all the files are staged):

```
$ pre-commit 
[WARNING] Unstaged files detected.
Stashing unstaged files to /home/anthony/workspace/pre-commit/.pre-commit-files/patch1397370090.
Trim Trailing Whitespace............................................Passed
Fix End of Files....................................................Passed
Check Yaml..........................................................Passed
Debug Statements (Python)...........................................Passed
Tests should end in _test.py........................................Passed
Pyflakes............................................................Passed
Validate Pre-Commit Config..........................................Passed
Validate Pre-Commit Manifest........................................Passed
[WARNING] Stashed changes conflicted with hook auto-fixes... Rolling back fixes...
Traceback (most recent call last):
  File "/home/anthony/workspace/pre-commit/venv-pre_commit/bin/pre-commit", line 9, in <module>
    load_entry_point('pre-commit==0.0.0', 'console_scripts', 'pre-commit')()
  File "/home/anthony/workspace/pre-commit/pre_commit/util.py", line 52, in wrapper
    return func(argv)
  File "/home/anthony/workspace/pre-commit/pre_commit/run.py", line 143, in run
    return _run(runner, args)
  File "/home/anthony/workspace/pre-commit/pre_commit/run.py", line 95, in _run
    return run_hooks(runner, args)
  File "/usr/lib/python2.7/contextlib.py", line 24, in __exit__
    self.gen.next()
  File "/home/anthony/workspace/pre-commit/pre_commit/staged_files_only.py", line 51, in staged_files_only
    cmd_runner.run(['git', 'apply', patch_filename])
  File "/home/anthony/workspace/pre-commit/pre_commit/prefixed_command_runner.py", line 67, in run
    returncode, replaced_cmd, retcode, output=(stdout, stderr),
pre_commit.prefixed_command_runner.CalledProcessError: Command: ['git', 'apply', '/home/anthony/workspace/pre-commit/.pre-commit-files/patch1397370090']
Return code: 128
Expected return code: 0
Output: ('', 'fatal: unrecognized input\n')
$ git status
# On branch rebuild_venv
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   .gitignore
#   modified:   Makefile
#
```

The "stashed diff" is an empty file.  I think the "fix" is to check if the diff contains anything before printing the warning message and entering the branch that isn't a noop context manager.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pre_commit/staged_files_only.py`
Content:
```
1 import contextlib
2 import logging
3 import time
4 
5 from pre_commit.prefixed_command_runner import CalledProcessError
6 
7 
8 logger = logging.getLogger('pre_commit')
9 
10 
11 @contextlib.contextmanager
12 def staged_files_only(cmd_runner):
13     """Clear any unstaged changes from the git working directory inside this
14     context.
15 
16     Args:
17         cmd_runner - PrefixedCommandRunner
18     """
19     # Determine if there are unstaged files
20     retcode, _, _ = cmd_runner.run(
21         ['git', 'diff-files', '--quiet'],
22         retcode=None,
23     )
24     if retcode:
25         patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))
26         logger.warning('Unstaged files detected.')
27         logger.info(
28             'Stashing unstaged files to {0}.'.format(patch_filename),
29         )
30         # Save the current unstaged changes as a patch
31         with open(patch_filename, 'w') as patch_file:
32             cmd_runner.run(['git', 'diff', '--binary'], stdout=patch_file)
33 
34         # Clear the working directory of unstaged changes
35         cmd_runner.run(['git', 'checkout', '--', '.'])
36         try:
37             yield
38         finally:
39             # Try to apply the patch we saved
40             try:
41                 cmd_runner.run(['git', 'apply', patch_filename])
42             except CalledProcessError:
43                 logger.warning(
44                     'Stashed changes conflicted with hook auto-fixes... '
45                     'Rolling back fixes...'
46                 )
47                 # We failed to apply the patch, presumably due to fixes made
48                 # by hooks.
49                 # Roll back the changes made by hooks.
50                 cmd_runner.run(['git', 'checkout', '--', '.'])
51                 cmd_runner.run(['git', 'apply', patch_filename])
52             logger.info('Restored changes from {0}.'.format(patch_filename))
53     else:
54         # There weren't any staged files so we don't need to do anything
55         # special
56         yield
57
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pre_commit/staged_files_only.py b/pre_commit/staged_files_only.py
--- a/pre_commit/staged_files_only.py
+++ b/pre_commit/staged_files_only.py
@@ -17,11 +17,11 @@
         cmd_runner - PrefixedCommandRunner
     """
     # Determine if there are unstaged files
-    retcode, _, _ = cmd_runner.run(
-        ['git', 'diff-files', '--quiet'],
+    retcode, diff_stdout, _ = cmd_runner.run(
+        ['git', 'diff', '--ignore-submodules', '--binary', '--exit-code'],
         retcode=None,
     )
-    if retcode:
+    if retcode and diff_stdout.strip():
         patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))
         logger.warning('Unstaged files detected.')
         logger.info(
@@ -29,7 +29,7 @@
         )
         # Save the current unstaged changes as a patch
         with open(patch_filename, 'w') as patch_file:
-            cmd_runner.run(['git', 'diff', '--binary'], stdout=patch_file)
+            patch_file.write(diff_stdout)
 
         # Clear the working directory of unstaged changes
         cmd_runner.run(['git', 'checkout', '--', '.'])

{"golden_diff": "diff --git a/pre_commit/staged_files_only.py b/pre_commit/staged_files_only.py\n--- a/pre_commit/staged_files_only.py\n+++ b/pre_commit/staged_files_only.py\n@@ -17,11 +17,11 @@\n         cmd_runner - PrefixedCommandRunner\n     \"\"\"\n     # Determine if there are unstaged files\n-    retcode, _, _ = cmd_runner.run(\n-        ['git', 'diff-files', '--quiet'],\n+    retcode, diff_stdout, _ = cmd_runner.run(\n+        ['git', 'diff', '--ignore-submodules', '--binary', '--exit-code'],\n         retcode=None,\n     )\n-    if retcode:\n+    if retcode and diff_stdout.strip():\n         patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))\n         logger.warning('Unstaged files detected.')\n         logger.info(\n@@ -29,7 +29,7 @@\n         )\n         # Save the current unstaged changes as a patch\n         with open(patch_filename, 'w') as patch_file:\n-            cmd_runner.run(['git', 'diff', '--binary'], stdout=patch_file)\n+            patch_file.write(diff_stdout)\n \n         # Clear the working directory of unstaged changes\n         cmd_runner.run(['git', 'checkout', '--', '.'])\n", "issue": "Occasional flakiness of staged file stasher\nIt appears `git diff-files` is returning incorrectly in some case that I haven't been able to pinpoint.\n\nIt results in something like this (you can see however that all the files are staged):\n\n```\n$ pre-commit \n[WARNING] Unstaged files detected.\nStashing unstaged files to /home/anthony/workspace/pre-commit/.pre-commit-files/patch1397370090.\nTrim Trailing Whitespace............................................Passed\nFix End of Files....................................................Passed\nCheck Yaml..........................................................Passed\nDebug Statements (Python)...........................................Passed\nTests should end in _test.py........................................Passed\nPyflakes............................................................Passed\nValidate Pre-Commit Config..........................................Passed\nValidate Pre-Commit Manifest........................................Passed\n[WARNING] Stashed changes conflicted with hook auto-fixes... Rolling back fixes...\nTraceback (most recent call last):\n  File \"/home/anthony/workspace/pre-commit/venv-pre_commit/bin/pre-commit\", line 9, in <module>\n    load_entry_point('pre-commit==0.0.0', 'console_scripts', 'pre-commit')()\n  File \"/home/anthony/workspace/pre-commit/pre_commit/util.py\", line 52, in wrapper\n    return func(argv)\n  File \"/home/anthony/workspace/pre-commit/pre_commit/run.py\", line 143, in run\n    return _run(runner, args)\n  File \"/home/anthony/workspace/pre-commit/pre_commit/run.py\", line 95, in _run\n    return run_hooks(runner, args)\n  File \"/usr/lib/python2.7/contextlib.py\", line 24, in __exit__\n    self.gen.next()\n  File \"/home/anthony/workspace/pre-commit/pre_commit/staged_files_only.py\", line 51, in staged_files_only\n    cmd_runner.run(['git', 'apply', patch_filename])\n  File \"/home/anthony/workspace/pre-commit/pre_commit/prefixed_command_runner.py\", line 67, in run\n    returncode, replaced_cmd, retcode, output=(stdout, stderr),\npre_commit.prefixed_command_runner.CalledProcessError: Command: ['git', 'apply', '/home/anthony/workspace/pre-commit/.pre-commit-files/patch1397370090']\nReturn code: 128\nExpected return code: 0\nOutput: ('', 'fatal: unrecognized input\\n')\n$ git status\n# On branch rebuild_venv\n# Changes to be committed:\n#   (use \"git reset HEAD <file>...\" to unstage)\n#\n#   modified:   .gitignore\n#   modified:   Makefile\n#\n```\n\nThe \"stashed diff\" is an empty file.  I think the \"fix\" is to check if the diff contains anything before printing the warning message and entering the branch that isn't a noop context manager.\n\n", "before_files": [{"content": "import contextlib\nimport logging\nimport time\n\nfrom pre_commit.prefixed_command_runner import CalledProcessError\n\n\nlogger = logging.getLogger('pre_commit')\n\n\n@contextlib.contextmanager\ndef staged_files_only(cmd_runner):\n    \"\"\"Clear any unstaged changes from the git working directory inside this\n    context.\n\n    Args:\n        cmd_runner - PrefixedCommandRunner\n    \"\"\"\n    # Determine if there are unstaged files\n    retcode, _, _ = cmd_runner.run(\n        ['git', 'diff-files', '--quiet'],\n        retcode=None,\n    )\n    if retcode:\n        patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))\n        logger.warning('Unstaged files detected.')\n        logger.info(\n            'Stashing unstaged files to {0}.'.format(patch_filename),\n        )\n        # Save the current unstaged changes as a patch\n        with open(patch_filename, 'w') as patch_file:\n            cmd_runner.run(['git', 'diff', '--binary'], stdout=patch_file)\n\n        # Clear the working directory of unstaged changes\n        cmd_runner.run(['git', 'checkout', '--', '.'])\n        try:\n            yield\n        finally:\n            # Try to apply the patch we saved\n            try:\n                cmd_runner.run(['git', 'apply', patch_filename])\n            except CalledProcessError:\n                logger.warning(\n                    'Stashed changes conflicted with hook auto-fixes... '\n                    'Rolling back fixes...'\n                )\n                # We failed to apply the patch, presumably due to fixes made\n                # by hooks.\n                # Roll back the changes made by hooks.\n                cmd_runner.run(['git', 'checkout', '--', '.'])\n                cmd_runner.run(['git', 'apply', patch_filename])\n            logger.info('Restored changes from {0}.'.format(patch_filename))\n    else:\n        # There weren't any staged files so we don't need to do anything\n        # special\n        yield\n", "path": "pre_commit/staged_files_only.py"}], "after_files": [{"content": "import contextlib\nimport logging\nimport time\n\nfrom pre_commit.prefixed_command_runner import CalledProcessError\n\n\nlogger = logging.getLogger('pre_commit')\n\n\n@contextlib.contextmanager\ndef staged_files_only(cmd_runner):\n    \"\"\"Clear any unstaged changes from the git working directory inside this\n    context.\n\n    Args:\n        cmd_runner - PrefixedCommandRunner\n    \"\"\"\n    # Determine if there are unstaged files\n    retcode, diff_stdout, _ = cmd_runner.run(\n        ['git', 'diff', '--ignore-submodules', '--binary', '--exit-code'],\n        retcode=None,\n    )\n    if retcode and diff_stdout.strip():\n        patch_filename = cmd_runner.path('patch{0}'.format(int(time.time())))\n        logger.warning('Unstaged files detected.')\n        logger.info(\n            'Stashing unstaged files to {0}.'.format(patch_filename),\n        )\n        # Save the current unstaged changes as a patch\n        with open(patch_filename, 'w') as patch_file:\n            patch_file.write(diff_stdout)\n\n        # Clear the working directory of unstaged changes\n        cmd_runner.run(['git', 'checkout', '--', '.'])\n        try:\n            yield\n        finally:\n            # Try to apply the patch we saved\n            try:\n                cmd_runner.run(['git', 'apply', patch_filename])\n            except CalledProcessError:\n                logger.warning(\n                    'Stashed changes conflicted with hook auto-fixes... '\n                    'Rolling back fixes...'\n                )\n                # We failed to apply the patch, presumably due to fixes made\n                # by hooks.\n                # Roll back the changes made by hooks.\n                cmd_runner.run(['git', 'checkout', '--', '.'])\n                cmd_runner.run(['git', 'apply', patch_filename])\n            logger.info('Restored changes from {0}.'.format(patch_filename))\n    else:\n        # There weren't any staged files so we don't need to do anything\n        # special\n        yield\n", "path": "pre_commit/staged_files_only.py"}]}