Git 属性

大约 5 分钟

# Git 属性

Git 属性是针对特定的路径配置的设置项。通过使用属性,你可以对项目中的文件或目录单独定义不同的合并策略,让 Git 知道怎样比较非文本文件,或者让 Git 在提交或检出前过滤内容。

Git 的 gitattributes 文件是一个文本文件,文件中的一行定义一个路径的若干个属性。

可以在 .git/info/attributes 文件中进行设置,也可以在项目根目录建立 .gitattributes 文件。配置的属性格式如下:

要匹配的文件模式 属性1 属性2 ...

例子:https://www.cnblogs.com/qiqi715/p/9286468.html (opens new window)

gitattributes文件示例:

*           text=auto
*.txt		text
*.jpg		-text
*.vcproj	text eol=crlf
*.sh		text eol=lf
*.py		eol=lf

说明:

  • 第1行,对任何文件,设置 text=auto,表示文件的行尾自动转换。如果是文本文件,则在文件入 Git 库时,行尾自动转换为 LF。如果已经在入 Git 库中的文件的行尾为 CRLF,则该文件在入 Git 库时,不再转换为 LF
  • 第2行,对于 txt 文件,标记为文本文件,并进行行尾规范化。
  • 第3行,对于 jpg 文件,标记为非文本文件,不进行任何的行尾转换。
  • 第4行,对于 vcproj 文件,标记为文本文件,在文件入 Git 库时进行规范化,即行尾为 LF。但是在检出到工作目录时,行尾自动转换为 CRLF
  • 第5行,对于 sh 文件,标记为文本文件,在文件入 Git 库时进行规范化,即行尾为 LF。在检出到工作目录时,行尾也不会转换为 CRLF(即保持 LF)。
  • 第6行,对于 py 文件,只针对工作目录中的文件,行尾为 LF

在一个 Git 库中可以有多个 gitattributes 文件,不同 gitattributes 文件中,属性设置的优先级(从高到低):

  • /myproj/info/attributes 文件
  • /myproj/my_path/.gitattributes 文件
  • /myproj/.gitattributes 文件

同一个 gitattributes 文件中,按照行的先后顺序,如果一个文件的某个属性被多次设置,则后序的设置优先。

# 关键字展开

Git 属性提供了一种方法,让我们可以编写自己的过滤器来实现文件提交或检出时的关键字替换。 一个过滤器由“clean”和“smudge”两个子过滤器组成。 在 .gitattributes 文件中,你能对特定的路径设置一个过滤器,然后设置文件检出前的处理脚本(“smudge”)和文件暂存前的处理脚本(“clean”)。

# 利用命令 clean , smudge

在(Git 源码中)实现这个特性的原始提交信息里给出了一个简单的例子:在提交前,用 indent 程序过滤所有 C 源码。 你可以在 .gitattributes 文件中对 filter 属性设置“indent”过滤器来过滤 *.c 文件

*.c filter=indent

然后,通过以下配置,让 Git 知道“indent”过滤器在 smudge 和 clean 时分别该做什么:

$ git config --global filter.indent.clean indent
$ git config --global filter.indent.smudge cat

在这个例子中,当你暂存 *.c 文件时,indent 程序会先被触发;在把它们检出回硬盘时,cat 程序会先被触发。cat 在这里没什么实际作用:它仅仅把输入的数据重新输出。这样的组合可以有效地在暂存前用 indent 过滤所有的 C 源码。

# 导出版本库

export-ignore

当归档的时候,可以设置 Git 不导出某些文件和目录。 如果你不想在归档中包含某个子目录或文件,但想把它们纳入项目的版本管理中,你可以在 export-ignore 属性中指定它们。

例如,假设你在 test/ 子目录下有一些测试文件,不希望它们被包含在项目导出的压缩包(tarball)中。 你可以增加下面这行到 Git 属性文件中:

test/ export-ignore

现在,当你运行 git archive 来创建项目的压缩包时,那个目录不会被包括在归档中。

export-subst

在导出文件进行部署的时候,你可以将 git log 的格式化和关键字展开处理应用到标记了 export-subst 属性的部分文件。

举个例子,如果你想在项目中包含一个叫做 LAST_COMMIT 的文件, 并在运行 git archive 的时候自动向它注入最新提交的元数据,可以像这样设置 .gitattributesLAST_COMMIT 该文件:

LAST_COMMIT export-subst
$ echo 'Last commit date: $Format:%cd by %aN$' > LAST_COMMIT
$ git add LAST_COMMIT .gitattributes
$ git commit -am 'adding LAST_COMMIT file for archives'

运行 git archive 之后,归档文件的内容会被替换成这样:

$ git archive HEAD | tar xCf ../deployment-testing -
$ cat ../deployment-testing/LAST_COMMIT
Last commit date: Tue Apr 21 08:38:48 2009 -0700 by Scott Chacon

# 合并策略

通过 Git 属性,我们可以对项目中的特定文件指定不同的合并策略。这个属性应该是最常用的一种了。

它最有用的一个选项就是,告诉 Git 当特定文件发生冲突时不要尝试合并它们,而是直接使用你这边的内容。

考虑如下场景:项目中有一个分叉的或者定制过的主题分支,你希望该分支上的更改能合并回你的主干分支,同时需要忽略其中某些文件。此时这个合并策略就能派上用场。假设你有一个数据库设置文件 database.xml,在两个分支中它是不同的,而你想合并另一个分支到你的分支上,又不想弄乱该数据库文件。你可以设置属性如下:

database.xml merge=ours

然后定义一个虚拟的合并策略,叫做 ours

$ git config --global merge.ours.driver true

如果你合并了另一个分支,database.xml 文件不会有合并冲突,相反会显示如下信息:

$ git merge topic
Auto-merging database.xml
Merge made by recursive.

这里,database.xml 保持了主干分支中的原始版本。

上次编辑于: 2024年5月10日 17:04