You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Git脚本删除分支.env文件后切换分支无法检测到其他分支.env问题

问题

我写了一段Bash脚本,用来移除项目所有分支里的.env文件。执行脚本时,第一个分支能找到并删除.env文件,但切换到其他确实存在.env文件的分支后,脚本却检测不到这些文件。附上脚本代码:

#!/bin/bash
function remove_env() {
    if [[ -z $1 ]];then
        echo "Require at least one argument, check help"
        exit 1
    fi
    if [[ $1 == "-h" ]];then
        echo "./env-remover.sh \"<path to the env file>\" -f (optional force everything)"
        exit 1
    fi
    filepath=$1
    remote=$(git config --get remote.origin.url)
    branch=$(git rev-parse --abbrev-ref HEAD)
    if [[ -z $2 ]];then
        git filter-repo --path $filepath --invert-paths
        git remote add origin $remote
        git push --set-upstream origin $branch --force
    elif [[ $2 == "-f" ]];then
        git filter-repo --path $filepath --invert-paths --force
        git remote add origin $remote
        git push --set-upstream origin $branch --force
    else
        echo "Bad syntax"
        exit 1
    fi
}

force=""

if [ -n $1 ] && [ "$1" == "-f" ]; then
    force="-f"
    echo "Force enabled"
fi


for branch in $(git for-each-ref --format='%(refname:short)'); do
    true_branch_name=$(echo $branch | sed -e 's/\origin\///g')
    git checkout -f $true_branch_name > /dev/null
    env_file=$(find . -type f -name ".env" ! -path "./front-web/*" ! -path "./area_api/node_modules/*" | cut -c 3-) # there is only 1 .env so I don't need to parse multiple responses
    if [ -z $env_file ]; then
        echo -e "\e[32mno .env in $true_branch_name\e[0m"
    else
        echo -e "\e[31m\e[1m\e[4m.env founded at $env_file in $true_branch_name\e[0m"
        remove_env $env_file $force
    fi
done
原因分析
  1. git filter-repo破坏分支引用:git filter-repo会重写仓库的所有历史提交,包括所有分支的历史记录。你脚本一开始通过git for-each-ref获取的分支列表是重写前的旧引用,第一次执行filter-repo后,仓库分支结构已完全改变,后续循环里checkout的分支是无效的旧引用,自然找不到原本存在的.env文件。
  2. 错误的分支循环逻辑:git filter-repo一次执行就会处理所有分支的历史,不需要逐个分支循环处理。重复执行反而会破坏仓库结构,导致后续分支操作异常。
  3. 冗余的Remote操作:每次执行filter-repo会自动移除remote,脚本重复执行git remote add origin $remote会导致remote重复添加,且每次只push当前分支,其他分支的修改无法同步到远程。
修复方案

不需要循环切换分支,直接用git filter-repo一次性处理所有分支历史,移除指定路径的.env文件后同步所有分支到远程。修复后的脚本如下:

#!/bin/bash

# 处理强制参数
force=""
if [[ "$1" == "-f" ]]; then
    force="--force"
    echo "Force mode enabled"
fi

# 保存远程仓库地址
remote=$(git config --get remote.origin.url)
if [[ -z $remote ]]; then
    echo "Error: No remote origin found"
    exit 1
fi

# 定义需要排除的路径(避免误删指定目录下的.env)
exclude_paths=(
    "./front-web/*"
    "./area_api/node_modules/*"
)

# 构建find命令的排除参数
find_args=()
for path in "${exclude_paths[@]}"; do
    find_args+=(! -path "$path")
done

# 查找所有需要移除的.env文件
env_files=$(find . -type f -name ".env" "${find_args[@]}")

if [[ -z $env_files ]]; then
    echo "No .env files found in the repository"
    exit 0
fi

# 遍历移除每个.env文件的所有历史记录
for env_file in $env_files; do
    # 去掉路径开头的./,适配filter-repo的路径格式
    clean_path=${env_file#./}
    echo "Removing $clean_path from all branch histories..."
    git filter-repo --path "$clean_path" --invert-paths $force
done

# 重新添加远程仓库
git remote add origin "$remote"

# 推送所有分支和标签到远程(强制覆盖,因为历史已重写)
echo "Pushing all updated branches to remote..."
git push origin --all --force
git push origin --tags --force

echo "All .env files have been removed from all branches"
关键改动说明
  • 移除了循环切换分支的逻辑,利用git filter-repo的特性一次性处理所有分支历史,这是工具的正确用法。
  • 批量查找所有需要删除的.env文件,避免遗漏。
  • 执行完历史重写后,一次性推送所有分支和标签,确保远程仓库同步所有修改。
  • 优化参数处理和错误判断,提升脚本稳定性。

注意:git filter-repo会彻底重写仓库历史,执行前务必备份仓库,同时通知所有协作成员重新clone仓库(不能用git pull拉取更新)。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:45:32