Git не коммитить файл

Обновлено: 04.07.2024

Коммит - очередное зафиксированное состояние проекта, "единица" версии.
Все коммиты (кроме первого) должны наследоваться от предыдущего коммита, образуя таким образом древовидную структуру, как изображено на рисунке ниже (кружки - коммиты).

Как видно из иллюстрации, проект может разветвляться, например если два разработчика параллельно работают и каждый создаёт свои коммиты. Чтобы не возникало полного хаоса и можно было ориентироваться в происходящем вводят понятие ветки
Ветка - по большому счёту просто именованная ссылка на некий коммит, указывающая на конец очередного ответвления от главной центральной ветки (по умолчанию она зовётся master). Как правило, репозиторий работает в привязке к какой-то ветке и при создании нового коммита, он присоединяется к тому, на который ссылается ветка, и ветка начинает указывать на новый коммит. На картинке выше помимо master есть ветки Little Feature и Big Feature.

Установка

Linux — нужно просто открыть терминал и установить приложение при помощи пакетного менеджера вашего дистрибутива. Для Ubuntu команда будет выглядеть следующим образом:

Windows — мы рекомендуем git for windows, так как он содержит и клиент с графическим интерфейсом, и эмулятор bash.

Настройка

Первым делом до начала работы, нужно внести глобальные настройки:

Репозиторий

Итак, вот у вас уже есть git. Теперь нужно создать хранилище версий для него. Запомните, это хранилище называется репозиторий (англ. repository) — при случае можете вставить где-нибудь это словечко. В зависимости от того, какая у вас оболочка, соответствующей командой создайте новую директорию, откройте ее (в командной строке, она же оболочка, а не проводником или чем-то подобным) и выполните:
Все, локальный репозиторий в этой папке создан. То, что здесь сейчас хранится, будет бекапом, поэтому, чтобы его не испортить, создадим рабочую копию (англ. check out)локальной версии:
Где [url] — это путь до клонируемого репозитория. Мы разбираем сейчас случай, когда вы создаете рабочую копию собственного репозитория, поэтому в качестве [url] здесь вам нужно указать путь до директории, для которой мы выполняли git init.
Иногда нужно склонировать только конкретную ветку, тогда:
Еще иногда может потребоваться склонировать репозиторий без многолетней истории его коммитов, тогда нужно использовать параметр --depth=5, где 5 - количество коммитов от последнего:
  1. Создание репозитория (git init) или (git clone адресс_репозитория ), если копируем удалённый
  2. Делаем изменения
  3. Помещаем файлы под VCS-отслеживание (git add)
  4. Фиксируем (коммитим) изменения (git commit)
  5. Заливаем (пушим) их на удалённое хранилище (git push)

Создание коммита

Файл(-ы) находятся в HEAD вашей рабочей локальной копии. В вашем удаленном репозитории их все еще нет.
Пуш в репозиторий:

Ветвление

Создание новой ветки
Есть разные принципы модели ветвления в git. Одна из них: Новая задача - новая ветка. О другой поговорим далее.
Создание новой ветки:

Обязательно нужно делать пуш изменений в общий репозиторий:

Запрос изменений с сервера

Чтобы обновить локальный репозиторий до последнего коммита, нужно сделать “пулл”:

Слияние веток

Чтобы слить ветку в ту, с которой вы сейчас работаете, используйте:

Ветки можно сравнить:

Обновить локальный репозиторий до нового коммита:
git tag [tag] [первые_десять_символов_соответствующего_коммита]
Откат мерджа
Если проблема только в одном файле, то вот вам Ctrl Z для HEAD’a:
Но если проблема находится в локальном репозитории, то зачистите там все и верните версию с сервера:

Разрешение конфликтов при слиянии

