Итак, у вас имеются настоящий Git-репозиторий и рабочая копия файлов для некоторого проекта.
Вам нужно делать некоторые изменения и фиксировать «снимки» состояния (snapshots) этих изменений в вашем репозитории каждый раз, когда проект достигает состояния, которое вам хотелось бы сохранить.
Запомните, каждый файл в вашем рабочем каталоге может находиться в одном из двух состояний: под версионным контролем и не под версионным контролем. Файлы под версионным контролем — это те файлы, которые были в последнем снимке состояния проекта. Они могут быть неизмененными, измененными и индексированными. Файлы не под версионным контролем — это все остальное, любые файлы в вашем рабочем каталоге, которые не входили в ваш последний снимок состояния и не подготовлены к фиксации.
Когда вы впервые клонируете репозиторий, все файлы будут находиться под версионным контролем и будут неизмененными, потому что вы только извлекли их из репозитория и ничего пока не редактировали.
Как только вы отредактируете файлы, Git будет рассматривать их как измененные, т. к. вы изменили их с момента последнего коммита. Вы индексируете эти изменения и затем фиксируете все индексированные изменения, а затем цикл повторяется.
Основной инструмент, используемый для определения, какие файлы в каком состоянии находятся — это значки, расположенные рядом с именами файлов в представлениях Проводник (Explorer) и Система управления версиями (Source Control).
Если вы посмотрите на представление Проводник (Explorer) сразу после клонирования, вы не увидите ни одного такого значка:
Это означает, что у вас чистый рабочий каталог, другими словами?—?в нем нет отслеживаемых измененных файлов. Git также не обнаружил неотслеживаемых файлов, в противном случае они бы были отмечены здесь.
Предположим, вы добавили в свой проект новый файл, new_script.sbsl. Если этого файла раньше не было, вы увидите свой неотслеживаемый файл вот так:
Понять, что новый файл new_script.sbsl неотслеживаемый можно по тому, что он отмечен буквой U (Untracked). Если вы сомневаетесь или забыли, что означает та или иная буква, подведите курсор к строке файла и в подсказке вы увидите статус Не отслеживается (Untracked):
Статус Не отслеживается (Untracked) означает, что Git видит файл, которого не было в предыдущем снимке состояния (коммите). Git не станет добавлять его в ваши коммиты, пока вы его явно об этом не попросите. Это предохранит вас от случайного добавления в репозиторий сгенерированных бинарных файлов или каких-либо других, которые вы и не думали добавлять.
Вы хотели добавить new_script.sbsl под версионный контроль, так сделайте это.
Как вы уже знаете, для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда (Индексировать изменения / Stage Changes). Она появляется в представлении Система управления версиями (Source Control) в строке файла при наведении мыши на строку.
Нажмите (Индексировать изменения / Stage Changes) и посмотрите, что изменилось.
Вы можете видеть, что файл проиндексирован, так как он находится в разделе Промежуточные изменения (Staged Changes) и отмечен буквой А, что значит Добавлено в индекс (Index Added).
Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды (Индексировать изменения / Stage Changes), будет добавлена в историю снимков состояния. Как вы помните, когда вы ранее создали репозиторий, а затем выполнили (Индексировать изменения / Stage Changes)?—?это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль.
Вы добавляли каждый из файлов отдельно (такова была задача), но обычно все измененные файлы добавляют одновременно. Для этого есть команда (Хранить все промежуточные изменения / Stage All Changes), которая появляется при наведении мыши на раздел Изменения (Changes).
Модифицируйте файл, уже находящийся под версионным контролем, например coldev.sbsl. Вы увидите следующие изменения:
Файл coldev.sbsl находится в разделе Изменения (Changes) и отмечен буквой M — Изменен (Modified). Это означает, что отслеживаемый файл был изменен в рабочем каталоге, но пока не проиндексирован.
Чтобы проиндексировать его, необходимо выполнить уже известную вам команду (Индексировать изменения / Stage Changes). Это многофункциональная команда, она используется и для добавления под версионный контроль новых файлов, и для индексации изменений, а также для других целей, например для указания файлов с исправленным конфликтом слияния.
Нажмите (Индексировать изменения / Stage Changes) и посмотрите, что изменилось.
Теперь оба файла проиндексированы и войдут в следующий коммит.
В этот момент вы, предположим, вспомнили одно небольшое изменение, которое вы хотите сделать в coldev.sbsl до коммита. Вы открываете файл, вносите и сохраняете необходимые изменения и вроде бы готовы к коммиту. Но взгляните на представление Система управления версиями (Source Control).
Что происходит? Теперь coldev.sbsl отображается как проиндексированный и непроиндексированный одновременно. Как такое возможно?
Эта ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду (Индексировать изменения / Stage Changes).
Если вы выполните коммит сейчас, то файл coldev.sbsl попадет в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду (Индексировать изменения / Stage Changes), а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения Фиксация (Commit).
Если вы изменили файл после добавления в индекс, вам придется снова выполнить (Индексировать изменения / Stage Changes), чтобы проиндексировать последнюю версию файла.
Зачастую, у вас имеется группа файлов, которые вы не только не хотите автоматически добавлять в репозиторий, но и видеть в списках неотслеживаемых. К таким файлам обычно относятся автоматически генерируемые файлы (различные логи, результаты сборки программ и т. п.).
В примере, когда вы создавали репозиторий, таким файлом является файл рабочей области coldevex.code-workspace, который создала Visual Studio Code.
Два скрипта вы добавили под версионный контроль, а этот файл оставили «на потом». Сейчас пришло время разобраться с ним.
Файл рабочей области хранит ваши настройки Visual Studio Code, которыми пользуетесь вы, разрабатывая проект. Если бы вы работали в одиночку, то имело смысл добавить этот файл в репозиторий. Но так как проект будут разрабатывать разные люди, у каждого из них могут быть свои настройки Visual Studio Code. Хранить все эти служебные файлы в репозитории не имеет смысла, кроме того не исключена ситуация, когда имена этих файлов совпадут у разных разработчиков. Один из них откроет проект и увидит Visual Studio Code совсем не такой, в какой он привык работать.
Поэтому при совместной работе имеет смысл проигнорировать файл coldevex.code-workspace.
Для этих целей можно создать в репозитории файл .gitignore, с перечислением шаблонов игнорируемых файлов. Вот пример файла .gitignore:
# Исключить все файлы с расширением .a
*.a
Чтобы проигнорировать файл coldevex.code-workspace выполните следующие действия:
В файле .gitignore можно использовать разные шаблоны. Вот пример файла .gitignore.
*.[oa]
*~
Первая строка предписывает Git игнорировать любые файлы заканчивающиеся на «.o» или «.a»?—?объектные и архивные файлы, которые могут появиться во время сборки кода.
Вторая строка предписывает игнорировать все файлы заканчивающиеся на тильду (~), которая используется во многих текстовых редакторах, например Emacs, для обозначения временных файлов.
Вы можете также включить каталоги log, tmp или pid, автоматически создаваемую документацию и т. д. и т. п. Хорошая практика заключается в настройке файла .gitignore до того, как начать серьезно работать. Это защитит вас от случайного добавления в репозиторий файлов, которых вы там видеть не хотите.
К шаблонам в файле .gitignore применяются следующие правила:
#
,
игнорируются;/
) в
начале шаблона;/
) в конец
шаблона;!
) в качестве первого символа. Глобальные шаблоны представляют собой упрощенные регулярные выражения, используемые командными интерпретаторами:
*
) соответствует 0 или более символам;[abc]
?—?любому символу из указанных в
скобках (в данном примере a, b или c);?
) соответствует одному символу;[0-9]
), соответствуют любому символу из интервала (в
данном случае от 0 до 9)a/**/z
соответствует a/z, a/b/z, a/b/c/z, и так
далее.Вот еще один пример файла .gitignore:
# Исключить все файлы с расширением .a
*.a
# Но отслеживать файл lib.a даже если он подпадает под исключение выше
!lib.a
# Исключить файл TODO в корневом каталоге, но не файл в subdir/TODO
/TODO
# Игнорировать все файлы в каталоге build/
build/
# Например, игнорировать doc/notes.txt, но не файл doc/server/arch.txt
doc/*.txt
# Игнорировать все .docx-файлы в каталоге doc/ и любых его подкаталогах
doc/**/*.docx
GitHub поддерживает довольно полный список примеров .gitignore файлов для множества проектов и языков https://github.com/github/gitignore это может стать отправной точкой для .gitignore в вашем проекте.
В простейшем случае репозиторий будет иметь один файл .gitignore в корневом каталоге, правила из которого будут рекурсивно применяться ко всем подкаталогам. Так же возможно использовать .gitignore файлы в подкаталогах. Правила из этих файлов будут применяться только к каталогам, в которых они находятся. Например, репозиторий исходного кода ядра Linux содержит 206 файлов .gitignore.
Детальное рассмотрение использования нескольких .gitignore файлов выходит за пределы этой книги.
Допустим, вы изменили файлы bitdepth.sbsl и coldev.sbsl без индексирования. Если вы откроете представление Система управления версиями (Source Control), вы увидите что эти файлы изменены и они не включены в индекс.
Чтобы увидеть, что же вы изменили, но пока не проиндексировали, нажмите (Просмотреть изменения / View Changes) в названии раздела Изменения (Changes). Эта команда появляется при наведении мыши на строку раздела.
Эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса. Результат показывает еще не проиндексированные изменения.
Вы видите, что изменены два файла. Для каждого из них показаны измененные строки. Слева находится индекс, справа — рабочий каталог.
В первом случае, в файле bitdepth.sbsl удалены две пустые строки: одна в начале, другая в конце файла.
Во втором случае, в файле coldev.sbsl изменен текст сообщений, которые выводятся в консоль.
Проиндексируйте файл bitdepth.sbsl. В разделе Промежуточные изменения (Staged Changes) есть аналогичная команда (Просмотреть подготовленные изменения / View Staged Changes). Она сравнивает ваши проиндексированные изменения с последним коммитом.
Сейчас результат этой команды выглядит так же, как и в предыдущем случае. Разница в том, что теперь слева находится последний коммит (HEAD), а справа — индекс.
Теперь посмотрите другой пример. Вы уже проиндексировали файл bitdepth.sbsl, но решили внести в него дополнительные изменения. В этом случае вы можете просмотреть как проиндексированные изменения в этом файле, так и те, что пока не проиндексированы.
В данном случае хорошо видно, что дополнительные изменения, которые вы внесли в файл, но еще не проиндексировали, заключаются в изменении сообщений, которые выводятся в консоль. Вы можете добавить эти изменения в индекс и зафиксировать все одним коммитом. Или же можете сейчас зафиксировать те изменения, которые уже есть в индексе, а дополнительные изменения зафиксировать вторым коммитом.
Все зависит от логики выполняемых действий. Если все эти изменения относятся к одной задаче, то логично фиксировать их одним коммитом. Если они относятся к разным задачам, то лучше сделать два коммита.
Теперь, когда ваш индекс находится в таком состоянии, как вам и хотелось, вы можете зафиксировать свои изменения. Запомните, все, что до сих пор не проиндексировано?—?любые файлы, созданные или измененные вами, для которых вы не выполнили (Индексировать изменения / Stage Changes) после редактирования?—?не войдут в этот коммит. Они останутся измененными файлами на вашем диске.
Допустим, вы добавили в индекс все измененные файлы и готовы к коммиту. Простейший способ зафиксировать изменения?—?это ввести сообщение коммита и нажать Фиксация (Commit) в представлении Система управления версиями (Source Control).
Итак, вы создали коммит, раздел Система управления версиями (Source Control) очистился (ваш рабочий каталог соответствует последнему коммиту, находящемуся в репозитории), а в разделе Граф системы управления версиями (Source Control Graph) появилась запись о вашем коммите.
В простейшем виде она содержит сообщение вашего коммита (Изменил сообщения, выводимые в консоль) и имя пользователя, выполнившего коммит (devmaster). Также в конце строки указана ветка, в которую выполнен этот коммит (main). Если вы наведете мышь на строку коммита, то в подсказке увидите более подробную информацию о коммите: какая контрольная сумма SHA-1 у этого коммита (979c285a), сколько файлов было изменено (2 файла), а также статистику по добавленным и удаленным строкам в этом коммите.
Запомните, что коммит сохраняет снимок состояния вашего индекса. Все, что вы не проиндексировали, так и висит в рабочем каталоге как измененное. Вы можете сделать еще один коммит, чтобы добавить эти изменения в репозиторий. Каждый раз, когда вы делаете коммит, вы сохраняете снимок состояния вашего проекта, который позже вы можете восстановить или с которым можно сравнить текущее состояние.
Несмотря на то, что индекс может быть удивительно полезным для создания коммитов именно такими, как вам и хотелось, он временами несколько сложнее, чем вам нужно в процессе работы. Если у вас есть желание пропустить этап индексирования, Git предоставляет простой способ.
После того, как вы изменили файлы, не помещая их в индекс, напишите сообщение коммита и нажмите Фиксация (Commit).
Visual Studio Code задаст вам вопрос.
Здесь у вас есть два варианта:
Мы рекомендуем поработать некоторое время прежде чем пропускать индексацию или решать, что она вам совсем не нужна. В любом случае, если вы выберете вариант Всегда, вы можете вернуть все к исходному поведению в параметрах Visual Studio Code в разделе .
Если вы просто удалите файл из своего рабочего каталога, он будет показан в разделе Изменения (Changes) (измененные, но не проиндексированные) со значком D — Удалить (Deleted):
Теперь вам нужно добавить удаление файла в индекс и зафиксировать изменения. После этого файл исчезнет и больше не будет отслеживаться.
Другая полезная штука, которую вы можете захотеть сделать?—?это удалить файл из индекса, оставив его при этом в рабочем каталоге. Другими словами, вы можете захотеть оставить файл на жестком диске, но перестать отслеживать изменения в нем. Это особенно полезно, если вы забыли добавить что-то в файл .gitignore и по ошибке проиндексировали, например, большой файл с логами, или кучу промежуточных файлов компиляции.
Чтобы сделать это, можно воспользоваться командной строкой. Например, вы хотите изъять из под версионного контроля файл randomfile.txt:
git rm log/\*.log
Обратите внимание на обратный слеш
(\) перед *. Он необходим из-за того, что Git использует свой
собственный обработчик имен файлов вдобавок к обработчику вашего командного
интерпретатора. Эта команда удаляет все файлы, имеющие расширение
.log и находящиеся в каталоге
log/. git rm \*~
Эта команда
удаляет все файлы, имена которых заканчиваются на ~.В отличие от многих других систем контроля версий, Git не отслеживает переименование файлов явно. Когда вы переименовываете файл в Git, в нем не сохраняется никаких метаданных, говорящих о том, что файл был переименован. Однако, Git довольно умен в плане обнаружения переименований.
Если вам хочется переименовать файл, в представлении Проводник (Explorer) нажмите Переименовать... (Rename...) в контекстном меню файла. Задайте новое имя, например randomfile1.txt вместо randomfile.txt, и нажмите Ввод.
Перейдите в представление Система управления версиями (Source Control).
Здесь вы увидите логичный результат ваших действий: файл randomfile.txt был удален, а файл randomfile1.txt — добавлен.
Однако как только вы поместите эти изменения в индекс, картина изменится и Visual Studio Code покажет вам, что файл был переименован. Она отметит его значком R — Переименовано в индексе (Index Renamed).
Вам останется только зафиксировать изменения.
По материалам книги Pro Git (авторы Scott Chacon и Ben Straub, издательство Apress). Книга распространяется по лицензии Creative Commons Attribution Non Commercial Share Alike 3.0 license.