绕过预提交钩子以进行合并提交

30

我设置了一些Git钩子来在 pre-commit 时运行一些 Gulp 命令。 我基本上运行 jshint/plato。 我基本上希望在两种情况下绕过这些钩子:

  1. hotfix 分支(master/hotfix)
  2. git merge(或找到一种不会在合并提交时崩溃的方法)

Plato Gulp 命令对源代码进行分析,并生成一个 /reports/ 目录,跟踪时间复杂度。 如果我们在 hotfix 分支上执行此操作,将导致将其合并回开发中时出现合并冲突。 这里是简单的钩子:

#!/bin/sh

if git diff --cached --name-only --diff-filter=ACM | grep '.js$' >/dev/null 2>&1
then
  git stash -q --keep-index
  ./node_modules/.bin/gulp jshint
  RESULT=$?
  git stash pop -q
  [ $RESULT -ne 0 ] && exit 1
  git stash -q --keep-index
  ./node_modules/.bin/gulp plato
  git add report/
  git stash pop -q
fi

exit 0

现在的问题是,如果我在“reports”上有合并冲突,我解决了合并所有冲突都已解决,但您仍在合并中。然后提交它运行分析并暂存提交,当提交时它会抛出错误:

/Users/Nix/work/project/.git/modules/somesubmodule/MERGE_HEAD'无法读取:没有这样的文件或目录。

该目录确实存在,但没有合并头...

3个回答

39

所以我刚刚找到了一个命令,我认为可以用来检测“merge_head”

 git rev-parse -q --verify MERGE_HEAD

如果rev-parse返回一个哈希值,那意味着我们当前处于合并状态。我可以使用它来绕过这个逻辑。但我会等待更有经验的人给出更好的建议。


适用于我。谢谢! - EM0
2
如果您正在进行变基操作,可以使用以下命令完成相同的操作:git rev-parse -q --verify REBASE_HEAD - Daan
抱歉问一个新手问题,但我们如何获得完全相反的效果?即,如果我们想在合并状态下出错。 - Flavio Wuensche
对于在合并时跳过:(git rev-parse -q --verify MERGE_HEAD) || (skip_this_if_merging)。对于在合并时运行:(git rev-parse -q --verify MERGE_HEAD) && (only_run_this_if_merging) - unforgiven1987
很奇怪,但是即使在rebase完成后,git rev-parse -q --verify REBASE_HEAD的结果仍然为true。 我尝试了(git rev-parse -q --verify MERGE_HEAD || git rev-parse -q --verify REBASE_HEAD) || (skip_this_if_merging_or_rebasing) - Harry Burns

4
如在此相关答案中提到的,您可以测试$GIT_DIR/MERGE_HEAD是否存在来检测合并提交:
以下是您可以获得的内容:
- 如果您使用git commit --amend来修改合并提交,则预提交钩子会像往常一样运行,但它实际上无法检测到这一点。新提交将是一个合并提交,但您无法确定。 - 如果您使用普通的git commit创建非合并提交,则git目录中将不存在MERGE_HEAD文件,并且您可以确定这不会创建合并提交。 - 如果您使用git commit完成冲突合并,则MERGE_HEAD文件将存在,并且您可以确定这将创建合并提交。 - 如果您运行git merge并且它自己成功,则会创建一个新的提交而不使用预提交钩子,因此您甚至不会在此处调用。
因此,如果您愿意允许对合并使用git commit --amend,则可以接近您想要的结果:只需测试是否存在$GIT_DIR/MERGE_HEAD,以查看这是否是完成冲突合并的git commit。(使用$GIT_DIR的技巧可以使其即使在git树之外运行命令也能正常工作。Git设置$GIT_DIR以便在钩子中运行的git命令能够正常工作。)

0
########################
# Setup Some Variables #
########################

REPO_ROOT_REL=$( git rev-parse --show-toplevel )
REPO_ROOT="$( cd "$REPO_ROOT_REL" >/dev/null 2>&1 ; pwd -P )"

####################################################
# Check for merge or rebase commit and abort if so #
####################################################

set +e
MERGE_HASH=$( git rev-parse -q --verify MERGE_HEAD 2> /dev/null)
set -e
if [ ! -z "$MERGE_HASH" ]; then
    echo "This appears to be a merge commit ($MERGE_HASH). Avoiding pre-commit steps."
    echo ""
    echo "EXITING ${0##*/}"
    exit 1
fi

REBASE_APPLY_PATH="${REPO_ROOT}/.git/rebase-apply"
REBASE_MERGE_PATH="${REPO_ROOT}/.git/rebase-merge"
if [ -e "${REBASE_APPLY_PATH}" ] || [ -e "${REBASE_MERGE_PATH}" ]; then
    echo "This appears to be a rebase commit (.git/rebase-apply or .git/rebase-merge exists). Avoiding pre-commit steps."
    echo ""
    echo "EXITING ${0##*/}"
    exit 1
fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接