git merge 1_branch
Auto-merging print_array.js
CONFLICT (content): Merge conflict in print_array.js
Automatic merge failed; fix conflicts and then commit the result.
Система не смогла разрешить конфликт автоматически, значит, это придется сделать разработчикам. Приложение отметило строки, содержащие конфликт:
Над разделителем ======= мы видим последний (HEAD) коммит, а под ним — конфликтующий. Таким образом, мы можем увидеть, чем они отличаются и решать, какая версия лучше. Или вовсе написать новую. В этой ситуации мы так и поступим, перепишем все, удалив разделители, и дадим git понять, что закончили.Когда все готово, нужно закоммитить изменения, чтобы закончить процесс:
git add -A
git commit -m "Array printing conflict resolved."

Короткая и простая история коммитов.

git checkout -b iss53

Создание новой ветки / указателя.


Сделали новый коммит:

Ветка iss53 передвинулась вперёд во время работы.


Создание хот-фикса:
git checkout master
git checkout -b hotfix

Ветка для решения срочной проблемы базируется на ветке master.


Слияние веток:
git checkout master
git merge hotfix
git merge iss53

Git автоматически создаёт новый коммит, содержащий результаты слияния.

Настройка .gitignore

  1. Создайте вручную файл под названием .gitignore и сохраните его в директорию проекта.
  2. Внутри файла перечислите названия файлов/папок, которые нужно игнорировать, каждый с новой строки.
  3. Файл .gitignore должен быть добавлен, закоммичен и отправлен на сервер, как любой другой файл в проекте.
  • Логи
  • Артефакты систем сборки
  • Папки node_modules в проектах node.js
  • Папки, созданные IDE, например, Netbeans или IntelliJ
  • Разнообразные заметки разработчика.

*.log
build/
node_modules/
.idea/
my_notes.txt

Удачная модель ветвления для Git

  • master - создаётся при инициализации репозитория, считаем ветку origin/master главной.
  • develop - ветвь origin/develop мы считаем главной ветвью для разработки.
  • Ветви функциональностей (Feature branches)
  • Ветви релизов (Release branches)
  • Ветви исправлений (Hotfix branches)

При начале работы над новой функциональностью делается ответвление от ветви разработки (develop).

Ветви релизов (release branches)
Могут порождаться от: develop
Должны вливаться в: develop и master
Соглашение о наименовании: release-*

Ветвь релиза создаётся из ветви разработки (develop).
Закрытие ветви релиза
Когда мы решаем, что ветвь релиза (release branch) окончательно готова для выпуска, нужно проделать несколько действий. В первую очередь ветвь релиза вливается в главную ветвь (напоминаю, каждый коммит в master — это по определению новый релиз). Далее, этот коммит в master должен быть помечен тегом, чтобы в дальнейшем можно было легко обратиться к любой существовавшей версии продукта. И наконец, изменения, сделанные в ветви релиза (release branch), должны быть добавлены обратно в разработку (ветвь develop), чтобы будущие релизы также содержали внесённые исправления багов.

Теперь релиз издан и помечен тегом.

Чтобы сохранить изменения и в последующих релизах, мы должны влить эти изменения обратно в разработку. Делаем это так:

git merge --no-ff release-1.2

Merge made by recursive.
(Отчёт об изменениях)

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

Теперь мы окончательно разделались с веткой релиза. Можно её удалять, потому что она нам больше не понадобится:

Deleted branch release-1.2 (was ff452fe).

Ветви исправлений (hotfix branches)
Могут порождаться от: master
Должны вливаться в: develop и master
Соглашение о наименовании: hotfix-*

Ветви исправлений (hotfix branches) создаются из главной (master) ветви.

Заключение

Можно сказать есть такие пути работы с гит:
1) разбить деятельность на задачи, и каждой задаче создать свою ветку, а потом мерджить
2) работать в одной ветке, и обновлять свой локальный репозиторий, с последующим его залитием

Краткая справка команд:

git pull - обновить данные из серверного репозитория
git add - добавить в список "на коммит"
git commit - создание пакета (коммита) с изменениями
git push - залить за серверный (удалённый) репозиторий
git merge BRANCH - слияние ветки в который ты находишься, с веткой BRANCH


