简体   繁体   中英

Git diff call in pre-commit throws “fatal: unable to read [SHA1]”

I am working in windows and attempting to run a git diff command in the pre-commit script (Python) of a repository. My Python call looks like this:

repo_dir = 'D:/git/current_uic/src/gtc/resource'
cmd = ['diff', '--name-only']
print(Popen(['git', '--git-dir={}'.format(repo_dir + '/.git'), 
             '--work-tree={}'.format(repo_dir)] + cmd,
            stdin=PIPE, stdout=PIPE).communicate())

Whenever I go to commit in the "D:/git/current_uic/src/gtc" repo, I get the following:

fatal: unable to read 6ff96bd371691b9e93520e133ebc4d84c74cd0f6

Note that this is a pre-commit hook for the 'D:/git/current_uic/src/gtc' repository and that 'D:/git/current_uic/src/gtc/resource' is a submodule of 'D:/git/current_uic/src/gtc'. Also note that if I pop open Git bash and run the following:

git --git-dir=D:/git/current_uic/src/gtc/resource/.git 
    --work-tree=D:/git/current_uic/src/gtc/resource diff --name-only

or if I just run the script straight from Git bash I get exactly what I want, regardless of working directory.

Any ideas as to what is going on here?

The Problem:

Upon running a hook, Git sets some environment variables that are accessible by the hook script. The problem is that Git itself uses these environment variables, and the normal way in which Git sets/uses them seems to be overridden by the values set when the hook gets fired off. In this particular instance, the environment variable GIT_INDEX_FILE has been set to the path to the index file corresponding to the repository which had called the hook (D:/git/current_uic/src/.git/modules/gtc/index), causing a mismatch between the (incorrect) index and the (correct) change tree.

The Fix:

In the hook script, set the environment variable GIT_INDEX_FILE to the correct value before making any git calls. In this case, you could do the following:

set GIT_INDEX_FILE=D:/git/current_uic/src/.git/modules/gtc/modules/resource/index
git --git-dir=D:/git/current_uic/src/gtc/resource/.git 
    --work-tree=D:/git/current_uic/src/gtc/resource diff --name-only

Additional Info

More information about these Git environment variables and which hooks set them can be found here .

Got exactly same issue but using gitpython . I solved it like this:

repo = git.Repo()
for submodule in repo.submodules:
    back_index = os.getenv('GIT_INDEX_FILE')
    os.environ['GIT_INDEX_FILE'] = submodule.module().index.path
    commit = submodule.module().head.commit
    print([item.a_path for item in commit.diff(None)])
    os.environ['GIT_INDEX_FILE'] = back_index

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM