如何删除Git历史提交中的old mode 100644 new mode 100755权限变更记录
Git 清理历史提交中仅文件权限变更记录的方法
前置操作
- 先配置当前仓库忽略文件权限变更,避免后续操作再次产生同类无效记录:
git config core.filemode false - 提前创建备份分支,防止操作失误导致代码丢失:
git branch backup_pre_cleanup
方法1:交互式Rebase处理(适合清理连续的本地未推送提交)
如果你需要清理的是当前HEAD往前的70个连续提交,且这些提交还没有推送到远程仓库,可直接用带exec参数的交互式rebase自动批量处理:
git rebase -i HEAD~70 --exec 'git reset --soft HEAD^ && git diff --cached --no-perms | git apply --cached && git commit -C HEAD@{1} --allow-empty-files'
该命令的执行逻辑:
- 逐个取出最近70个提交进行处理
- 软回滚到上一个提交,将当前提交的所有改动保留在暂存区
- 导出不含权限变更的代码改动补丁,重新加载到暂存区,自动过滤掉仅修改权限的内容
- 用原提交的提交信息重新生成提交,如果原提交只有权限变更,该次提交会被自动跳过
如果你的提交链中包含合并提交,可在rebase命令中添加-r参数保留合并结构:
git rebase -r -i HEAD~70 --exec 'git reset --soft HEAD^ && git diff --cached --no-perms | git apply --cached && git commit -C HEAD@{1} --allow-empty-files'
方法2:filter-repo全量清理(适合清理全仓库历史的权限变更记录)
如果你需要清理仓库所有历史提交中的权限变更内容,使用Git官方推荐的git filter-repo工具(Git 2.22及以上版本默认集成):
- 先创建当前仓库的裸克隆,避免污染工作目录:
git clone --bare /你的/仓库/本地/路径 tmp_clean_repo cd tmp_clean_repo
- 执行全量过滤命令,统一文件权限,自动跳过仅修改权限的空提交:
git filter-repo --tree-filter ' for file in $(git ls-files); do # 普通文件统一设为644,需要保留执行权限的脚本可在此处添加例外规则 if [[ $file =~ \.(sh|py|pl)$ ]]; then chmod 755 "$file" else chmod 644 "$file" fi done ' --commit-callback ' if not commit.file_changes: commit.skip() '
- 处理完成后,用tmp_clean_repo替换原有仓库的
.git目录,或直接推送到远程仓库即可。
校验与回滚
处理完成后可执行git log -p查看提交日志,确认已无仅权限变更的无效记录,代码内容与清理前完全一致。
如果操作过程中出现问题,可直接回滚到备份分支:git reset --hard backup_pre_cleanup
内容的提问来源于stack exchange,提问作者Archive VEGA
相关产品推荐
相关产品推荐