Вопросы:
Есть репозиторий, над ним работают два человека: первый клонирует репозиторий, вносит правки и пушит; второй в это же время тоже начал работу, склонировал, но запушить не может, так как 1й уже внес правки. Как быть?

Ответ:
Ты делаешь комит и когда пытается сделать пуш, гит говорит, что надо сначала стянуть изменения. Когда стягиваешь изменения, они автоматом мержатся со своими изменениями и потом уже можешь сделать свой пуш.
Если правите разные файлы или разные строчки в одном и том же файле, то гит смержит изменения автоматически.


Теперь случай посложнее, когда вы правили одни и те же строчки в одних и тех же файлах:

В тех местах, где гит не смог сам смержить 2му придется выбирать что оставить или переписать эти куски так, чтобы работало правильно.

Потом сделать:
git add .
git commit
(в комите можно написать комментарий типа "фикс конфликтов")
git push

После этого ваши изменения будут залиты.

Комментарии:

Отправитель: anonymous git reset --hard HEAD - сброс незакоммиченных изменений

Отправитель: anonymous Спасибо. Кратко и всё по делу.

Отправитель: anonymous ты ты ты ты ты

Отправитель: anko В Git есть специальная команда cherry-pick, которая позволяет вставлять в текущую ветку изменения из любого коммита. Работает она так:
git cherry-pick test

Есть файл который изменяется постоянно при работе самого приложения и его коммитить не нужно. Как сделать чтоб он не коммитился? .gitignore не вариант, так как файл уже создан.

Нужно больше контекста. Что это за файл, почему он постоянно меняется, нужен ли он в гите для корректной работы приложения? Может проще его удалить совсем из репозитория и потом добавить в gitignore, раз приложение может работать без изменений в этом файле. как раз вполне себе вариант. Добавьте этот файл в .gitignore и не забудьте закомитить .gitignore. Чем вас не устраивает gitignore? Создан - и фиг с ним. Нужно добавить в .gitignore и сделать git rm --cached <filename> , подробности в вопросе по ссылке. > .gitignore не вариант, так как файл уже создан. Почему не вариант? Как раз таки вариант, добавить созданный файл в .gitignore.

Предположим, что у Вас имеется следующая папка с файлами (репозиторий) и некоторое количество коммитов:

введите сюда описание изображения

Вы обнаруживаете, что в репозитории лежит файл который совершенно не нужен в проекте.

Исправляем ошибку

Ситуация №1. Ненужный файл уже в коммите

Вам потребуется сначала удалить файл из коммитов. Выполняем команду:

Ссылка на оригинал ответа.

Ситуация №2. Ненужный файл в состоянии stage

Вы выполнили комманду git add * (например) и весь репозиторий оказался в состоянии stage. Команда git status покажет какие файлы в каком состоянии находятся.

введите сюда описание изображения

В этой ситуации необходимо выполнить git rm --cached NOOOO.cpp или git reset NOOOO.cpp . После выполнения команды получим следующий результат:

введите сюда описание изображения

Ситуация №3. Ненужный файл в был создан но не попал в поле зрения git

В этой ситуации Вам нужно перейти к следующему пункту :).

Избегаем будущих ошибок

Теперь мы избавились от ненужного файла в коммитах существующих или в области stage. Нужно теперь сделать так, чтобы гит не "видел файл".

Создаем .gitignore (на win можно создать через .gitignore. ). добавляем в него следующую строку и сохраняем:

Теперь нужно, чтобы git проиндексировал gitignore. для этого занесем его в новый коммит:

После этого git будет сообщать, что новых файлов нету:

введите сюда описание изображения


2,162 2 2 золотых знака 15 15 серебряных знаков 27 27 бронзовых знаков

