gitattributes中的filter

.gitattributes文件中的一些配置可以为某些特定目录或者文件来设置,这样Git就仅仅对一个子目录或者文件子集来应用规则。这些path-specific配置被称为Git atttributes并且要么在你的project root目录中的.gitattributes文件来配置或者如果你不想把.gitattributes文件commit到项目中的话,那么也可以放在.git/info/attributes文件中。

使用attributes,你可以做以下事情:比如对不同的文件集或者项目中的不同目录指定不同的merge strategy,告诉git如何来diff非text文件,或者Git在你check in/check out时 git如何来过滤文件的内容。

binary文件

你能使用git attributes的功能来实现的一个很cool的事情是:告诉git哪些文件是binary二进制文件并且给Git关于如何处理这些文件的特定的指令。比如,一些text文件有可能是由机器产生的,而不能diff出来,然而有些binary文件却可以被diff.你将需要告诉Git谁是谁。

一些文件看起来像是text文件,但是可能其目的却是被用作binary data.比如,Xcode项目包含一个文件,以.pbxroj为扩展名,这时一耳光简单的JSON文件,它记录了你的build配置等信息。虽然技术上说,它是一个文本文(因为它都是UTF-8编码的),但是实际上它确实一个轻量级的数据库,因此它并不是一个真正的文本文件,因为他的内容是不能简单的merge或者diff的。文件本身主要是由机器来使用的,简单的说,你应该把它当做binary文件来对待。

为了告诉git将pbxproj文件都以binray data来处理,需要增加以下行到.gitattributes文件中:

*.pbxproj binary

现在Git将不会试图变换或者fix CRLF的问题;也不会当你运行git show或者git diff时试图计算或者打印一一些changes。

Diffing Binary Files

你可以使用Git attributes的功能有效地diff二进制文件。你可以通过告诉git如何转换你的二进制文件为可以被git diff来比较的通用text格式来实现二进制文件的比较功能。

首先,使用这个技术来解决令人烦恼的word文件变更比较吧。如果你对word文档做版本控制,你会发现一旦执行git diff命令,只有如下毫无意义的信息输出:

$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 88839c4..4afcb7c 100644
Binary files a/chapter1.docx and b/chapter1.docx differ

你希望比较二者的不同,只能把两个版本拿下来人工比较。而借助git attributes特性,你可以实现像文本文件一样来比较不同。在.gitattributes文件中增加:

*.docx diff=word

这将告诉Git,任何匹配扩展名为.docx的文档当使用git diff命令查看变更时将使用"word" filter命令。那么什么是word filter呢?你必须要配置它。这里你可以配置git使用docx2txt程序来转换word文档为一个可读的text文件,这样就能轻松实现diff功能了。

首先,你要安装docx2txt程序,随后你需要写一个wrapper脚本来变换输出为git期望的格式。创建一个docx2txt的脚本:

#!/bin/bash
docx2txt.pl $1 -

将上述脚本chmod a+x,以便可以执行。最后,配置git来使用这个脚本:

$ git config diff.word.textconv docx2txt

现在git知道如果试图执行两个快照之间的diff时,任何以.docx为扩展名的文件,它都应该执行word filter(被定义为docx2txt程序)这将有效地在试图比较他们之前转换word文件为普通的text文件以便比较。

下面是一个输出的例子:

$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 0b013ca..ba25db5 100644
--- a/chapter1.docx
+++ b/chapter1.docx
@@ -2,6 +2,7 @@
 This chapter will be about getting started with Git. We will begin at the beginning by explaining some background on version control tools, then move on to how to get Git running on your system and finally how to get it setup to start working with. At the end of this chapter you should understand why Git is around, why you should use it and you should be all setup to do so.
 1.1. About Version Control
 What is "version control", and why should you care? Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. For the examples in this book you will use software source code as the files being version controlled, though in reality you can do this with nearly any type of file on a computer.
+Testing: 1, 2, 3.
 If you are a graphic or web designer and want to keep every version of an image or layout (which you would most certainly want to), a Version Control System (VCS) is a very wise thing to use. It allows you to revert files back to a previous state, revert the entire project back to a previous state, compare changes over time, see who last modified something that might be causing a problem, who introduced an issue and when, and more. Using a VCS also generally means that if you screw things up or lose files, you can easily recover. In addition, you get all this for very little overhead.
 1.1.1. Local Version Control Systems
 Many people‘s version-control method of choice is to copy files into another directory (perhaps a time-stamped directory, if they‘re clever). This approach is very common because it is so simple, but it is also incredibly error prone. It is easy to forget which directory you‘re in and accidentally write to the wrong file or copy over files you don‘t mean to.

另外一个你可以通过这种模式来解决的二进制文件比较问题的是:image文件比较。一种方法是通过一个能够抽取image文件的EXIF信息(metadata信息)的filter来执行image files比较。你可以下载并且安装exiftool程序,你使用它来转换image文件为你所需要的关于metadata的text文件。

$ echo '*.png diff=exif' >> .gitattributes
$ git config diff.exif.textconv exiftool

keyword expansion

SVN-/CVS-Style keyword expansion经常被开发人员提出需求。在git中这个keyword expansion功能的主要问题是:你不能修改commit的任何信息,虽然注入text到一个文件中不被允许,因为git使用checksum机制来确保文件安全。然而,你可以在checkout时注入,而在放到commit时删除一段text来规避这种情况。

首先你可以自动注入一个blob的SHA-1 checksum到一个$Id$域中。如果你在一个文件或一组文件中设置这个attribute,那么下一次你checkout那个branch时,git会自动更换使用那个blob的SHA-1信息来更换那个$Id$域。需要注意的是那个id不是commit的sha-1而是blob的sha-1 checksum:

$ echo '*.txt ident' >> .gitattributes
$ echo '$Id$' > test.txt

下一次你checkout这个文件时,git将注入blob的sha-1:

$ rm test.txt
$ git checkout -- test.txt
$ cat test.txt
$Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $

然而,那个结果却只能限制使用。如果你使用过CVS的keyword substitution功能,你可以包含一个datastamp信息。

如何实现呢?你可以通过写一个你自己的filter来实现党文件commit/checkout时自动替换这个信息。这些功能需要通过"clean"和"smudge" filter来实现。在.gitattributes文件中,你可以为一些特定路径来设置一个filter,随后设置当他们被checkout(smudge)时需要执行的处理该文件的脚本程序,以及当他们将被stage时(“clean"filter).这些filter可以被用来执行许多有趣的事情:

当checkout时执行上述smudge filter;

当文件被staged(commit)时执行clean filter

前面介绍过通过一个indent filter program来执行C源代码在commit之前自动indent的功能。回顾一下:你通过设置.gitattributes中的filter属性来配置所有*.c文件将使用indent filter

*.c filter=indent

然后,告诉git,indent filter在smudge和clean时,该indent filter应该做什么:

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

在上面这个例子中,当你commit *.c文件时,git将在commit之前执行indent程序,在checkout之前执行cat程序。这个组合便有效地在commit之前filter了所有c源程序代码。

另外一个有趣的例子是:获取$Date$keyword expansion.为了有效实现它,你需要一个小的脚本,该脚本带一个文件名,指出最近的commit日期,并且插入到文件中。下面是一耳光ruby script:

#! /usr/bin/env ruby
data = STDIN.read
last_date = `git log --pretty=format:"%ad" -1`
puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')

上面的脚本功能是从git log命令中获取最新的commit日期,并把该信息放到任何它在stdin中发现的$Date$ string,并且打印结果。你可以将该文件命名为expand_date并且放到你的path中。现在你需要设置一耳光filter(我们就叫他dater filter),并且告诉git使用expand_date filter来smudge files on checkout。你需要一个perl expression 在commit时清除掉:

$ git config filter.dater.smudge expand_date
$ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'

这个perl脚本strips out anything it sees in a $Date$ string。现在你的filter已经就绪,你可以通过创建一个包含$Date$关键词的文件然后创建filter:

$ echo '# $Date$‘ > date_test.txt
$ echo 'date*.txt filter=dater' >> .gitattributes

如果你commit那些变更并且checkout文件,你可以看到关键词已经被替换:

$ git add date_test.txt .gitattributes
$ git commit -m "Testing date expansion in Git"
$ rm date_test.txt
$ git checkout date_test.txt
$ cat date_test.txt
# $Date: Tue Apr 21 07:26:52 2009 -0700$

你可以看到这个技术在定制应用时是如何强大。你要注意的是因为.gitattributes文件被commit了,并且被随着项目repo来传播,然而由于driver(这里是dater)并不会随着project repo自然就ready,所以有可能在一些情况下并不能工作。当你设计这些filter时,他们可能会优雅地失败,但项目本身仍然能够正常工作。

Exporting your repository

Git attribute data也允许你在exporting项目的archive时做一些有趣的事情。

export-ignore

你可以告诉git不要在生成一个archive时,不要export一些文件或者目录。如果有一些子目录或者文件你不希望放到archive文件中但是你又需要放到项目checkout的working directory中去时,你可以通过export-ignore这个attribute来指定。

例如,你有一些test文件在test/目录下,它本身对于export你的项目作为一个归档并没有意义,你可以增加下面的行在git attributes文件中:

test/ export-ignore

现在当你执行git archive来创建project的tarball时,那个目录并不会放入

export-subst

当输出文件以便部署时,你可以应用git log的格式和keyword-expansion来选择那些被标示为export-subst属性的子文件集。

例如,如果你希望包含一个命名为LAST_COMMIT的文件在你的项目中,并且关于最后的commit的metadata信息在git archive命令运行时自动注入那个文件中,你可以设置下面的信息:

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

当你运行git archive时,那么achived file将由以下内容:

$ 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

被替换的信息可以包含commit message和任何git notes以及git log:

$ echo ‘$Format:Last commit: %h by %aN at %cd%n%+w(76,6,9)%B$‘ > LAST_COMMIT
$ git commit -am ‘export-subst uses git log‘s custom formatter

git archive uses git log‘s `pretty=format:` processor
directly, and strips the surrounding `$Format:` and `$`
markup from the output.
‘
$ git archive @ | tar xfO - LAST_COMMIT
Last commit: 312ccc8 by Jim Hill at Fri May 8 09:14:04 2015 -0700
       export-subst uses git log‘s custom formatter

         git archive uses git log‘s `pretty=format:` processor directly, and
         strips the surrounding `$Format:` and `$` markup from the output.

产生的archive适合于deployment,但是像任何exported archive一样,它并不适合做任何继续的开发。

merge strategies:

你可以使用git attributes来告诉git对特定的项目文件使用不同的merge strategies。一个非常有用的选项是告诉git当发生冲突时不要试图merge特定的文件,而是使用你优选的冲突方来作为最后merge的结果。

比如你有一个database.xml文件包含了数据库的配置信息,该文件在两个branch中是不同的,而你希望merge in your other branch without messing up the database file.你可以通过设置一个属性如下:

database.xml merge=ours

然后顶一个一个dummy ours merge strategy with:

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

如果你emrge in the other branch,不会有database.xml文件的merge conflicts,你看到如下内容:

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

在这种情况下,database.xml将停留在你期初所有的任何版本上

时间: 2024-10-10 15:37:48

gitattributes中的filter的相关文章

angular input输入框中使用filter格式化日期

最近使用了angular日期选择器,不过需要把选中的日期输出到input输入框中,如果按照默认情况,显示的是时间戳形式的时间,不符合要求,需要把格式变成特定格式,但是input上ng-model上又不能直接使用filter,因此需要一种方法把这里显示的内容格式化. 网上寻找解决方案就是写个directive,具体实例代码如下: JS angular.module('dateRange',[]).directive('dateFormat', ['$filter',function($filter

Exchange的PowerShell中关于Filter的写法

这篇文章简单说一下Exchange的PowerShell中,Filter的用法,不过相信看完的同学以后可能不会用这个东西------虽然这么说,但是毕竟是一个新的选择,大家可以学习一下. 首先我们看一个输出,我们看看在Exchange2010中,get-user有哪些属性可以做筛选 [PS] E:\>Get-User zhangpengliang|select * 正在创建新会话来隐式远程处理"Get-User"命令... RunspaceId               : 2

SQL中的Filter, join, semi-join等概念的释义

经常在工作中用到,虽然当年在数据库原理课程中学习过,不过基本已经还给老师了.工作这么多年,感觉自己在学习上倒退了很多,惭愧.这篇帖子,作为SQL相关知识的整理贴. 1.semi-join(半连接)(来自:http://wiki.answers.com/Q/What_is_semi_join_in_SQL) 半连接返回表中能够与另一表中连接的记录(并不执行一次全连接),它并没有一个明确的语法格式. A semi-join returns rows from one table that would

Python中map,filter,reduce的应用

事例1: l=[('main', 'router_115.236.xx.xx', [{'abc': 1}, {'dfg': 1}]), ('main', 'router_183.61.xx.xx', [{'abc': 0}, {'dfg': 1}]), ('main', 'router_52.11.xx.xx', [{'abc': 0}, {'dfg': 1}]), ('main', 'router_183.17.xx.xx', [{'abc': 1}, {'dfg': 1}]) ] 检查参数l

Attribute(二)——自定义特性+Asp.net MVC中的filter详解

上篇博客是关于特性中有关预定义特性的一些基础,同时也是对Attribute这一概念的一个宏观上的认识,在上篇博客结尾介绍了有关为自定义特性服务的AttributeUsage,这篇博客主要是通过filter的使用间接的了解自定义特性的具体应用. 一.filter简介 在了解自定义特性前,先引入一个概念filter,它是MVC中自带的一种功能,在我们项目中通常会遇到在Action执行前或结束时,去执行日志记录或错误处理等功能,通常可使用AOP截取来实现,但是在MVC中提供了filter过滤,大大方便

数组中的filter函数,递归以及一些应用。

当我们用一个东西时候我们必须知道的是?why---where----how---when.一个东西我们为什么用?在哪用?怎么用?何时用?而不是被动的去接受一些东西.用在js里边我觉得也会试用.一直追求源生js,虽然也都背过好多东西,但是随着时间的流逝,工作的繁忙都忘了,有时甚至一点印象都没有,这让我开始思考我的学习方法了已经思维方式了.我们要记得不是简单的那个单词然后开始联想这个单词有什么用?一定是我要做什么事情?然后联想到谁可以做.带有目的性的学习. 现在有十个人(也就是数组)需要我们把属虎的

ABP中的Filter(上)

这个部分我打算用上下两个部分来将整个结构来讲完,在我们读ABP中的代码之后我们一直有一个疑问?在ABP中为什么要定义Interceptor和Filter,甚至这两者之间我们都能找到一些对应关系,比如:AuthorizationInterceptor和AbpAuthorizationFilter,AuditingInterceptor和AbpAuditActionFilter,甚至这些代码的实现也是调用相同的接口和实现?那么ABP为什么要采用这种方式呢?在前面的章节中我已经充分介绍过了ABP中的各

Servlet中的Filter怎么使用?

一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter.通过F

在springboot工程中使用filter

在springboot工程中使用filter 一.什么是filter 过滤器实际上就是用来对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理 通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理 . filter可以在请求到达servlet前或者请求完成响应后进行后续的处理. 二.在springboot工程中使用filter 创建一个filter,并使用注解配置该filter的名称和拦截路径等属性 @WebFilter(filterName