Git: игнорирование файлов

Приемы и команды Git игнорирования файлов и папок при работе над проектом.

Практически при любой разработке более или менее серьезной программы существуют файлы, которые не требуют отслеживания, это могут быть временные файлы, локальные настройки или конфигурации. Давайте разберемся, что с ними нужно сделать в git, чтобы они не засоряли проект. Самое простое решение — запретить отслеживать их изменения.

Рассмотрим такие ситуации:
– как исключить файл при отправке в репозиторий, т.е. исключить из индексирования;
– как игнорировать файл при загрузке из удаленного хранилища;
– как поступить, если в удаленном и локальном репозиториях хранятся важные и разные версии файла.

Исключение из индексирования.

Чтобы ресурс не отслеживался git’ом и не появлялся в списке неотслеживаемых, его надо исключить из списка индексируемых. Для этого создают специальные файлы игнорирования «.gitignore». В них с помощью перечислений и шаблонов указывают git, что запрещено отправлять в репозиторий. Способ хорош тем, что подобное можно один раз проделать и забыть, дальше работает git. Следует заметить, что отслеживания не будет в том случае, если файла нет в удаленном репозитории. Если он там присутствует, то будет аккуратненько загружаться git, но это уже другая история, которую разберем ниже.
Игнорировать файлы можно для отдельных проектов или глобально для всех. Если .gitignore разместить в корневом каталоге проекта, он будет работать для только для него. Чтобы он трудился для всех проектов, его размещают в корневой папке пользователя, а в конфигурации git указывают путь к нему.

Для Windows:

git config – –global core.excludesfile «%USERPROFILE%\.gitignore» — в Windows указывает git, где находится глобальный файл игнорирования.

Для Linux:

git config – –global core.excludesfile ‘~/.gitignore’ — в Linux указывает git, где находится глобальный файл игнорирования.

Масок и шаблонов в .gitignore достаточно много, поэтому укажу наиболее востребованные, остальное можно легко найти в Инете:
одна строка используется для указания одного правила игнорирования;
символ «/» в начале строки – указание применять правило только для папок и файлов в той директории, где находится сам .gitignore;
«/» в конце имени – означает, что игнорируемое место является директорией;
«\» – используется для экранирования специальных символов в шаблонах .gitignore;
«*» – означает ноль или более символов в любом месте шаблона;
«?» – означает ноль или один символ в любом месте шаблона;
«#» в начале строки – комментарий;
«!» в начале строки – инвертирование правила, используется для указания исключений из правил;

Примеры правил в .gitignore.
*.back — игнорировать все файлы с расширением back
*.[ec] — игнорировать файлы, заканчивающиеся на .e или .c
config.php – игнорировать файл config.php во всех директориях
/config.php – файл игнорируется в той директории, где расположен данный .gitignore
/config/* — игнорирование всех файлов и папок, включая вложенные, в папке config

Больше примеров применения шаблонов игнорирования можно найти в Примеры правил .gitignore на github

Описанное используется для постоянной настройки игнорирования ресурсов программного кода, а если надо временно исключить файл? Для текущих операций игнорирования используется команда git

git rm [options] ‹file› — удаляет файл из индекса и рабочей директории

Разберемся, что она делает.
Предположим, мы создали файл index.php и проиндексировали его. Если удалить файл из рабочего каталога инструкцией операционной системы, git status покажет его в секции “Changes not staged for commit” т.е. укажет, что удаление в рабочем каталоге не было проиндексировано.
Если же удалить этот файл с помощью git

git rm index.php

то git status скажет, что index.php был удален из рабочего каталога и это удаление было проиндексировано, т.е., после следующего коммита файл исчезнет из указанной в команде папки и из текущего состояния хранилища и не будет больше отслеживаться.
Теперь разберемся с некоторыми опциями этой инструкции.

git rm – –cached ‹file› — удаляет файл из списка проиндексированных для последующего коммита, добавляет в список игнорируемых и оставляет в рабочем каталоге

Как видите, если вы ошибочно проиндексировали файл, который должен игнорироваться, эта инструкция исправит ситуацию.

git -f – –cached ‹file› — удаляет из проекта и из списка проиндексированных, фактически повторяет git rm ‹file›

Резюме. Для удаления файла из проекта и хранилищей удобнее использовать git rm ‹file›

Игнорирование файла в удаленном Git репозитории

Теперь такая ситуация. В удаленном репозитории находится файл, который вам либо не нужен, либо он каждый раз затирает ваши локальные настройки при синхронизации. В этом случае надо выполнить

git update-index – –assume-unchanged project/config.php

Если надо игнорировать целиком папку project, то используется шаблон *

git update-index – –assume-unchanged project/*

Чтобы вернуть файл в лоно отслеживаемых при закачке удаленного репозитория, git должен перед pull’ом выполнить инструкцию

git update-index – –no-assume-unchanged project/config.php

или тоже для всей директории

git update-index – –no-assume-unchanged project/*

Конфликт версий файла в Git репозиториях

Еще одна ситуация. В удаленном репозитории Git хранится какой-то файл, например, options.ini, который был кем-то изменен и теперь отличается от вашего локального. Вы при этом хотите получить проект из удаленного хранилища, но и свой сохранить. Git не позволит вам сделать pull, т.к. у вас версии файлов конфликтуют. Чтобы разрулить ситуацию придется немного потрудиться и проделать следующее.
1.Сохранить свой options.ini в папку, недоступную git.
2.Отменить игнорирование файла

git update-index – –no-assume-unchanged options.ini

3.Произвести синхронизацию с удаленным репозиторием

git pull origin master

4.Создать отдельную ветку, например, dev1 и влить в нее основную ветку

git branch dev1
git checkout dev1
git merge master

5. Вернуть в рабочую папку свои предварительно сохраненные настройки.
6. Дать команду git игнорировать файл options.ini

git update-index – –assume-unchanged options.ini

В итоге имеем локальную ветку master, которая совпадает с одноименной удаленной, и локальную ветку dev1 с вашими локальными настройками, остальные файлы совпадают с файлами основной веткой master. Состояние вашего рабочего каталога после проделанных операций соответствует состоянию ветки dev1 с вашими локальными настройками. При желании перейти в состояние, которое идентично основной ветки master выполните

git checkout master