You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何git-revert不触发pre-commit和commit-msg钩子?

Why git-revert Doesn’t Trigger the Same Hooks as git-commit

Great question—this is one of those subtle Git design choices that often catches folks off guard, especially when you’re building hook-based workflows like the one you’re working on (blocking merge commit reverts, which are indeed tricky!). Let’s break this down:

First, confirm your observation is correct

You’re right: git-revert only triggers the prepare-commit-msg and post-commit hooks, while git-commit runs all four: pre-commit, prepare-commit-msg, commit-msg, and post-commit.

Why Git does this

Git’s hook behavior here boils down to two core design principles:

  1. Revert is treated as an automated, "safe" operation
    Git sees git-revert as a predictable, machine-generated commit—it’s not a user-initiated commit where you’re writing custom code or crafting a unique message. The pre-commit hook is meant to validate user-written changes (like running linters, tests, or code checks), and commit-msg validates user-authored messages. Since revert’s changes are auto-generated to undo a specific commit, and its message is standardized (Revert "Original commit message"), Git skips these hooks to avoid unnecessary friction.

  2. Avoid breaking automated workflows
    Many teams use pre-commit hooks that enforce strict code rules. If git-revert triggered these hooks, it could fail for reasons unrelated to the revert itself—for example, the revert might reintroduce code that was previously flagged by a linter, but that’s intentional (you’re undoing a change). Git wants revert operations to be reliable and unblocked by user-defined checks that aren’t relevant to its purpose.

How to block merge commit reverts (your use case)

Since git-revert skips the hooks you’d normally use for validation, you’ll need to use a different hook type to enforce this rule:

If you want to block these reverts before they reach your remote repository, server-side hooks are the way to go. These run on the server whenever someone pushes code, so they enforce the rule for everyone on the team.

Here’s a simplified bash example for a pre-receive hook:

#!/bin/bash

# Loop through each push reference
while read oldrev newrev refname; do
    # Check every commit being pushed
    git rev-list "$oldrev..$newrev" | while read commit; do
        # Get the commit message
        commit_msg=$(git log --format=%B -n1 "$commit")
        
        # Check if it's a revert commit
        if [[ "$commit_msg" == "Revert "* ]]; then
            # Extract the original commit being reverted
            reverted_commit_subject=$(echo "$commit_msg" | grep -oP 'Revert "\K[^"]+')
            reverted_commit=$(git rev-parse "$reverted_commit_subject" 2>/dev/null)
            
            # If the reverted commit exists, check if it's a merge commit (>=2 parents)
            if [[ -n "$reverted_commit" ]]; then
                parent_count=$(git log --format=%P -n1 "$reverted_commit" | wc -w)
                if [[ "$parent_count" -ge 2 ]]; then
                    echo "ERROR: Reverting merge commits is prohibited. Commit $commit reverts merge commit $reverted_commit."
                    exit 1
                fi
            fi
        fi
    done
done

exit 0

Option 2: Client-side pre-push hook

If you want to catch this locally before anyone pushes, a pre-push hook works similarly. It runs right before git push and can abort the push if it detects a merge revert commit. The logic is nearly identical to the pre-receive example—just adjust it to check the commits you’re about to push.

Avoid modifying git-revert itself

You could technically create a custom alias for git revert that runs pre-commit and commit-msg hooks manually before calling the real git-revert, but this is fragile. It breaks Git’s default behavior, won’t work consistently across team members, and could cause unexpected issues with other tools that rely on standard Git hook behavior.


内容的提问来源于stack exchange,提问作者Gnustavo

火山引擎 最新活动