Если вы хотите прекратить отслеживать изменения в каком-либо файл в репозитории git, но файл .gitignore по каким-либо причинам не подходит — например, файл является довольно специфическим для конкретного проекта и на других компьютерах не возникает (скажем, временные тестовые файлы, полезные только единственному участнику), можно воспользоваться файлом .git/info/exclude . Он должен находиться в скрытом внутреннем каталоге git'а, его синтаксис и семантика точно такая же, как и у gitignore. Единственное различие — он является локальным для репозитория, его содержимое видно только его владельцу.

Ещё есть глобальная версия этого файла. Она используется для всех репозиториев пользователя и по умолчанию находится в

/.config/git/ignore (путь можно изменить настройкой core.excludesFile ). Тут целесообразно указывать временные файлы вашей любимой IDE, как пример.

Подробнее про обработку всех подобных файлов: классического .gitignore , а так же вышеупомянутых .git/info/exclude и

/.config/git/ignore — смотрите руководство gitignore(5). Там же описаны все вариации именования этих файлов.

Итак, у вас имеется настоящий Git-репозиторий и рабочая копия файлов для некоторого проекта. Вам нужно делать некоторые изменения и фиксировать «снимки» состояния (snapshots) этих изменений в вашем репозитории каждый раз, когда проект достигает состояния, которое вам хотелось бы сохранить.

Запомните, каждый файл в вашем рабочем каталоге может находиться в одном из двух состояний: под версионным контролем (отслеживаемые) и нет (неотслеживаемые). Отслеживаемые файлы — это те файлы, которые были в последнем снимке состояния проекта; они могут быть неизменёнными, изменёнными или подготовленными к коммиту. Если кратко, то отслеживаемые файлы — это те файлы, о которых знает Git.

Неотслеживаемые файлы — это всё остальное, любые файлы в вашем рабочем каталоге, которые не входили в ваш последний снимок состояния и не подготовлены к коммиту. Когда вы впервые клонируете репозиторий, все файлы будут отслеживаемыми и неизменёнными, потому что Git только что их извлек и вы ничего пока не редактировали.

Как только вы отредактируете файлы, Git будет рассматривать их как изменённые, так как вы изменили их с момента последнего коммита. Вы индексируете эти изменения, затем фиксируете все проиндексированные изменения, а затем цикл повторяется.

Жизненный цикл состояний файлов

Определение состояния файлов

Основной инструмент, используемый для определения, какие файлы в каком состоянии находятся — это команда git status . Если вы выполните эту команду сразу после клонирования, вы увидите что-то вроде этого:

Это означает, что у вас чистый рабочий каталог, другими словами — в нем нет отслеживаемых измененных файлов. Git также не обнаружил неотслеживаемых файлов, в противном случае они бы были перечислены здесь. Наконец, команда сообщает вам на какой ветке вы находитесь и сообщает вам, что она не расходится с веткой на сервере. Пока что это всегда ветка master , ветка по умолчанию; в этой главе это не важно. В главе Ветвление в Git будут рассмотрены ветки и ссылки более детально.

Предположим, вы добавили в свой проект новый файл, простой файл README . Если этого файла раньше не было, и вы выполните git status , вы увидите свой неотслеживаемый файл вот так:

Понять, что новый файл README неотслеживаемый можно по тому, что он находится в секции «Untracked files» в выводе команды status . Статус Untracked означает, что Git видит файл, которого не было в предыдущем снимке состояния (коммите); Git не станет добавлять его в ваши коммиты, пока вы его явно об этом не попросите. Это предохранит вас от случайного добавления в репозиторий сгенерированных бинарных файлов или каких-либо других, которые вы и не думали добавлять. Мы хотели добавить README, так давайте сделаем это.

Отслеживание новых файлов

Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда git add . Чтобы начать отслеживание файла README , вы можете выполнить следующее:

Если вы снова выполните команду status , то увидите, что файл README теперь отслеживаемый и добавлен в индекс:

Вы можете видеть, что файл проиндексирован, так как он находится в секции «Changes to be committed». Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды git add , будет добавлена в историю снимков состояния. Как вы помните, когда вы ранее выполнили git init , затем вы выполнили git add (файлы) — это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль. Команда git add принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет все файлы из указанного каталога в индекс.

