Repository: pre-commit/pre-commit

Issue:
Not stashing changes before installing
Hi,

I'm regularly running into this situation: I have pending changes, I run `git commit -a`, and pre-commit tries to install its hooks:

```
[INFO] Initializing environment for git://github.com/pre-commit/pre-commit-hooks.
An unexpected error has occurred: CalledProcessError: Command: ['git', 'checkout', 'd3db0385825d4c082bc7117c090ac16cb4840f3e']
Return code: 1
Expected return code: 0
Output: (none)
Errors: 
    error: Your local changes to the following files would be overwritten by checkout:
        .pre-commit-config.yaml
        .travis.yml
        CHANGELOG
        README.md
        hooks.yaml
        pre_commit_hooks/autopep8_wrapper.py
        pre_commit_hooks/check_json.py
        pre_commit_hooks/check_yaml.py
        pre_commit_hooks/debug_statement_hook.py
        pre_commit_hooks/end_of_file_fixer.py
        pre_commit_hooks/tests_should_end_in_test.py
        pre_commit_hooks/trailing_whitespace_fixer.py
        pre_commit_hooks/util.py
        pylintrc
        requirements-dev.txt
        setup.py
        testing/util.py
        tests/autopep8_wrapper_test.py
        tests/debug_statement_hook_test.py
        tests/end_of_file_fixer_test.py
        tests/tests_should_end_in_test_test.py
        tests/trailing_whitespace_fixer_test.py
        tests/util_test.py
        tox.ini
    Please, commit your changes or stash them before you can switch branches.
    Aborting


Check the log at ~/.pre-commit/pre-commit.log
```

The log contents are 

```
An unexpected error has occurred: CalledProcessError: Command: ['git', 'checkout', 'd3db0385825d4c082bc7117c090ac16cb4840f3e']
Return code: 1
Expected return code: 0
Output: (none)
Errors: 
    error: Your local changes to the following files would be overwritten by checkout:
        .pre-commit-config.yaml
        .travis.yml
        CHANGELOG
        README.md
        hooks.yaml
        pre_commit_hooks/autopep8_wrapper.py
        pre_commit_hooks/check_json.py
        pre_commit_hooks/check_yaml.py
        pre_commit_hooks/debug_statement_hook.py
        pre_commit_hooks/end_of_file_fixer.py
        pre_commit_hooks/tests_should_end_in_test.py
        pre_commit_hooks/trailing_whitespace_fixer.py
        pre_commit_hooks/util.py
        pylintrc
        requirements-dev.txt
        setup.py
        testing/util.py
        tests/autopep8_wrapper_test.py
        tests/debug_statement_hook_test.py
        tests/end_of_file_fixer_test.py
        tests/tests_should_end_in_test_test.py
        tests/trailing_whitespace_fixer_test.py
        tests/util_test.py
        tox.ini
    Please, commit your changes or stash them before you can switch branches.
    Aborting


Traceback (most recent call last):
  File "/home/qdm/workspace/web/pre-commit/pre_commit/error_handler.py", line 34, in error_handler
    yield
  File "/home/qdm/workspace/web/pre-commit/pre_commit/main.py", line 129, in main
    return run(runner, args)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/commands/run.py", line 165, in run
    return _run_hooks(runner, args, write=write, environ=environ)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/commands/run.py", line 115, in _run_hooks
    for repo in runner.repositories:
  File "/usr/lib/python3.4/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/runner.py", line 43, in repositories
    repository.require_installed()
  File "/home/qdm/workspace/web/pre-commit/pre_commit/repository.py", line 64, in require_installed
    self.install()
  File "/home/qdm/workspace/web/pre-commit/pre_commit/repository.py", line 78, in install
    for language_name, _ in self.languages
  File "/usr/lib/python3.4/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/repository.py", line 41, in languages
    for _, hook in self.hooks
  File "/usr/lib/python3.4/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/repository.py", line 49, in hooks
    for hook in self.repo_config['hooks']
  File "/home/qdm/workspace/web/pre-commit/pre_commit/repository.py", line 49, in <genexpr>
    for hook in self.repo_config['hooks']
  File "/usr/lib/python3.4/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/manifest.py", line 24, in hooks
    return dict((hook['id'], hook) for hook in self.manifest_contents)
  File "/usr/lib/python3.4/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/manifest.py", line 18, in manifest_contents
    self.repo_path_getter.repo_path, C.MANIFEST_FILE,
  File "/usr/lib/python3.4/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/store.py", line 46, in repo_path
    return self._store.clone(self._repo, self._sha)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/store.py", line 119, in clone
    cmd_output('git', 'checkout', sha)
  File "/home/qdm/workspace/web/pre-commit/pre_commit/util.py", line 160, in cmd_output
    returncode, cmd, retcode, output=(stdout, stderr),
pre_commit.util.CalledProcessError: Command: ['git', 'checkout', 'd3db0385825d4c082bc7117c090ac16cb4840f3e']
Return code: 1
Expected return code: 0
Output: (none)
Errors: 
    error: Your local changes to the following files would be overwritten by checkout:
        .pre-commit-config.yaml
        .travis.yml
        CHANGELOG
        README.md
        hooks.yaml
        pre_commit_hooks/autopep8_wrapper.py
        pre_commit_hooks/check_json.py
        pre_commit_hooks/check_yaml.py
        pre_commit_hooks/debug_statement_hook.py
        pre_commit_hooks/end_of_file_fixer.py
        pre_commit_hooks/tests_should_end_in_test.py
        pre_commit_hooks/trailing_whitespace_fixer.py
        pre_commit_hooks/util.py
        pylintrc
        requirements-dev.txt
        setup.py
        testing/util.py
        tests/autopep8_wrapper_test.py
        tests/debug_statement_hook_test.py
        tests/end_of_file_fixer_test.py
        tests/tests_should_end_in_test_test.py
        tests/trailing_whitespace_fixer_test.py
        tests/util_test.py
        tox.ini
    Please, commit your changes or stash them before you can switch branches.
    Aborting
```

