为什么这个干净的过滤器在第一次运行时被忽略?



为了在提交时自动使.sh文件可执行,我做了一个干净的过滤器,并对其结果感到困惑。

首先,我跑git config filter.executable.clean 'chmod +x %f'.这会将以下节添加到我的测试存储库的.git/config文件中:

[filter "executable"]
clean = chmod +x %f

接下来,我创建了一个.gitattributes文件:

*.sh    filter=executable

让我们看看它是如何表现的。当然,新创建的.sh文件是不可执行的:

$ touch foo.sh
$ ls -l foo.sh
-rw-r--r-- foo.sh

如果我们add它,我们的干净过滤器应该运行。但这会导致我们的工作目录中有一个可执行文件,在我们的暂存区域中有一个不可执行的文件,以及一个脏的工作副本!

$ git add foo.sh
$ ls -l foo.sh  # As expected
-rwxr-xr-x foo.sh
$ git ls-files -s foo.sh  # Confusing
100644 foo.sh
$ git status  # Confusing
Changes to be committed:
new file: foo.sh
Changes not staged for commit:
modified: foo.sh

再次运行git add会在暂存区域中生成可执行文件和干净的工作副本:

$ git add foo.sh
$ git ls-files -s foo.sh
10755 foo.sh
$ git status
Changes to be committed:
new file: foo.sh

这是怎么回事?

Git 的过滤器必须从 STDIN 获取输入并将其输出发送到 STDOUT:

签出时,当指定smudge命令时,该命令将从其标准输入提供给 blob 对象,其标准输出用于更新工作树文件。同样,clean命令用于在检入时转换工作树文件的内容。

上面显示的筛选器不会以这种方式运行。它忽略 STDIN,并且不向 STDOUT 发送任何输出,因此第一个git add命令不会捕获其效果。暂存文件不可执行。

但是,筛选器确实运行。这会产生在工作副本中的文件上添加执行位的副作用。git status看到文件的权限已更改。

第二个git add捕获可执行位,但不直接因为我们的过滤器。它只是暂存它在工作副本中看到的权限更改。

我不知道有什么方法可以通过 STDIN 和 STDOUT 修改文件的权限。在干净和污迹过滤器中修改文件权限可能非常困难。

相关内容

  • 没有找到相关文章

最新更新