Индексация изменённых файлов

Давайте модифицируем файл, уже находящийся под версионным контролем. Если вы измените отслеживаемый файл CONTRIBUTING.md и после этого снова выполните команду git status , то результат будет примерно следующим:

Файл CONTRIBUTING.md находится в секции «Changes not staged for commit» — это означает, что отслеживаемый файл был изменён в рабочем каталоге, но пока не проиндексирован. Чтобы проиндексировать его, необходимо выполнить команду git add . Это многофункциональная команда, она используется для добавления под версионный контроль новых файлов, для индексации изменений, а также для других целей, например для указания файлов с исправленным конфликтом слияния. Вам может быть понятнее, если вы будете думать об этом как «добавить этот контент в следующий коммит», а не как «добавить этот файл в проект». Выполним git add , чтобы проиндексировать CONTRIBUTING.md , а затем снова выполним git status :

Теперь оба файла проиндексированы и войдут в следующий коммит. В этот момент вы, предположим, вспомнили одно небольшое изменение, которое вы хотите сделать в CONTRIBUTING.md до коммита. Вы открываете файл, вносите и сохраняете необходимые изменения и вроде бы готовы к коммиту. Но давайте-ка ещё раз выполним git status :

Что за чёрт? Теперь CONTRIBUTING.md отображается как проиндексированный и непроиндексированный одновременно. Как такое возможно? Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду git add . Если вы выполните коммит сейчас, то файл CONTRIBUTING.md попадёт в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду git add , а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения git commit . Если вы изменили файл после выполнения git add , вам придётся снова выполнить git add , чтобы проиндексировать последнюю версию файла:

Сокращенный вывод статуса

Вывод команды git status довольно всеобъемлющий и многословный. Git также имеет флаг вывода сокращенного статуса, так что вы можете увидеть изменения в более компактном виде. Если вы выполните git status -s или git status --short вы получите гораздо более упрощенный вывод:

Новые неотслеживаемые файлы помечены ?? слева от них, файлы добавленные в отслеживаемые помечены A , отредактированные файлы помечены M и так далее. В выводе содержится два столбца — в левом указывается статус файла, а в правом модифицирован ли он после этого. К примеру в нашем выводе, файл README модифицирован в рабочем каталоге, но не проиндексирован, а файл lib/simplegit.rb модифицирован и проиндексирован. Файл Rakefile модифицирован, проиндексирован и ещё раз модифицирован, таким образом на данный момент у него есть те изменения, которые попадут в коммит, и те, которые не попадут.

Игнорирование файлов

Зачастую, у вас имеется группа файлов, которые вы не только не хотите автоматически добавлять в репозиторий, но и видеть в списках неотслеживаемых. К таким файлам обычно относятся автоматически генерируемые файлы (различные логи, результаты сборки программ и т. п.). В таком случае, вы можете создать файл .gitignore . с перечислением шаблонов соответствующих таким файлам. Вот пример файла .gitignore :

Первая строка предписывает Git игнорировать любые файлы заканчивающиеся на «.o» или «.a» — объектные и архивные файлы, которые могут появиться во время сборки кода. Вторая строка предписывает игнорировать все файлы заканчивающиеся на тильду (

), которая используется во многих текстовых редакторах, например Emacs, для обозначения временных файлов. Вы можете также включить каталоги log, tmp или pid; автоматически создаваемую документацию; и т. д. и т. п. Хорошая практика заключается в настройке файла .gitignore до того, как начать серьёзно работать, это защитит вас от случайного добавления в репозиторий файлов, которых вы там видеть не хотите.

К шаблонам в файле .gitignore применяются следующие правила:

Стандартные шаблоны являются глобальными и применяются рекурсивно для всего дерева каталогов.

Чтобы избежать рекурсии используйте символ слеш (/) в начале шаблона.

Чтобы исключить каталог добавьте слеш (/) в конец шаблона.