I think this is a regression from a previous version, it was more seamless then.



Discussion:
Hmmm that is odd!

Can you supply the following:

```
$ git --version
$ pre-commit --version
```

And potentially can you cd to that directory and see what `git status` is?  (The directory might be hard to find... hmm...)

You can find it by doing the following:

```
$ sqlite3 ~/.pre-commit/db.db 'SELECT path FROM repos WHERE repo = "git url for repo" AND ref = "sha you are using"'
```

Also I'm curious if `pre-commit clean` will fix it (obviously not a solution as I'd like to prevent getting into this situation).

I have some ideas on how to fix it if it's just that git changed how `--no-checkout` + `checkout` works

```
$ git --version
git version 2.3.3
hub version 2.2.0
$ pre-commit --version
pre-commit 0.4.2
```

`pre-commit clean` does not fix it.
My `~/.pre-commit/db.db` file has no repos…

Currently building git from source, I imagine this is a git change :/

Sounds like a good place to look, after a short investigation, my teammates who are on git 2.3 have encountered this issue as well. 

Can you cat `/etc/gitconfig` and `~/.gitconfig` ?

`/etc/gitconfig` does not exist.
`~/.gitconfig` contents:

```
[user]
        name = Quentin de Metz
        email = quentin.de-metz@pricematch.travel
[credential]
        helper = cache --timeout=3600
[push]
        default = current
[help]
        autocorrect = 1
[branch]
        autosetuprebase = never
[color]
  branch = auto
  diff = auto
  status = auto

[color "branch"]
  current = yellow reverse
  local = yellow
  remote = green

[color "diff"]
  meta = yellow bold
  frag = magenta bold
  old = red bold
  new = green bold

[color "status"]
  added = yellow
  changed = green
  untracked = cyan
[tag]
        sort = version:refname
```


Resolving patch:
diff --git a/pre_commit/store.py b/pre_commit/store.py
--- a/pre_commit/store.py
+++ b/pre_commit/store.py
@@ -116,7 +116,7 @@ def clone(self, url, sha):
         with clean_path_on_failure(dir):
             cmd_output('git', 'clone', '--no-checkout', url, dir)
             with cwd(dir):
-                cmd_output('git', 'checkout', sha)
+                cmd_output('git', 'reset', sha, '--hard')
 
         # Update our db with the created repo
         with sqlite3.connect(self.db_path) as db:


Test patch: