git filter不是'unmodifying'文件

时间:2017-06-01 10:38:51

标签: git sed git-filter

我正在使用IDE,它在一些生成但强烈需要的库文件中生成一个版本。因此,如果我想使用具有多个版本的库,或者我看到一大堆实际上毫无意义的更改,则会出现问题。

摘要:我想忽略一个或多个文件的单个行,我认为git的过滤器是正确的方法。我能够grep没有问题的相关行,因为人们可能会看到进一步阅读。

长话短说,我设置了一个git过滤器来恢复对头文件中版本的任何修改。 (请注意,此文件中可能有不同的修改。)

[filter "ignore-version"]
    smudge = cat %f || cat
    clean  = git ls-files %f --error-unmatch >&- 2>&- \
              && sed \"/version/c $(git show HEAD:%f | grep version)\" || cat

(为了更好的阅读,我添加了转义换行符并更改了单词以便简单匹配。在原始版本中没有可能的冲突。)

  1. git ls-files检查文件是否已存储在存储库中(当前 HEAD
  2. 1.1如果存在,sed将执行肮脏的工作以用已经跟踪的一行替换整行

    1.2如果没有,cat将不做任何事情,只能继续(这应该确保一个尚未跟踪的文件不会丢失)

    到目前为止,它有效。 (我可以接受以下事实:过滤器将所有 CRLF 静默转换为 LF ...)

    问题:固定文件被​​git标记为已修改,尽管存储库的最新文件和已过滤的版本是二进制相等的。我使用 kdiff 作为单独的工具进行了检查。

    编辑1 :这是一些显示两个文件版本相等的输出:

    $ git show HEAD:file.txt | md5sum
    9f95c28cebe4f45b8efb7b0ae64dfa56
    $ cat file.txt | md5sum
    894e7d1b28180b7a193bf3cdd6ceaacb
    $ cat file.txt | git ls-files file.txt --error-unmatch >&- 2>&- \
                  && sed \"/version/c $(git show HEAD:file.txt | grep version)\" 
                  || cat | md5sum
    9f95c28cebe4f45b8efb7b0ae64dfa56
    

    编辑2:此外,差异的输出......

    $ git diff file.txt
    warning: LF will be replaced by CRLF in file.txt.
    The file will have its original line endings in your working directory.
    

    请注意,此文件的签入版本仅包含 LF ,就像之前的提交一样。另请注意,设置core.autocrlf true ,除了.gitattributes文件中的过滤器规范外,没有任何其他内容。

1 个答案:

答案 0 :(得分:4)

Finally, I solved it. The file of question was in a strange state, it seems like the checked out version had unix style line endings which is not right regarding the git configuration (check out windows style, commit unix style). After staging this particular file it was instantly removed from staging area without any mention and is now considered unchanged. So I think git cleaned the working directory file during staging (line endings) and now it works.

Sorry for the noise.


Steps to completly check the problem:

git init
echo "version=0.1" > file.txt
echo "*.txt filter=ignore-version" > .gitattributes
git config --local filter.ignore-version.clean 'git ls-files %f --error-unmatch >&- 2>&- \
    && sed -b "/version/c $(git show HEAD:%f | grep version)" || cat'
git config --local filter.ignore-version.smudge 'cat %f || cat'
git add file.txt .gitattributes
git commit -m "initial commit"
# -----
echo "version=0.2" > file.txt
git status

Status should not report any changes. It worked for me using bare repositories on both, Linux and Windows.