排除 .gitignore 中包含特定文件的目录

Exclude directories in .gitignore which contain a particular file

当在 OpenModelica 中删除包(例如 Examples)时,不会删除基础目录。相反,目录 Examples 包含一个名为 package.bak-mo 的文件,以指示不再使用该目录。所以保留了一个备份。如果文件 package.bak-mo 存在于文件夹中,则该文件夹及其文件应从 git 提交过程中排除。

├── Sub1
│   └── package.mo
│   └── package.order
│   └── Examples
│       └── package.bak-mo
│       └── otherfile.mo
│       └── package.order
├── Sub2
│   └── package.mo
│   └── package.order
│   └── Demo
│       └── otherfile.mo
│       └── package.mo
│       └── package.order

在此示例中,应从 git 提交中排除以下目录和文件:

│   └── Examples
│       └── package.bak-mo
│       └── otherfile.mo
│       └── package.order

所有其他文件和目录仍应包含在可能的 git 提交中。

注意:此问题由https://trac.openmodelica.org/OpenModelica/ticket/4854

触发

我不知道如何让它工作。这里有什么想法吗?

gitignore pattern format 无法做到这一点,它基本上是一种稍微扩展的 globbing 语法(据我所知)。

另外,请注意 已经提交但随后与忽略模式匹配的文件仍保留在存储库 中,如 this note 所解释的那样。要停止跟踪当前正在跟踪的文件,您必须使用 git rm --cached.

因此,您可能无法避免使用 shell 脚本或类似 git hook 实现您想要的东西。

这可以通过 pre-commit 挂钩来完成。创建挂钩 运行

$ touch .git/hooks/pre-commit  
$ chmod a+x .git/hooks/pre-commit   

添加以下代码

#!/bin/bash
path_with_pattern=$(git diff --cached --find-copies --find-renames --name-only --diff-filter=ACR | grep "\.bak-mo$")
if [[ -n $path_with_pattern  ]];
then
  for path in $path_with_pattern; do
    folder=$(echo $path | sed 's/\/[^\/]*\.bak-mo$//')
    echo "Found OpenModelica backup folder: $folder"
    git reset HEAD $folder
    echo "Unstaged: $folder"
    rm -rf $folder  # Consider adding some confirmation here (use at your own risk)
    echo "Removed: $folder"
    # or safer option add to .gitignore instead of removing
    # echo $folder >> .gitignore
  done
fi

注意:此代码需要更多测试我没有按需要测试此代码(仅针对您提供的示例)