阿猫的博客

阿猫的博客

通过 git pre-commit hook 防止误提交二进制文件

2025-09-05

在开发 Go 的时候经常不小心把二进制 commit 上去(顺手就 gaa 了),虽然有几个不太靠谱的方法似乎能避免,例如

  • 把二进制的名称放进 .gitignore,仅限项目有 Makefile 的时候可能好用,换个名就完蛋。
  • 如果 git add 的时候耗时特别长,应该发觉完蛋。
  • 提交前通过 git status 好好看看 stage。

提交错了怎么处理这里就不展开叙述,反正就是很麻烦,会把仓库撑大,简单删除不行,要递归删除,还会搞乱提交历史,然后覆盖远端,非常麻烦。

但是我们可以通过 pre-commit hook 来检测 stage 里是否有二进制文件,并且在检测到时给出指引如何去掉二进制文件。

修改项目中 .git/hooks/pre-commit 为以下内容即可。

#!/bin/sh

# Function to detect binary files
detect_binaries() {
    echo "Checking for binary files..."

    # Get list of files to be committed (cached/staged files)
    files_to_commit=$(git diff --cached --name-only --diff-filter=A)

    if [ -z "$files_to_commit" ]; then
        return 0
    fi

    binary_files=""

    # Check each file
    for file in $files_to_commit; do
        if [ -f "$file" ]; then
            # Use file command to detect binary files
            if file "$file" | grep -q "binary\|executable\|ELF\|PE32\|Mach-O"; then
                binary_files="$binary_files $file"
            fi

            # Also check for common binary file extensions
            case "$file" in
                *.exe|*.dll|*.so|*.dylib|*.a|*.o|*.bin|*.class|*.jar|*.war|*.ear|*.pyc|*.pyo|*.pyd)
                    binary_files="$binary_files $file"
                    ;;
            esac
        fi
    done

    if [ -n "$binary_files" ]; then
        echo "ERROR: Binary files detected in commit:"
        for file in $binary_files; do
            echo "  - $file"
        done
        echo ""
        echo "To remove these files from staging:"
        for file in $binary_files; do
            echo "  git reset HEAD '$file'"
        done
        echo ""
        echo "Consider adding these patterns to .gitignore to prevent future commits."
        return 1
    fi

    return 0
}

# Check for binary files first
detect_binaries
if [ $? -ne 0 ]; then
    echo "Pre-commit hook failed: Binary files detected."
    exit 1
fi

效果如下