We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Unicode error: python 2 + merge conflict + non-ascii commit message
The important part of the stack:

```
  File "...python2.7/site-packages/pre_commit/commands/run.py", line 52, in get_filenames
    return getter(include_expr, exclude_expr)
  File "...python2.7/site-packages/pre_commit/util.py", line 46, in wrapper
    ret = wrapper._cache[key] = func(*args)
  File "...python2.7/site-packages/pre_commit/git.py", line 98, in wrapper
    for filename in all_file_list_strategy()
  File "...python2.7/site-packages/pre_commit/util.py", line 46, in wrapper
    ret = wrapper._cache[key] = func(*args)
  File "...python2.7/site-packages/pre_commit/git.py", line 64, in get_conflicted_files
    merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)
  File "...python2.7/site-packages/pre_commit/git.py", line 54, in parse_merge_msg_for_conflicts
    if line.startswith(('\t', '#\t'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 37: ordinal not in range(128)
```

An easy fix: https://github.com/pre-commit/pre-commit/blob/e3b14c35f782ed464e3f96b44e8509048187689f/pre_commit/git.py#L63

--- 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/git.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import functools
4 import logging
5 import os.path
6 import re
7 import sys
8 
9 from pre_commit.errors import FatalError
10 from pre_commit.util import CalledProcessError
11 from pre_commit.util import cmd_output
12 from pre_commit.util import memoize_by_cwd
13 
14 
15 logger = logging.getLogger('pre_commit')
16 
17 
18 def get_root():
19     try:
20         return cmd_output('git', 'rev-parse', '--show-toplevel')[1].strip()
21     except CalledProcessError:
22         raise FatalError(
23             'git failed. Is it installed, and are you in a Git repository '
24             'directory?'
25         )
26 
27 
28 def get_git_dir(git_root):
29     return os.path.normpath(os.path.join(
30         git_root,
31         cmd_output('git', 'rev-parse', '--git-dir', cwd=git_root)[1].strip(),
32     ))
33 
34 
35 def get_remote_url(git_root):
36     ret = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root)[1]
37     return ret.strip()
38 
39 
40 def is_in_merge_conflict():
41     git_dir = get_git_dir('.')
42     return (
43         os.path.exists(os.path.join(git_dir, 'MERGE_MSG')) and
44         os.path.exists(os.path.join(git_dir, 'MERGE_HEAD'))
45     )
46 
47 
48 def parse_merge_msg_for_conflicts(merge_msg):
49     # Conflicted files start with tabs
50     return [
51         line.lstrip('#').strip()
52         for line in merge_msg.splitlines()
53         # '#\t' for git 2.4.1
54         if line.startswith(('\t', '#\t'))
55     ]
56 
57 
58 @memoize_by_cwd
59 def get_conflicted_files():
60     logger.info('Checking merge-conflict files only.')
61     # Need to get the conflicted files from the MERGE_MSG because they could
62     # have resolved the conflict by choosing one side or the other
63     merge_msg = open(os.path.join(get_git_dir('.'), 'MERGE_MSG')).read()
64     merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)
65 
66     # This will get the rest of the changes made after the merge.
67     # If they resolved the merge conflict by choosing a mesh of both sides
68     # this will also include the conflicted files
69     tree_hash = cmd_output('git', 'write-tree')[1].strip()
70     merge_diff_filenames = cmd_output(
71         'git', 'diff', '-m', tree_hash, 'HEAD', 'MERGE_HEAD', '--name-only',
72     )[1].splitlines()
73     return set(merge_conflict_filenames) | set(merge_diff_filenames)
74 
75 
76 @memoize_by_cwd
77 def get_staged_files():
78     return cmd_output(
79         'git', 'diff', '--staged', '--name-only',
80         # Everything except for D
81         '--diff-filter=ACMRTUXB'
82     )[1].splitlines()
83 
84 
85 @memoize_by_cwd
86 def get_all_files():
87     return cmd_output('git', 'ls-files')[1].splitlines()
88 
89 
90 def get_files_matching(all_file_list_strategy):
91     @functools.wraps(all_file_list_strategy)
92     @memoize_by_cwd
93     def wrapper(include_expr, exclude_expr):
94         include_regex = re.compile(include_expr)
95         exclude_regex = re.compile(exclude_expr)
96         return {
97             filename
98             for filename in all_file_list_strategy()
99             if (
100                 include_regex.search(filename) and
101                 not exclude_regex.search(filename) and
102                 os.path.lexists(filename)
103             )
104         }
105     return wrapper
106 
107 
108 get_staged_files_matching = get_files_matching(get_staged_files)
109 get_all_files_matching = get_files_matching(get_all_files)
110 get_conflicted_files_matching = get_files_matching(get_conflicted_files)
111 
112 
113 def check_for_cygwin_mismatch():
114     """See https://github.com/pre-commit/pre-commit/issues/354"""
115     if sys.platform in ('cygwin', 'win32'):  # pragma: no cover (windows)
116         is_cygwin_python = sys.platform == 'cygwin'
117         toplevel = cmd_output('git', 'rev-parse', '--show-toplevel')[1]
118         is_cygwin_git = toplevel.startswith('/')
119 
120         if is_cygwin_python ^ is_cygwin_git:
121             exe_type = {True: '(cygwin)', False: '(windows)'}
122             logger.warn(
123                 'pre-commit has detected a mix of cygwin python / git\n'
124                 'This combination is not supported, it is likely you will '
125                 'receive an error later in the program.\n'
126                 'Make sure to use cygwin git+python while using cygwin\n'
127                 'These can be installed through the cygwin installer.\n'
128                 ' - python {}\n'
129                 ' - git {}\n'.format(
130                     exe_type[is_cygwin_python],
131                     exe_type[is_cygwin_git],
132                 )
133             )
134
```
--- 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/git.py b/pre_commit/git.py
--- a/pre_commit/git.py
+++ b/pre_commit/git.py
@@ -48,10 +48,10 @@
 def parse_merge_msg_for_conflicts(merge_msg):
     # Conflicted files start with tabs
     return [
-        line.lstrip('#').strip()
+        line.lstrip(b'#').strip().decode('UTF-8')
         for line in merge_msg.splitlines()
         # '#\t' for git 2.4.1
-        if line.startswith(('\t', '#\t'))
+        if line.startswith((b'\t', b'#\t'))
     ]
 
 
@@ -60,7 +60,7 @@
     logger.info('Checking merge-conflict files only.')
     # Need to get the conflicted files from the MERGE_MSG because they could
     # have resolved the conflict by choosing one side or the other
-    merge_msg = open(os.path.join(get_git_dir('.'), 'MERGE_MSG')).read()
+    merge_msg = open(os.path.join(get_git_dir('.'), 'MERGE_MSG'), 'rb').read()
     merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)
 
     # This will get the rest of the changes made after the merge.

{"golden_diff": "diff --git a/pre_commit/git.py b/pre_commit/git.py\n--- a/pre_commit/git.py\n+++ b/pre_commit/git.py\n@@ -48,10 +48,10 @@\n def parse_merge_msg_for_conflicts(merge_msg):\n     # Conflicted files start with tabs\n     return [\n-        line.lstrip('#').strip()\n+        line.lstrip(b'#').strip().decode('UTF-8')\n         for line in merge_msg.splitlines()\n         # '#\\t' for git 2.4.1\n-        if line.startswith(('\\t', '#\\t'))\n+        if line.startswith((b'\\t', b'#\\t'))\n     ]\n \n \n@@ -60,7 +60,7 @@\n     logger.info('Checking merge-conflict files only.')\n     # Need to get the conflicted files from the MERGE_MSG because they could\n     # have resolved the conflict by choosing one side or the other\n-    merge_msg = open(os.path.join(get_git_dir('.'), 'MERGE_MSG')).read()\n+    merge_msg = open(os.path.join(get_git_dir('.'), 'MERGE_MSG'), 'rb').read()\n     merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)\n \n     # This will get the rest of the changes made after the merge.\n", "issue": "Unicode error: python 2 + merge conflict + non-ascii commit message\nThe important part of the stack:\r\n\r\n```\r\n  File \"...python2.7/site-packages/pre_commit/commands/run.py\", line 52, in get_filenames\r\n    return getter(include_expr, exclude_expr)\r\n  File \"...python2.7/site-packages/pre_commit/util.py\", line 46, in wrapper\r\n    ret = wrapper._cache[key] = func(*args)\r\n  File \"...python2.7/site-packages/pre_commit/git.py\", line 98, in wrapper\r\n    for filename in all_file_list_strategy()\r\n  File \"...python2.7/site-packages/pre_commit/util.py\", line 46, in wrapper\r\n    ret = wrapper._cache[key] = func(*args)\r\n  File \"...python2.7/site-packages/pre_commit/git.py\", line 64, in get_conflicted_files\r\n    merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)\r\n  File \"...python2.7/site-packages/pre_commit/git.py\", line 54, in parse_merge_msg_for_conflicts\r\n    if line.startswith(('\\t', '#\\t'))\r\nUnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 37: ordinal not in range(128)\r\n```\r\n\r\nAn easy fix: https://github.com/pre-commit/pre-commit/blob/e3b14c35f782ed464e3f96b44e8509048187689f/pre_commit/git.py#L63\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport functools\nimport logging\nimport os.path\nimport re\nimport sys\n\nfrom pre_commit.errors import FatalError\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import memoize_by_cwd\n\n\nlogger = logging.getLogger('pre_commit')\n\n\ndef get_root():\n    try:\n        return cmd_output('git', 'rev-parse', '--show-toplevel')[1].strip()\n    except CalledProcessError:\n        raise FatalError(\n            'git failed. Is it installed, and are you in a Git repository '\n            'directory?'\n        )\n\n\ndef get_git_dir(git_root):\n    return os.path.normpath(os.path.join(\n        git_root,\n        cmd_output('git', 'rev-parse', '--git-dir', cwd=git_root)[1].strip(),\n    ))\n\n\ndef get_remote_url(git_root):\n    ret = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root)[1]\n    return ret.strip()\n\n\ndef is_in_merge_conflict():\n    git_dir = get_git_dir('.')\n    return (\n        os.path.exists(os.path.join(git_dir, 'MERGE_MSG')) and\n        os.path.exists(os.path.join(git_dir, 'MERGE_HEAD'))\n    )\n\n\ndef parse_merge_msg_for_conflicts(merge_msg):\n    # Conflicted files start with tabs\n    return [\n        line.lstrip('#').strip()\n        for line in merge_msg.splitlines()\n        # '#\\t' for git 2.4.1\n        if line.startswith(('\\t', '#\\t'))\n    ]\n\n\n@memoize_by_cwd\ndef get_conflicted_files():\n    logger.info('Checking merge-conflict files only.')\n    # Need to get the conflicted files from the MERGE_MSG because they could\n    # have resolved the conflict by choosing one side or the other\n    merge_msg = open(os.path.join(get_git_dir('.'), 'MERGE_MSG')).read()\n    merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)\n\n    # This will get the rest of the changes made after the merge.\n    # If they resolved the merge conflict by choosing a mesh of both sides\n    # this will also include the conflicted files\n    tree_hash = cmd_output('git', 'write-tree')[1].strip()\n    merge_diff_filenames = cmd_output(\n        'git', 'diff', '-m', tree_hash, 'HEAD', 'MERGE_HEAD', '--name-only',\n    )[1].splitlines()\n    return set(merge_conflict_filenames) | set(merge_diff_filenames)\n\n\n@memoize_by_cwd\ndef get_staged_files():\n    return cmd_output(\n        'git', 'diff', '--staged', '--name-only',\n        # Everything except for D\n        '--diff-filter=ACMRTUXB'\n    )[1].splitlines()\n\n\n@memoize_by_cwd\ndef get_all_files():\n    return cmd_output('git', 'ls-files')[1].splitlines()\n\n\ndef get_files_matching(all_file_list_strategy):\n    @functools.wraps(all_file_list_strategy)\n    @memoize_by_cwd\n    def wrapper(include_expr, exclude_expr):\n        include_regex = re.compile(include_expr)\n        exclude_regex = re.compile(exclude_expr)\n        return {\n            filename\n            for filename in all_file_list_strategy()\n            if (\n                include_regex.search(filename) and\n                not exclude_regex.search(filename) and\n                os.path.lexists(filename)\n            )\n        }\n    return wrapper\n\n\nget_staged_files_matching = get_files_matching(get_staged_files)\nget_all_files_matching = get_files_matching(get_all_files)\nget_conflicted_files_matching = get_files_matching(get_conflicted_files)\n\n\ndef check_for_cygwin_mismatch():\n    \"\"\"See https://github.com/pre-commit/pre-commit/issues/354\"\"\"\n    if sys.platform in ('cygwin', 'win32'):  # pragma: no cover (windows)\n        is_cygwin_python = sys.platform == 'cygwin'\n        toplevel = cmd_output('git', 'rev-parse', '--show-toplevel')[1]\n        is_cygwin_git = toplevel.startswith('/')\n\n        if is_cygwin_python ^ is_cygwin_git:\n            exe_type = {True: '(cygwin)', False: '(windows)'}\n            logger.warn(\n                'pre-commit has detected a mix of cygwin python / git\\n'\n                'This combination is not supported, it is likely you will '\n                'receive an error later in the program.\\n'\n                'Make sure to use cygwin git+python while using cygwin\\n'\n                'These can be installed through the cygwin installer.\\n'\n                ' - python {}\\n'\n                ' - git {}\\n'.format(\n                    exe_type[is_cygwin_python],\n                    exe_type[is_cygwin_git],\n                )\n            )\n", "path": "pre_commit/git.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport functools\nimport logging\nimport os.path\nimport re\nimport sys\n\nfrom pre_commit.errors import FatalError\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import memoize_by_cwd\n\n\nlogger = logging.getLogger('pre_commit')\n\n\ndef get_root():\n    try:\n        return cmd_output('git', 'rev-parse', '--show-toplevel')[1].strip()\n    except CalledProcessError:\n        raise FatalError(\n            'git failed. Is it installed, and are you in a Git repository '\n            'directory?'\n        )\n\n\ndef get_git_dir(git_root):\n    return os.path.normpath(os.path.join(\n        git_root,\n        cmd_output('git', 'rev-parse', '--git-dir', cwd=git_root)[1].strip(),\n    ))\n\n\ndef get_remote_url(git_root):\n    ret = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root)[1]\n    return ret.strip()\n\n\ndef is_in_merge_conflict():\n    git_dir = get_git_dir('.')\n    return (\n        os.path.exists(os.path.join(git_dir, 'MERGE_MSG')) and\n        os.path.exists(os.path.join(git_dir, 'MERGE_HEAD'))\n    )\n\n\ndef parse_merge_msg_for_conflicts(merge_msg):\n    # Conflicted files start with tabs\n    return [\n        line.lstrip(b'#').strip().decode('UTF-8')\n        for line in merge_msg.splitlines()\n        # '#\\t' for git 2.4.1\n        if line.startswith((b'\\t', b'#\\t'))\n    ]\n\n\n@memoize_by_cwd\ndef get_conflicted_files():\n    logger.info('Checking merge-conflict files only.')\n    # Need to get the conflicted files from the MERGE_MSG because they could\n    # have resolved the conflict by choosing one side or the other\n    merge_msg = open(os.path.join(get_git_dir('.'), 'MERGE_MSG'), 'rb').read()\n    merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)\n\n    # This will get the rest of the changes made after the merge.\n    # If they resolved the merge conflict by choosing a mesh of both sides\n    # this will also include the conflicted files\n    tree_hash = cmd_output('git', 'write-tree')[1].strip()\n    merge_diff_filenames = cmd_output(\n        'git', 'diff', '-m', tree_hash, 'HEAD', 'MERGE_HEAD', '--name-only',\n    )[1].splitlines()\n    return set(merge_conflict_filenames) | set(merge_diff_filenames)\n\n\n@memoize_by_cwd\ndef get_staged_files():\n    return cmd_output(\n        'git', 'diff', '--staged', '--name-only',\n        # Everything except for D\n        '--diff-filter=ACMRTUXB'\n    )[1].splitlines()\n\n\n@memoize_by_cwd\ndef get_all_files():\n    return cmd_output('git', 'ls-files')[1].splitlines()\n\n\ndef get_files_matching(all_file_list_strategy):\n    @functools.wraps(all_file_list_strategy)\n    @memoize_by_cwd\n    def wrapper(include_expr, exclude_expr):\n        include_regex = re.compile(include_expr)\n        exclude_regex = re.compile(exclude_expr)\n        return {\n            filename\n            for filename in all_file_list_strategy()\n            if (\n                include_regex.search(filename) and\n                not exclude_regex.search(filename) and\n                os.path.lexists(filename)\n            )\n        }\n    return wrapper\n\n\nget_staged_files_matching = get_files_matching(get_staged_files)\nget_all_files_matching = get_files_matching(get_all_files)\nget_conflicted_files_matching = get_files_matching(get_conflicted_files)\n\n\ndef check_for_cygwin_mismatch():\n    \"\"\"See https://github.com/pre-commit/pre-commit/issues/354\"\"\"\n    if sys.platform in ('cygwin', 'win32'):  # pragma: no cover (windows)\n        is_cygwin_python = sys.platform == 'cygwin'\n        toplevel = cmd_output('git', 'rev-parse', '--show-toplevel')[1]\n        is_cygwin_git = toplevel.startswith('/')\n\n        if is_cygwin_python ^ is_cygwin_git:\n            exe_type = {True: '(cygwin)', False: '(windows)'}\n            logger.warn(\n                'pre-commit has detected a mix of cygwin python / git\\n'\n                'This combination is not supported, it is likely you will '\n                'receive an error later in the program.\\n'\n                'Make sure to use cygwin git+python while using cygwin\\n'\n                'These can be installed through the cygwin installer.\\n'\n                ' - python {}\\n'\n                ' - git {}\\n'.format(\n                    exe_type[is_cygwin_python],\n                    exe_type[is_cygwin_git],\n                )\n            )\n", "path": "pre_commit/git.py"}]}