Можно инвертировать шаблон, использовав восклицательный знак (!) в качестве первого символа.

Glob-шаблоны представляют собой упрощённые регулярные выражения, используемые командными интерпретаторами. Символ ( * ) соответствует 0 или более символам; последовательность [abc] — любому символу из указанных в скобках (в данном примере a, b или c); знак вопроса ( ? ) соответствует одному символу; и квадратные скобки, в которые заключены символы, разделённые дефисом ( 1 ), соответствуют любому символу из интервала (в данном случае от 0 до 9). Вы также можете использовать две звёздочки, чтобы указать на вложенные каталоги: a/**/z соответствует a/z , a/b/z , a/b/c/z , и так далее.

Вот ещё один пример файла .gitignore :

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

Детальное рассмотрение использования нескольких .gitignore файлов выходит за пределы этой книги; детали доступны в справке man gitignore .

Просмотр индексированных и неиндексированных изменений

Допустим, вы снова изменили и проиндексировали файл README , а затем изменили файл CONTRIBUTING.md без индексирования. Если вы выполните команду git status , вы опять увидите что-то вроде:

Чтобы увидеть, что же вы изменили, но пока не проиндексировали, наберите git diff без аргументов:

Эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса. Результат показывает ещё не проиндексированные изменения.

Если вы хотите посмотреть, что вы проиндексировали и что войдёт в следующий коммит, вы можете выполнить git diff --staged . Эта команда сравнивает ваши проиндексированные изменения с последним коммитом:

Важно отметить, что git diff сама по себе не показывает все изменения сделанные с последнего коммита — только те, что ещё не проиндексированы. Такое поведение может сбивать с толку, так как если вы проиндексируете все свои изменения, то git diff ничего не вернёт.

Другой пример: вы проиндексировали файл CONTRIBUTING.md и затем изменили его, вы можете использовать git diff для просмотра как проиндексированных изменений в этом файле, так и тех, что пока не проиндексированы. Если наше окружение выглядит вот так:

Используйте git diff для просмотра непроиндексированных изменений

а так же git diff --cached для просмотра проиндексированных изменений ( --staged и --cached синонимы):

Мы будем продолжать использовать команду git diff различными способами на протяжении всей книги. Существует еще один способ просматривать эти изменения, если вы предпочитаете графический просмотр или внешнюю программу просмотра различий, вместо консоли. Выполнив команду git difftool вместо git diff , вы сможете просмотреть изменения в файле с помощью таких программ как emerge, vimdiff и других (включая коммерческие продукты). Выполните git difftool --tool-help чтобы увидеть какие из них уже установлены в вашей системе.

Коммит изменений

Теперь, когда ваш индекс находится в таком состоянии, как вам и хотелось, вы можете зафиксировать свои изменения. Запомните, всё, что до сих пор не проиндексировано — любые файлы, созданные или изменённые вами, и для которых вы не выполнили git add после редактирования — не войдут в этот коммит. Они останутся изменёнными файлами на вашем диске. В нашем случае, когда вы в последний раз выполняли git status , вы видели что всё проиндексировано, и вот, вы готовы к коммиту. Простейший способ зафиксировать изменения — это набрать git commit :

Эта команда откроет выбранный вами текстовый редактор.

Редактор устанавливается переменной окружения EDITOR — обычно это vim или emacs, хотя вы можете установить любой другой с помощью команды git config --global core.editor , как было показано в главе Введение).

В редакторе будет отображён следующий текст (это пример окна Vim):

Для ещё более подробного напоминания, что же именно вы поменяли, можете передать аргумент -v в команду git commit . Это приведёт к тому, что в комментарий будет также помещена дельта/diff изменений, таким образом вы сможете точно увидеть все изменения которые вы совершили.

Есть и другой способ — вы можете набрать свой комментарий к коммиту в командной строке вместе с командой commit указав его после параметра -m , как в следующем примере:

Итак, вы создали свой первый коммит! Вы можете видеть, что коммит вывел вам немного информации о себе: на какую ветку вы выполнили коммит ( master ), какая контрольная сумма SHA-1 у этого коммита ( 463dc4f ), сколько файлов было изменено, а также статистику по добавленным/удалённым строкам в этом коммите.

Запомните, что коммит сохраняет снимок состояния вашего индекса. Всё, что вы не проиндексировали, так и висит в рабочем каталоге как изменённое; вы можете сделать ещё один коммит, чтобы добавить эти изменения в репозиторий. Каждый раз, когда вы делаете коммит, вы сохраняете снимок состояния вашего проекта, который позже вы можете восстановить или с которым можно сравнить текущее состояние.

Игнорирование индексации

Несмотря на то, что индекс может быть удивительно полезным для создания коммитов именно такими, как вам и хотелось, он временами несколько сложнее, чем вам нужно в процессе работы. Если у вас есть желание пропустить этап индексирования, Git предоставляет простой способ. Добавление параметра -a в команду git commit заставляет Git автоматически индексировать каждый уже отслеживаемый на момент коммита файл, позволяя вам обойтись без git add :

Обратите внимание, что в данном случае перед коммитом вам не нужно выполнять git add для файла CONTRIBUTING.md , потому что флаг -a включает все файлы. Это удобно, но будьте осторожны: флаг -a может включить в коммит нежелательные изменения.

Удаление файлов

Для того чтобы удалить файл из Git, вам необходимо удалить его из отслеживаемых файлов (точнее, удалить его из вашего индекса) а затем выполнить коммит. Это позволяет сделать команда git rm , которая также удаляет файл из вашего рабочего каталога, так что в следующий раз вы не увидите его как «неотслеживаемый».

Если вы просто удалите файл из своего рабочего каталога, он будет показан в секции «Changes not staged for commit» (измененные, но не проиндексированные) вывода команды git status :

Затем, если вы выполните команду git rm , удаление файла попадёт в индекс:

После следующего коммита файл исчезнет и больше не будет отслеживаться. Если вы изменили файл и уже проиндексировали его, вы должны использовать принудительное удаление с помощью параметра -f . Это сделано для повышения безопасности, чтобы предотвратить ошибочное удаление данных, которые ещё не были записаны в снимок состояния и которые нельзя восстановить из Git.

Другая полезная штука, которую вы можете захотеть сделать — это удалить файл из индекса, оставив его при этом в рабочем каталоге. Другими словами, вы можете захотеть оставить файл на жёстком диске, но перестать отслеживать изменения в нём. Это особенно полезно, если вы забыли добавить что-то в файл .gitignore и по ошибке проиндексировали, например, большой файл с логами, или кучу промежуточных файлов компиляции. Чтобы сделать это, используйте опцию --cached :

В команду git rm можно передавать файлы, каталоги или шаблоны. Это означает, что вы можете сделать что-то вроде:

Обратите внимание на обратный слеш ( \ ) перед * . Он необходим из-за того, что Git использует свой собственный обработчик имён файлов вдобавок к обработчику вашего командного интерпретатора. Эта команда удаляет все файлы, имеющие расширение .log и находящиеся в каталоге log/ . Или же вы можете сделать вот так:

Эта команда удаляет все файлы, имена которых заканчиваются на

Перемещение файлов

В отличие от многих других систем контроля версий, Git не отслеживает перемещение файлов явно. Когда вы переименовываете файл в Git, в нём не сохраняется никаких метаданных, говорящих о том, что файл был переименован. Однако, Git довольно умён в плане обнаружения перемещений постфактум — мы рассмотрим обнаружение перемещения файлов чуть позже.

Таким образом, наличие в Git команды mv выглядит несколько странным. Если вам хочется переименовать файл в Git, вы можете сделать что-то вроде:

и это отлично сработает. На самом деле, если вы выполните что-то вроде этого и посмотрите на статус, вы увидите, что Git считает, что произошло переименование файла:

Однако, это эквивалентно выполнению следующих команд:

Git неявно определяет, что произошло переименование, поэтому неважно, переименуете вы файл так или используя команду mv . Единственное отличие состоит лишь в том, что mv — одна команда вместо трёх — это функция для удобства. Важнее другое — вы можете использовать любой удобный способ для переименования файла, а затем воспользоваться командами add/rm перед коммитом.

Создать репозиторий для проекта на лабораторные работы. Репозиторий должен содержать исходный код, конфигурационный файл .clang-format , файл .gitignore и простейший Makefile . Отработать этапы создания коммита и просмотр истории репозитория.

Подготовка к работе¶

Формат вывода команды git log по умолчанию не очень удобен для анализа.

В качестве альтернативы можно запускать git log с несколькими параметрами:

Описание используемых параметров доступно в мануале команды git log.

Для упрощения ввода команды, можно создать алиас (синоним). Для этого нужно выполнить в терминале:

После чего станет доступна команда git hist :

Подробнее об алиасах: Git Aliases.

Make — утилита для преобразования файлов из одной формы в другую. Чаще всего применяется для сборки приложений.

Мейкфайл состоит из правил вида:

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

  • <зависимость> — имя входного файла, необходимого для получения целевого файла. В простейшем случае — имя файла с исходным кодом.

  • <команды> — инструкции командной оболочки. В простейшем случае — запуск компилятора.

В качестве отступа перед командами используется один символ табуляции.

.gitignore¶

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

Артефакты сборки: исполняемые файлы, объектные файлы *.o .

Бекап-файлы используемого текстового редактора ( .main.c.swp , main.c

Специфичные для пользователя настройки среды разработки или специфичные для платформы проектные файлы.

Для того, чтобы такие файлы не были закоммичены случайно, а также не отображались в выводе команды git status, используется файл .gitignore . В него записываются имена и маски файлов, которые git должен игнорировать.

Содержание коммитов¶

Основной принцип: один коммит включает в себя только одно изменение. Изменения в каждом коммите самодостаточны и независимы.

Нарушение этого принципа легко заметить при написании заголовка коммита. Если заголовок выглядит как «Format source code AND implement user input validation AND fix crash», значит один коммит включает в себя слишком много изменений. В данном примере изменения следует разделить на три коммита.

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

Оформление коммитов¶

Заголовок коммита пишется на английском языке, в императиве. Начинается с заглавной буквы, точка в конце не ставится.

Неправильно: implemented request handling.

Правильно: Implement request handling

Перемещение по истории коммитов¶

Для перемещения по истории коммитов необходимо, чтобы все изменения были закоммичены. Т.е. не должно быть файлов в состоянии modified или staged .

Один из способов перемещения по истории — использование команды git checkout.

Руководство¶

Не следует коммитить артефакты сборки (исполняемые и объектные файлы).

Во время выполнения работы до и после команд git add, git commit следует выполнять git status и git hist и анализировать их вывод.

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

Ввод и вывод окружностей в формате WKT, проверка корректности входных данных.

Вывод исходного состояния шахматной доски в текстовом формате и/или в формате html.

Добавьте в репозиторий файл .clang-format из предыдущей работы:

Реализуйте часть приложения в соответствии с выбранным вариантом.

Напишите простейший Makefile для сборки приложения. Приложение следует компилировать с опциями -Wall -Werror . Компиляция должна проходить без ошибок.

Добавьте в репозиторий файл .gitignore , настройте игнорирование файлов.

Загрузите изменения на GitHub. После завершения работы назначте ее на ревью своему преподавателю практики.

Локально отработайте перемещение по истории репозитория. Переместитесь по истории к первому коммиту. Посмотрите содержимое файлов. Вернитесь к последнему коммиту.

Пример содержания коммитов:

Создание приложения «Hello, World».

Реализация функции вывода доски в stdout .

Контрольные вопросы¶

Что такое коммит?

Этапы создания коммита.

В каких состояниях может находиться файл в репозитории? Как происходит изменение состояния файла?

Читайте также: