#! /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, заменяет результатом все подстроки $Date$ и возвращает результат. Вы можете написать аналогичный скрипт на любом языке. Назовите файл со скриптом, например, expand_date и сохраните в директории с программами. Теперь, нужно настроить Git фильтр (назовите его dater) и укажите ему использовать ваш скрипт expand_date при извлечении файлов. Всместе с этим, мы будем использовать регулярное выражение Perl для очистки перед коммитом:
$git config filter.dater.smudge expand_date
$git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'
Указанная Perl команда очищает любое значение в строке, где она видит $Date$, чтобы вернуть файл в изначальное состояние. Теперь фильтр готов и вы можете проверить его добавив ключевое слово $Date$ в файл и настроив Git атрибут, чтобы для вашего файла применялся созданный фильтр:
$echo '# $Date$' > date_test.txt
$echo 'date*.txt filter=dater' >> .gitattributes
Если добавить в коммит последние изменения, а затем извлечь файл, то вы увидите корректную подстановку ключевого слова:
$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 включается в коммит и распространяется вместе с проектом, а драйвер (в данном случае dater) нет, поэтому он не будет работать везде. Учитывайте это при разработке фильтров оставляя возможность работы без них - так вы сохраните проект в рабочем состоянии.
Атрибуты Git так же позволяют вам делать некоторые интересные вещи при экспорте вашего проекта.
Вы можете указать Git игнорировать определенные файлы и директории при создании архива. Если в вашем проекте есть файл или директория, которые вам нужны, но вы не хотите включать их в архив при экспорте, то можно присвоить им атрибут export-ignore.
Например, у вас есть неколько файлов в директории test/ и совершенно нет смысла включать их в архив вашего проекта. В этом случае достаточно добавить следующую строку в файл .gitattributes:
test/ export-ignore
Теперь, при создании архива проекта командой git archive, директория test/ не будет включена в архив.
При создании архива так же доступна простая подстановка по ключевым словам. Git допускает размещение строк $Format:$ в любом файле с любой комбинацией --pretty=format кодов, большинство из которых вам известны по Разделу 2. Например, если вы хотите добавить файл с именем LAST_COMMIT, в который будет добавляться дата последнего коммита при создании архива, то сделайте следующее:
$echo 'Last commit date: $Format:%cd$' > LAST_COMMIT
$echo "LAST_COMMIT export-subst" >> .gitattributes
$git add LAST_COMMIT .gitattributes
$git commit -am 'adding LAST_COMMIT file for archives'
Теперь, при создании архива проекта командой git archive, в него будет включен файл со следующим содержанием:
$cat LAST_COMMIT
Last commit date: $Format:Tue Apr 21 08:38:48 2009 -0700$
Используя атрибуты Git можно применять разные стратегии слияния для разных типов файлов вашего проекта. Одна из полезных опций - это указать Git не сливать изменения в определенных файлах в случае конфликта, при этом использовать вашу версию файла.
Это полезно в случае, когда ветка разошлась или у вас специализированная ветка, при этом вы хотите иметь возможность сливать изменения, но игнорировать определенные файлы. Предположим, что у вас есть файл с настройками базы данных database.xml, содержимое которого в разных ветках отличается, при этом вы хотите сливать изменения из другой ветки не меняя этот файл. Для этого нужно добавить следующий атрибут:
database.xml merge=ours
А затем определить фиктивную стратегию слияния выполнив команду:
$git config --global merge.ours.driver true
Если вы сольёте изменения из другой ветки, то вместо конфликта слияния для файла database.xml вы увидите что-то вроде этого:
$git merge topic
Auto-merging database.xml
Merge made by recursive.
В этом случае файл database.xml всегда остаётся неизменным.
Like many other Version Control Systems, Git has a way to fire off custom scripts when certain important actions occur. There are two groups of these hooks: client-side and server-side. Client-side hooks are triggered by operations such as committing and merging, while server-side hooks run on network operations such as receiving pushed commits. You can use these hooks for all sorts of reasons
Читать дальше