Reputation: 4364
We have a specific requirement in which we have to push all files which arrive for being committed to a certain branch.
We are planning to achieve this via git hooks specifically commit-msg hook.
While doing so what we do is we clone branch to temporary location (/tmp/) and then in git commit-msg hook, attempt to commit arrived files to certain branch.
But what happens now is we see all files as deleted in /tmp/.
Crude commit-msg script is as under:-
#!/bin/bash
#
#!/usr/bin/env bash
#git config credential.helper store
REPOSRC="https://<USER>:<PASS>@<REPO_URL>"
LOCALREPO="<LOCAL_REPO_DIR>"
echo "Pulling code to temporarry location";
cd /tmp && git clone "${REPOSRC}" || (cd "${LOCALREPO}"; git pull;)
#here when I navigate to /tmp/<LOCALREPO> all files are listed as DELETED
git diff --cached --name-status | while read st file; do
echo "file == $file and status == $st";
if [ "$st" == "A" ]; then
cd "${LOCALREPO}" && git add "$file" && git commit "$file" -m "$COMMIT_MSG" && git push origin "$branch"
else
cd "${LOCALREPO}" && git commit "$file" -m "$COMMIT_MSG" && git push origin "$branch"
fi
done
What can be the root cause for this?
EDIT:
GIT_INDEX_FILE shows path of index file from which commit was initiated and not /tmp/ path. Is there any way to change this variable? Also index file prints something like next-index-32419.lock. Regards
Upvotes: 8
Views: 1763
Reputation: 69964
I ran into this same issue while developing pre-commit (which distributes git hooks as installable git
repositories).
The GIT_*
environment variables are interfering with the git clone
commands. These environment variables are set by git
internals before invoking the .git/hooks/pre-commit
script.
My solution to this was to clear all GIT_*
environment variables (except for a whitelist of allowed variables).
My solution is in python but you can probably adapt it into whatever language you're writing in:
def no_git_env(_env=None):
# Too many bugs dealing with environment variables and GIT:
# https://github.com/pre-commit/pre-commit/issues/300
# In git 2.6.3 (maybe others), git exports GIT_WORK_TREE while running
# pre-commit hooks
# In git 1.9.1 (maybe others), git exports GIT_DIR and GIT_INDEX_FILE
# while running pre-commit hooks in submodules.
# GIT_DIR: Causes git clone to clone wrong thing
# GIT_INDEX_FILE: Causes 'error invalid object ...' during commit
_env = _env if _env is not None else os.environ
return {
k: v for k, v in _env.items()
if not k.startswith('GIT_') or
k in {'GIT_EXEC_PATH', 'GIT_SSH', 'GIT_SSH_COMMAND'}
}
Upvotes: 1
Reputation: 146530
I would just simply execute my git
commands in a clean environment. Now the question is how to do that?
$ env --help | grep env
Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
Set each NAME to VALUE in the environment and run COMMAND.
-i, --ignore-environment start with an empty environment
-u, --unset=NAME remove variable from the environment
A mere - implies -i. If no COMMAND, print the resulting environment.
Full documentation at: <http://www.gnu.org/software/coreutils/env>
So using a -i
would give your git command a clean environment. But you might need certain variables to exists. So I would just add below to the top of my script
alias git='env -i PATH=$PATH HOME=$HOME git'
Now all the git commands your run in your hook will not inherit the environment which the commit hook was run with
Upvotes: 0
Reputation: 1324935
Whenever a hook changes folder, it is important to check the value of:
GIT_DIR
(which should reference the right .git repo folder in your case)GIT_WORK_TREE
(which should not reference the expected folder)That is why, for any Git command, you would need to replace git
with:
git --work-tree=$(pwd) ...
(or /path/to/your/working/tree
)
Upvotes: 5