【问题标题】:git clone different repository in git hooks creating troublegit 在 git hooks 中克隆不同的存储库会造成麻烦
【发布时间】:2018-03-13 06:52:29
【问题描述】:

我们有一个特定的要求,我们必须推送所有到达以提交到某个分支的文件。

我们计划通过 git hooks 特别是 commit-msg hook 来实现这一点。

这样做时,我们将分支克隆到临时位置(/tmp/),然后在 git commit-msg 挂钩中,尝试将到达的文件提交到某个分支。

但是现在我们看到 /tmp/ 中的所有文件都已删除。

粗略的 commit-msg 脚本如下:-

#!/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

这可能是什么根本原因?

编辑:

GIT_INDEX_FILE 显示提交开始的索引文件的路径,而不是 /tmp/ 路径。有没有办法改变这个变量? 索引文件也会打印类似 next-index-32419.lock 的内容。 问候

【问题讨论】:

  • Hooks 在特殊环境中运行,通常设置了各种 Git 环境变量。因此,编写可以在其他地方运行完全通用的 Git 命令的钩子是很棘手的。确保您知道$GIT_DIR$GIT_INDEX_FILE 的设置(如果有的话)以及如果它们设置了您应该怎么做。阅读 Git 如何使用索引。
  • 好的@torek,让我看看你的建议。问候
  • 似乎是问题所在。 GIT_INDEX_FILE 显示启动提交的索引文件的路径,而不是 /tmp/ 路径。有没有办法改变这个变量?
  • 是的,您可以更改或取消设置环境变量,您需要这样做才能处理其他存储库中的提交。但是您需要保持变量不变以处理原始存储库中的未决提交(要提交的文件不一定是工作树中的文件)。
  • 尝试git --work-tree=$(pwd) pull,然后设置GIT_WORK_TREE=$(pwd)

标签: git commit githooks pre-commit-hook pre-commit


【解决方案1】:

每当钩子更改文件夹时,检查以下值很重要:

  • GIT_DIR(在您的情况下应该引用正确的 .git repo 文件夹)
  • GIT_WORK_TREE(应该引用预期的文件夹)

这就是为什么对于任何 Git 命令,您都需要将 git 替换为:

git --work-tree=$(pwd) ...

(或/path/to/your/working/tree

【讨论】:

  • 感谢您的建议。我会检查并回复你。
【解决方案2】:

我在开发 pre-commit(将 git 挂钩作为可安装的 git 存储库分发)时遇到了同样的问题。

GIT_* 环境变量干扰了git clone 命令。这些环境变量在调用.git/hooks/pre-commit 脚​​本之前由git 内部设置。

我对此的解决方案是清除所有 GIT_* 环境变量(允许变量的白名单除外)。

My solution 在 python 中,但您可以将其调整为您正在编写的任何语言:

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'}
    }

【讨论】:

    【解决方案3】:

    我只想在干净的环境中执行我的git 命令。现在的问题是如何做到这一点?

    $ 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>
    

    所以使用-i 会给你的 git 命令一个干净的环境。但是您可能需要某些变量才能存在。所以我会在下面添加到我的脚本顶部

    alias git='env -i PATH=$PATH HOME=$HOME git'
    

    现在,您在钩子中运行的所有 git 命令都不会继承运行提交钩子的环境

    【讨论】:

    • 感谢您的建议。我会检查并回复你。
    • 它似乎不起作用。别名 git='env -i PATH=$PATH HOME=$HOME git' REPOSRC="git-codecommit.eu-west-1.amazonaws.com/repo" LOCALREPO="auto_merge_test_repo" project_dir="/tmp/""$LOCALREPO" cd /tmp && git clone "${REPOSRC }"
    • 然后当我 cd 进入 /tmp/auto_merge_test_repo 我看到变更集 WRT 到 git 存储库的提交位置
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 2017-12-29
    • 2016-08-15
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多