为什么第一次运行时会忽略此清洁过滤器?

时间:2017-08-16 14:25:47

标签: git gitattributes

为了在提交时自动使.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

这里发生了什么?

1 个答案:

答案 0 :(得分:0)

Git的过滤器必须take their input from STDIN and send their output to STDOUT

  

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

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

但是,过滤器运行。这具有在工作副本中的文件上添加执行位的副作用。 git status发现该文件的权限已更改。

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

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