Перейти к содержимому

Как зафиксировать изменения в git

  • автор:

Создание фиксации Git в Visual Studio

Область применения:yesVisual Studio Visual Studio для Mac noVisual Studio Code no

Основная часть любого рабочего процесса Git заключается в изменении файлов и фиксации изменений в этих файлах. Хотя в этой статье рассматриваются репозитории GitHub, вы можете работать удаленно через выбранного поставщика Git, такого как GitHub или Azure DevOps. или локально без каких-либо поставщиков.

GIT отслеживает изменения файлов в репозитории в процессе работы и разделяет файлы на три категории. Это те же изменения, которые отображаются при вводе команды git status в командной строке.

  • Неизмененные файлы: эти файлы не изменились с момента последней фиксации.
  • Измененные файлы: эти файлы имеют изменения с момента последней фиксации, но вы еще не выполнили их для следующей фиксации.
  • Промежуточные файлы: эти файлы имеют изменения, которые будут добавлены в следующую фиксацию.

В процессе работы Visual Studio отслеживает изменения в файлах проекта в разделе Изменения окна Изменения GIT.

The Git Changes window in Visual Studio 2022.

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

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

При подготовке изменения Visual Studio создает раздел Подготовленные изменения. Только изменения из раздела Подготовленные изменения добавляются к следующей фиксации, которую можно выполнить, выбрав команду Зафиксировать промежуточные. Эквивалентная команда для этого действия — git commit -m «Your commit message» .

The Git commit dialog in Visual Studio 2022.

Можно также отменить подготовку изменений, нажав кнопку (минус). Эквивалентная команда для этого действия — git reset для отмены размещения одного файла или git reset для отмены размещения всех файлов в каталоге.

Кроме того, можно отказаться от подготовки измененных файлов, пропустив область подготовки. В этом случае Visual Studio позволяет зафиксировать изменения напрямую без предварительной подготовки. Просто введите сообщение о фиксации и выберите Зафиксировать все. Эквивалентная команда для этого действия — git commit -a .

Visual Studio также позволяет выполнить фиксацию и синхронизацию одним щелчком мыши с помощью ярлыков Зафиксировать все и отправить и Зафиксировать все и синхронизировать. Если дважды щелкнуть любой файл в разделе Изменения или Подготовленные изменения, то можно построчно сравнить измененную версию файла с неизмененной.

The line-by-line comparison of file versions in Visual Studio 2022.

Если дважды щелкнуть фиксацию, в Visual Studio откроются сведения о ней в отдельном окне инструментов. Здесь можно отменить фиксацию, сбросить ее, исправить сообщение о фиксации или создать тег для нее. Если щелкнуть измененный файл в фиксации, в Visual Studio откроется инструмент сравнения, в котором рядом друг с другом показаны фиксация и ее предок.

The Commit Details dialog in Visual Studio 2022.

Связанный контент

  • Этапы строк кода
  • Интерфейс GIT в Visual Studio

Сохранение работы с фиксациями

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

В этой статье приведены процедуры для выполнения следующих задач:

  • Как Git отслеживает изменения
  • Что находится в фиксации
  • Как подготовить изменения
  • Создание фиксации
  • Обновление последней фиксации

Общие сведения о рабочем процессе Git см. в руководстве по Azure Repos Git.

Как Git отслеживает изменения

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

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

Снимок экрана: жизненный цикл файлов в репозитории между тремя состояниями.

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

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

Что находится в фиксации

Каждая фиксация содержит следующие сведения:

  • Snapshot всех отслеживаемых файлов в репозитории во время фиксации. Snapshot не является разницей между фиксациями, хотя Git использует моментальные снимки для вычисления разницы. Моментальные снимки обеспечивают быстрое переключение между ветвями и поддерживают слияние ветвей.
  • Ссылка на родительские фиксации. Большинство фиксаций имеют один родительский элемент, но следующая фиксация после слияния ветвей имеет несколько родительских элементов, а первая фиксация в репозитории не имеет никакого значения.
  • Сообщение, описывающее изменения в фиксации. Вы вводите сообщение при создании фиксации.

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

Как подготовить изменения

Чтобы создать snapshot для фиксации, выполните приведенные далее действия.

  • Подготовьте новые файлы, чтобы сообщить Git, что вы хотите добавить их в snapshot, и вы хотите, чтобы Git отслеживал изменения в этих файлах в будущем.
  • Подготовьте измененные файлы, чтобы сообщить Git, что вам нужна измененная версия файла в snapshot, а не не измененная версия файла.
  • Подготовьте удаленные файлы, чтобы сообщить Git, что вы хотите удалить их из snapshot и больше не отслеживать.

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

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

  • Visual Studio 2022
  • Visual Studio 2019 — меню Git
  • Visual Studio 2019 — командная Обозреватель
  • Командная строка Git

Visual Studio 2022 предоставляет возможности управления версиями Git с помощью меню Git, изменений Git и контекстных меню в Обозреватель решений. Visual Studio 2019 версии 16.8 также предлагает пользовательский интерфейс Git для команды Обозреватель. Дополнительные сведения см. на вкладке Visual Studio 2019 — team Обозреватель.

В окне Изменения Git щелкните правой кнопкой мыши файл в разделе Изменения и выберите Этап , чтобы добавить его в раздел Промежуточные изменения .

Снимок экрана: параметр

Вы также можете создать измененный файл, щелкнув знак «плюс» рядом с файлом. Чтобы подготовить все измененные файлы в папке, щелкните знак «плюс» рядом с папкой. Чтобы подготовить все измененные файлы в репозитории, выберите знак «плюс» в правом верхнем углу раздела Изменения .

Вы можете указать Git игнорировать файл, щелкнув его правой кнопкой мыши и выбрав Пропустить этот локальный элемент или Пропустить это расширение. Любая команда создает GITIGNORE-файл в репозитории, если он не существует, и добавляет в него запись. Пропущенные файлы не будут отображаться в разделе Изменения в Visual Studio. Однако файл .gitignore не влияет на отслеживаемые файлы. Сведения о том, как настроить Git для игнорирования отслеживаемых файлов, см. в разделе Игнорировать файлы. Чтобы сэкономить время, можно скачать шаблоны .gitignore для различных сред разработки из репозитория GitHub gitignore .

Начиная с Visual Studio 2022 версии 17.3, Visual Studio поддерживает промежуточные частичные изменения в файле. Дополнительные сведения см. в разделе Этап строк кода в Visual Studio.

Visual Studio 2019 предоставляет возможности управления версиями Git с помощью меню Git, изменений Git и контекстных меню в Обозреватель решений.

В окне Изменения Git щелкните правой кнопкой мыши файл в разделе Изменения и выберите Этап , чтобы добавить его в раздел Промежуточные изменения .

Снимок экрана: параметр

Вы также можете создать измененный файл, щелкнув знак «плюс» рядом с файлом. Чтобы подготовить все измененные файлы в папке, щелкните знак «плюс» рядом с папкой. Чтобы подготовить все измененные файлы в репозитории, выберите знак «плюс» в правом верхнем углу раздела Изменения .

Вы можете указать Git игнорировать файл, щелкнув его правой кнопкой мыши и выбрав Пропустить этот локальный элемент или Пропустить это расширение. Любая команда создает GITIGNORE-файл в репозитории, если он не существует, и добавляет в него запись. Пропущенные файлы не будут отображаться в разделе Изменения в Visual Studio. Однако файл .gitignore не влияет на отслеживаемые файлы. Сведения о том, как настроить Git для игнорирования отслеживаемых файлов, см. в разделе Игнорировать файлы. Чтобы сэкономить время, можно скачать шаблоны .gitignore для различных сред разработки из репозитория GitHub gitignore .

Visual Studio 2019 версии 16.8 и более поздних версий предоставляет возможности управления версиями Git при сохранении пользовательского интерфейса Team Обозреватель Git. Чтобы использовать командную Обозреватель, снимитефлажокСервис> Параметры >Предварительный просмотр функций>Новый пользовательский интерфейс Git в строке меню. Функции Git можно использовать из любого интерфейса взаимозаменяемо.

  1. В командной Обозреватель нажмите кнопку Домой и выберите Изменения. Снимок экрана: параметр
  2. В представлении Изменения щелкните правой кнопкой мыши файл в разделе Изменения и выберите Этап , чтобы добавить его в раздел Промежуточные изменения . Снимок экрана: контекстное меню с параметром Вы также можете создать измененный файл, перетащив его из раздела Изменения в раздел Промежуточные изменения . Чтобы подготовить все измененные файлы в папке, щелкните правой кнопкой мыши папку и выберите пункт Этап. Чтобы подготовить все измененные файлы в репозитории, выберите знак «плюс» в правом верхнем углу раздела Изменения .

Вы можете указать Git игнорировать файл, щелкнув его правой кнопкой мыши и выбрав Пропустить этот локальный элемент или Пропустить это расширение. Любая команда создает GITIGNORE-файл в репозитории, если он не существует, и добавляет в него запись. Пропущенные файлы не будут отображаться в разделе Изменения в Visual Studio. Однако файл .gitignore не влияет на отслеживаемые файлы. Сведения о том, как настроить Git для игнорирования отслеживаемых файлов, см. в разделе Игнорировать файлы. Чтобы сэкономить время, можно скачать шаблоны .gitignore для различных сред разработки из репозитория GitHub gitignore .

Visual Studio 2019 не поддерживает промежуточные частичные изменения в файле.

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

git add --all 

Изменения в определенных файлах можно выполнить с помощью следующей команды.

git add

Вы можете в интерактивном режиме подготовить части измененного файла с помощью —patch параметра .

git add --patch

Другие связанные команды Git:

  • git rm для удаления файлов в репозитории и поэтапного изменения.
  • git mv для перемещения или переименования файлов в репозитории и поэтапного изменения.
  • git status для просмотра текущего состояния изменений в репозитории.

После промежуточной подготовки файлов просмотрите промежуточные и незамеченные изменения, выполнив команду git status .

Создание фиксации

  • Visual Studio 2022
  • Visual Studio 2019 — меню Git
  • Visual Studio 2019 — Обозреватель команды
  • Командная строка Git

В окне Git Changes (Изменения Git ) введите сообщение с описанием промежуточных изменений, а затем выберите Зафиксировать промежуточные изменения.

Снимок экрана: ссылка на сведения о фиксации в Visual Studio.

Щелкните ссылку фиксации для сведений о фиксации.

Снимок экрана: ссылка сведений о фиксации в окне

Если все изменения не имеют тегов, можно пропустить промежуточную и прямую фиксацию, выбрав Зафиксировать все.

Снимок экрана: параметр

В окне Git Changes (Изменения Git ) введите сообщение с описанием промежуточных изменений, а затем выберите Зафиксировать промежуточные изменения.

Снимок экрана: ссылка на сведения о фиксации в Visual Studio.

Щелкните ссылку фиксации для сведений о фиксации.

Снимок экрана: ссылка сведений о фиксации в окне

Если все изменения не имеют тегов, можно пропустить промежуточную и прямую фиксацию, выбрав Зафиксировать все.

Снимок экрана: параметр

  1. В представлении Изменениякоманды Обозреватель введите сообщение с описанием промежуточных изменений, а затем выберите Зафиксировать поэтапно. Снимок экрана: текст сообщения о фиксации и кнопка
  2. Щелкните ссылку фиксации для сведений о фиксации. Снимок экрана: ссылка на сведения о фиксации в

Снимок экрана: параметр

Примечание Если все изменения не имеют тегов, можно пропустить промежуточную и прямую фиксацию, выбрав Зафиксировать все.

Вы можете создать фиксацию git commit с помощью команды с -m флагом , чтобы указать сообщение фиксации. Если вы не предоставите сообщение о фиксации, Git откроет редактор, чтобы вы могли его предоставить.

git commit -m "" 

Перед фиксацией просмотрите промежуточные и незамеченные изменения, выполнив команду git status .

Обновление последней фиксации

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

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

  • Создайте и отправьте другую фиксацию, которая устраняет проблемы, вызванные предыдущей фиксацией.
  • Отмените отправленную ранее фиксацию, используя git revert для создания новой фиксации, которая отменяет все изменения, внесенные предыдущей фиксацией. Затем отправьте новую фиксацию.
  • Visual Studio 2022
  • Visual Studio 2019 — меню Git
  • Visual Studio 2019 — Обозреватель команды
  • Командная строка Git

В окне Git Changes (Изменения Git ) при необходимости разверните один или несколько файлов, введите сообщение о фиксации, нажмите кнопку Изменить, а затем выберите Зафиксировать поэтапно.

Снимок экрана: параметр

Окно «Изменения Git» поддерживает изменение сообщения фиксации, промежуточных файлов или и того, и другого. При нажатии кнопки Изменить отображается идентификатор SHA для предыдущей фиксации.

В окне Git Changes (Изменения Git ) при необходимости разверните один или несколько файлов, введите сообщение о фиксации, нажмите кнопку Изменить, а затем выберите Зафиксировать поэтапно.

Снимок экрана: параметр

Окно «Изменения Git» поддерживает изменение сообщения фиксации, промежуточных файлов или и того, и другого. При нажатии кнопки Изменить отображается идентификатор SHA для предыдущей фиксации.

В представлении Изменениякоманды Обозреватель на этапе одного или нескольких файлов введите сообщение о фиксации, а затем выберите Действия > Изменить предыдущую фиксацию.

Снимок экрана: параметр

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

  1. Подготовьте новые изменения, если таковые есть.
  2. git commit Используйте команду с параметром —amend и флагом -m , чтобы указать новое сообщение о фиксации.
git commit --amend -m "" 

2.2 Основы Git — Запись изменений в репозиторий

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

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

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

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

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

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

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

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

$ git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working tree clean

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

Примечание

В 2020 году GitHub изменил имя ветки по умолчанию с master на main , другие же git-хостинг платформы последовали этому примеру. Поэтому, вы можете обнаружить, что ветка по умолчанию для новых репозиториев — main , а не master . Более того, имя ветки по умолчанию можно изменить (как вы видели в Настройка ветки по умолчанию), поэтому вам может встретиться и другое имя. При этом Git продолжает использовать имя master , поэтому далее в книге мы используем именно его.

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

$ echo 'My Project' > README $ git status On branch master Your branch is up-to-date with 'origin/master'. Untracked files: (use "git add . " to include in what will be committed) README nothing added to commit but untracked files present (use "git add" to track)

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

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

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

$ git add README

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

$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git restore --staged . " to unstage) new file: README

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

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

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

$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) new file: README Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: CONTRIBUTING.md

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

$ git add CONTRIBUTING.md $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) new file: README modified: CONTRIBUTING.md

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

$ vim CONTRIBUTING.md $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) new file: README modified: CONTRIBUTING.md Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: CONTRIBUTING.md

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

$ git add CONTRIBUTING.md $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) new file: README modified: CONTRIBUTING.md

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

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

$ git status -s M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt

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

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

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

$ cat .gitignore *.[oa] *~

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

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

  • Пустые строки, а также строки, начинающиеся с # , игнорируются.
  • Стандартные шаблоны являются глобальными и применяются рекурсивно для всего дерева каталогов.
  • Чтобы избежать рекурсии используйте символ слеш (/) в начале шаблона.
  • Чтобы исключить каталог добавьте слеш (/) в конец шаблона.
  • Можно инвертировать шаблон, использовав восклицательный знак (!) в качестве первого символа.

Glob-шаблоны представляют собой упрощённые регулярные выражения, используемые командными интерпретаторами. Символ ( * ) соответствует 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 # Игнорировать все .txt файлы в каталоге doc/ doc/**/*.txt

GitHub поддерживает довольно полный список примеров .gitignore файлов для множества проектов и языков https://github.com/github/gitignore это может стать отправной точкой для .gitignore в вашем проекте.

Примечание

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

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

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

Если результат работы команды git status недостаточно информативен для вас — вам хочется знать, что конкретно поменялось, а не только какие файлы были изменены — вы можете использовать команду git diff . Позже мы рассмотрим команду git diff подробнее; вы, скорее всего, будете использовать эту команду для получения ответов на два вопроса: что вы изменили, но ещё не проиндексировали, и что вы проиндексировали и собираетесь включить в коммит. Если git status отвечает на эти вопросы в самом общем виде, перечисляя имена файлов, git diff показывает вам непосредственно добавленные и удалённые строки — патч как он есть.

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

$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) modified: README Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: CONTRIBUTING.md

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

$ git diff diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ebb991..643e24f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,8 @@ branch directly, things can get messy. Please include a nice description of your changes when you submit your PR; if we have to read the whole diff to figure out why you're contributing in the first place, you're less likely to get feedback and have your change -merged in. +merged in. Also, split your changes into comprehensive chunks if you patch is +longer than a dozen lines. If you are starting to work on a particular area, feel free to submit a PR that highlights your work in progress (and note in the PR title that it's

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

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

$ git diff --staged diff --git a/README b/README new file mode 100644 index 0000000..03902a1 --- /dev/null +++ b/README @@ -0,0 +1 @@ +My Project

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

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

$ git add CONTRIBUTING.md $ echo '# test line' >> CONTRIBUTING.md $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) modified: CONTRIBUTING.md Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: CONTRIBUTING.md

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

$ git diff diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 643e24f..87f08c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -119,3 +119,4 @@ at the ## Starter Projects See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md). +# test line

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

$ git diff --cached diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ebb991..643e24f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,8 @@ branch directly, things can get messy. Please include a nice description of your changes when you submit your PR; if we have to read the whole diff to figure out why you're contributing in the first place, you're less likely to get feedback and have your change -merged in. +merged in. Also, split your changes into comprehensive chunks if you patch is +longer than a dozen lines. If you are starting to work on a particular area, feel free to submit a PR that highlights your work in progress (and note in the PR title that it's

Примечание
Git Diff во внешних инструментах

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

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

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

$ git commit

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

Примечание

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

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

# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Your branch is up-to-date with 'origin/master'. # # Changes to be committed: # new file: README # modified: CONTRIBUTING.md # ~ ~ ~ ".git/COMMIT_EDITMSG" 9L, 283C

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

Примечание

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

Когда вы выходите из редактора, Git создаёт для вас коммит с этим сообщением, удаляя комментарии и вывод команды diff .

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

$ git commit -m "Story 182: fix benchmarks for speed" [master 463dc4f] Story 182: fix benchmarks for speed 2 files changed, 2 insertions(+) create mode 100644 README

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

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

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

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

$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: CONTRIBUTING.md no changes added to commit (use "git add" and/or "git commit -a") $ git commit -a -m 'Add new benchmarks' [master 83e38c7] Add new benchmarks 1 file changed, 5 insertions(+), 0 deletions(-)

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

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

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

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

$ rm PROJECTS.md $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes not staged for commit: (use "git add/rm . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) deleted: PROJECTS.md no changes added to commit (use "git add" and/or "git commit -a")

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

$ git rm PROJECTS.md rm 'PROJECTS.md' $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) deleted: PROJECTS.md

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

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

$ git rm --cached README

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

$ git rm log/\*.log

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

$ git rm \*~

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

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

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

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

$ git mv file_from file_to

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

$ git mv README.md README $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) renamed: README.md -> README

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

$ mv README.md README $ git rm README.md $ git add README

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

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

Итак, у вас имеется настоящий репозиторий Git и рабочая копия файлов для некоторого проекта. Вам нужно делать некоторые изменения и фиксировать “снимки” состояния (snapshots) этих изменений в вашем репозитории каждый раз, когда проект достигает состояния, которое вам хотелось бы сохранить. Запомните, каждый файл в вашем рабочем каталоге может находиться в одном из двух состояний: под версионным контролем (отслеживаемые) и нет (неотслеживаемые). Отслеживаемые файлы — это те файлы, которые были в последнем слепке состояния проекта (snapshot); они могут быть неизмененными, измененными или подготовленными к коммиту (staged). Неотслеживаемые файлы — это всё остальное, любые файлы в вашем рабочем каталоге, которые не входили в ваш последний слепок состояния и не подготовлены к коммиту. Когда вы впервые клонируете репозиторий, все файлы будут отслеживаемыми и неизмененные, потому что вы только взяли их из хранилища (checked them out) и ничего пока не редактировали. Как только вы отредактируете файлы, Git будет рассматривать их как измененные, т.к. вы изменили их с момента последнего коммита. Вы индексируете (stage) эти изменения и затем фиксируете все индексированные изменения, а затем цикл повторяется. Этот жизненный цикл изображен на Рисунке 2-1.

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

Рисунок 2-1. Жизненный цикл состояния ваших файлов

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

Основной инструмент, используемый для определения какие файлы в каком состоянии находятся — это команда git status . Если вы выполните эту команду сразу после клонирования, вы увидите что-то вроде этого: $ git status # On branch master nothing to commit (working directory clean) Это означает, что у вас чистый рабочий каталог, другими словами — в нем нет отслеживаемых измененных файлов. Git также не обнаружил неотслеживаемых файлов, в противном случае они бы были перечислены здесь. И наконец, команда сообщает вам на какой ветке (branch) вы сейчас находитесь. Пока что это всегда ветка master — это ветка по умолчанию; в этой главе это не важно. В следующей главе будет подробно рассказано про ветки и ссылки. Предположим, вы добавили новый файл в ваш проект, простой README файл. Если этого файла раньше не было, и вы выполните git status , вы увидите неотслеживаемый файл как-то так: $ vim README $ git status # On branch master # Untracked files: # (use «git add . » to include in what will be committed) # # README nothing added to commit but untracked files present (use «git add» to track) Вы можете видеть, что новый файл README неотслеживаемый, т.к. он находится в секции “ Untracked files ” в выводе команды status . Неотслеживаемый файл обычно означает, что Git нашел файл, отсутствующий в предыдущем снимке состояния (коммите); Git не станет добавлять его в ваши коммиты, пока вы явно ему это не укажете. Это предохраняет вас от случайного добавления в репозиторий сгенерированных двоичных файлов или каких-либо других, которые вы и не думали добавлять. Вы хотите добавить README , так что давайте сделаем это.

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

Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда git add . Чтобы начать отслеживание файла README , вы можете выполнить следующее: $ git add README Если вы снова выполните команду status , то увидите, что файл README теперь отслеживаемый и индексированный: $ git status # On branch master # Changes to be committed: # (use «git reset HEAD . » to unstage) # # new file: README # Вы можете видеть, что файл проиндексирован по тому, что он находится в секции “ Changes to be committed ”. Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды git add , будет добавлена в историю снимков состояния. Как вы помните, когда вы ранее выполнили git init , вы затем выполнили git add (files) — это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль. Команда git add принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет (индексирует) все файлы в данном каталоге.

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

Давайте модифицируем файл уже находящийся под версионным контролем. Если вы измените отслеживаемый файл benchmarks.rb , и после этого снова выполните команду status , то результат будет примерно следующим: $ git status # On branch master # Changes to be committed: # (use «git reset HEAD . » to unstage) # # new file: README # # Changed but not updated: # (use «git add . » to update what will be committed) # # modified: benchmarks.rb # Файл benchmarks.rb находится в секции “ Changed but not updated ” — это означает, что отслеживаемый файл был изменен в рабочем каталоге, но пока не проиндексирован. Чтобы проиндексировать его, необходимо выполнить команду git add (это многофункциональная команда, она используется для добавления под версионный контроль новых файлов, для индексации изменений, а также для других целей, например для указания файлов с исправленным конфликтом слияния). Выполним git add , чтобы проиндексировать benchmarks.rb , а затем снова выполним git status : $ git add benchmarks.rb $ git status # On branch master # Changes to be committed: # (use «git reset HEAD . » to unstage) # # new file: README # modified: benchmarks.rb # Теперь оба файла проиндексированы и войдут в следующий коммит. В этот момент, вы, предположим, вспомнили одно небольшое изменение, которое вы хотите сделать в benchmarks.rb до фиксации. Вы открываете файл, вносите и сохраняете необходимые изменения и вроде бы готовы к коммиту. Но давайте-ка еще раз выполним git status : $ vim benchmarks.rb $ git status # On branch master # Changes to be committed: # (use «git reset HEAD . » to unstage) # # new file: README # modified: benchmarks.rb # # Changed but not updated: # (use «git add . » to update what will be committed) # # modified: benchmarks.rb # Что за черт? Теперь benchmarks.rb отображается как проиндексированный и непроиндексированный одновременно. Как такое возможно? Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду git add . Если вы выполните коммит сейчас, то файл benchmarks.rb попадет в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду git add , а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения git commit . Если вы изменили файл после выполнения git add , вам придется снова выполнить git add , чтобы проиндексировать последнюю версию файла: $ git add benchmarks.rb $ git status # On branch master # Changes to be committed: # (use «git reset HEAD . » to unstage) # # new file: README # modified: benchmarks.rb #

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

  1. Пустые строки, а также строки начинающиеся с # игнорируются.
  2. Можно использовать стандартные glob шаблоны.
  3. Можно заканчивать шаблон символом слэша ( / ) для указания каталога.
  4. Можно инвертировать шаблон, использовав восклицательный знак ( ! ) в качестве первого символа.

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

Если результат работы команды git status недостаточно информативен для вас — вам хочется знать, что конкретно поменялось, а не только какие файлы были изменены — вы можете использовать команду git diff . Позже мы рассмотрим команду git diff подробнее; вы, скорее всего, будете использовать эту команду для получения ответов на два вопроса: что вы изменили но еще не проиндексировали, и что вы проиндексировали и собираетесь фиксировать. Если git status отвечает на эти вопросы слишком обобщенно, то git diff показывает вам непосредственно добавленные и удаленные строки — собственно заплатку ( patch ). Допустим, вы снова изменили и проиндексировали файл README , а затем изменили файл benchmarks.rb без индексирования. Если вы выполните команду status , вы опять увидите что-то вроде: $ git status # On branch master # Changes to be committed: # (use «git reset HEAD . » to unstage) # # new file: README # # Changed but not updated: # (use «git add . » to update what will be committed) # # modified: benchmarks.rb # Чтобы увидеть, что же вы изменили, но пока не проиндексировали, наберите git diff без аргументов: $ git diff diff —git a/benchmarks.rb b/benchmarks.rb index 3cb747f..da65585 100644 — a/benchmarks.rb +++ b/benchmarks.rb @@ -36,6 +36,10 @@ def main @commit.parents[0].parents[0].parents[0] end + run_code(x, ‘commits 1’) do + git.commits.size + end + run_code(x, ‘commits 2’) do log = git.commits(‘master’, 15) log.size Эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса. Результат показывает еще не проиндексированные изменения. Если вы хотите посмотреть, что вы проиндексировали и что войдет в следующий коммит, вы можете выполнить git diff —cached . (В Git версии 1.6.1 и выше, вы также можете использовать git diff —staged , которая легче запоминается.) Эта команда сравнивает ваши индексированные изменения с последним коммитом: $ git diff —cached diff —git a/README b/README new file mode 100644 index 0000000..03902a1 — /dev/null +++ b/README2 @@ -0,0 +1,5 @@ +grit + by Tom Preston-Werner, Chris Wanstrath + http://github.com/mojombo/grit + +Grit is a Ruby library for extracting information from a Git repository Важно отметить, что git diff сама по себе не показывает все изменения сделанные с последнего коммита — только те, что еще не проиндексированы. Такое поведение может сбивать с толку, так как если вы проиндексируете все свои изменения, то git diff ничего не вернет. Другой пример, вы проиндексировали файл benchmarks.rb и затем изменили его, вы можете использовать git diff для просмотра как индексированных изменений в этом файле, так и тех, что пока не проиндексированны: $ git add benchmarks.rb $ echo ‘# test line’ >> benchmarks.rb $ git status # On branch master # # Changes to be committed: # # modified: benchmarks.rb # # Changed but not updated: # # modified: benchmarks.rb # Теперь вы можете используя git diff посмотреть непроиндексированные изменения $ git diff diff —git a/benchmarks.rb b/benchmarks.rb index e445e28..86b2f7c 100644 — a/benchmarks.rb +++ b/benchmarks.rb @@ -127,3 +127,4 @@ end main() ##pp Grit::GitRuby.cache_client.stats +# test line а также уже проиндексированные, используя git diff —cached : $ git diff —cached diff —git a/benchmarks.rb b/benchmarks.rb index 3cb747f..e445e28 100644 — a/benchmarks.rb +++ b/benchmarks.rb @@ -36,6 +36,10 @@ def main @commit.parents[0].parents[0].parents[0] end + run_code(x, ‘commits 1’) do + git.commits.size + end + run_code(x, ‘commits 2’) do log = git.commits(‘master’, 15) log.size

Фиксация изменений

Теперь, когда ваш индекс настроен так как вам и хотелось, вы можете зафиксировать ваши изменения. Запомните, всё, что до сих пор не проиндексировано — любые файлы, созданные или измененные вами, и для которых вы не выполнили git add после момента редактирования — не войдут в этот коммит. Они останутся измененными файлами на вашем диске. В нашем случае, когда вы в последний раз выполняли git status , вы видели что все проиндексировано, и вот, вы готовы к коммиту. Простейший способ зафиксировать ваши изменения — это набрать git commit : $ git commit Эта команда откроет выбранный вами текстовый редактор. (Редактор устанавливается системной переменной $EDITOR — обычно это vim или emacs , хотя вы можете установить ваш любимый с помощью команды git config —global core.editor как было показано в Главе Введение). В редакторе будет отображен следующий текст (это пример окна Vim-а): # Please enter the commit message for your changes. Lines starting # with ‘#’ will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use «git reset HEAD . » to unstage) # # new file: README # modified: benchmarks.rb ~ ~ ~ «.git/COMMIT_EDITMSG» 10L, 283C Вы можете видеть, что комментарий по умолчанию для коммита содержит закомментированный результат работы (“выхлоп”) команды git status и ещё одну пустую строку сверху. Вы можете удалить эти комментарии и набрать ваше сообщение или же оставить их для напоминания того, что вы фиксируете. (Для еще более подробного напоминания, что же вы именно меняли, вы можете передать аргумент -v в команду git commit . Это приведет к тому, что в комментарий будет помещена также разница/diff ваших изменений, таким образом вы сможете точно увидеть всё что сделано.) Когда вы выходите из редактора, Git создает ваш коммит с этим сообщением (удаляя комментарии и вывод diff -а). Другой способ — вы можете набрать ваш комментарий к коммиту в командной строке вместе с командой commit указав его после параметра -m , как в следующем примере: $ git commit -m «Story 182: Fix benchmarks for speed» [master]: created 463dc4f: «Fix benchmarks for speed» 2 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 README Итак, вы создали свой первый коммит! Вы можете видеть, что коммит вывел вам немного информации о себе: на какую ветку вы выполнили коммит (master), какая контрольная сумма SHA-1 у этого коммита ( 463dc4f ), сколько файлов было изменено, а также статистику по добавленным/удаленным строкам в этом коммите. Запомните, что коммит сохраняет снимок состояния вашего индекса. Все, что вы не проиндексировали, так и торчит в рабочем каталоге как измененное; вы можете сделать еще один коммит, чтобы добавить эти изменения в репозиторий. Каждый раз, когда вы делаете коммит, вы сохраняете снимок состояния вашего проекта, который позже вы можете восстановить, или, с которым можно сравнить текущее состояние.

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

Несмотря на то, что индекс может быть удивительно полезным для создания коммитов именно такими вам и хотелось, он временами несколько сложнее, чем вам нужно в процессе работы. Если у вас есть желание пропустить этап индексирования, Git предоставляет простой способ. Добавление параметра -a в команду git commit заставляет Git автоматически индексировать каждый уже отслеживаемый на момент коммита файл, позволяя вам обойтись без git add : $ git status # On branch master # # Changed but not updated: # # modified: benchmarks.rb # $ git commit -a -m ‘added new benchmarks’ [master 83e38c7] added new benchmarks 1 files changed, 5 insertions(+), 0 deletions(-) Обратите внимание на то, что в данном случае перед коммитом вам не нужно выполнять git add для файла benchmarks.rb .

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

Для того чтобы удалить файл из Git, вам необходимо удалить его из отслеживаемых файлов (точнее, удалить его из вашего индекса) а затем выполнить коммит. Это позволяет сделать команда git rm , которая также удаляет файл из вашего рабочего каталога, так что вы в следующий раз не увидите его как “неотслеживаемый”. Если вы просто удалите файл из вашего рабочего каталога, он будет показан в секции “ Changed but not updated ” (“Измененные но не обновленные” — читай не проиндексированные) вывода команды git status : $ rm grit.gemspec $ git status # On branch master # # Changed but not updated: # (use «git add/rm . » to update what will be committed) # # deleted: grit.gemspec # Затем, если вы выполните команду git rm , удаление файла попадёт в индекс: $ git rm grit.gemspec rm ‘grit.gemspec’ $ git status # On branch master # # Changes to be committed: # (use «git reset HEAD . » to unstage) # # deleted: grit.gemspec # После следующего коммита, файл исчезнет и больше не будет отслеживаться. Если вы изменили файл и уже проиндексировали его, вы должны использовать принудительное удаление с помощью параметра -f . Это сделано для повышения безопасности, чтобы предотвратить ошибочное удаление данных, которые ещё не были записаны в снимок состояния и которые нельзя восстановить из Git. Другая полезная штука, которую вы можете захотеть сделать — это удалить файл из индекса, оставив его при этом в вашем рабочем каталоге. Другими словами, вы можете захотеть оставить файл на вашем винчестере, и убрать его из-под бдительного ока Git-а. Это особенно полезно, если вы забыли добавить что-то в ваш файл .gitignore и по ошибке проиндексировали, например, большой файл с логами, или кучу промежуточных файлов компилляции. Чтобы сделать это, используйте опцию —cached : $ git rm —cached readme.txt В команду git rm вы можете передавать файлы, каталоги или glob-шаблоны. Это означает, что вы можете вытворять что-то вроде: $ git rm log/\*.log Обратите внимание на обратный слэш ( \ ) перед * . Это обязательно, т.к. Git использует свой собственный обработчик имён файлов в добавок к обработчику вашего командного интерпретатора. Эта команда удаляет все файлы которые имеют расширение .log в каталоге log/ . Или же вы можете сделать вот так: $ git rm \*~ Эта команда удаляет все файлы чьи именя заканчиваются на ~ .

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

В отличие от многих других систем версионного контроля, Git не отслеживает непосредственно перемещение файла. Если вы переименуете файл в Git, то в Git не сохранится никаких метаданных о том, что вы переименовали файл. Однако, Git довольно умён в плане обнаружения перемещений постфактум — мы рассмотрим обнаружение перемещения файлов чуть позже. Таким образом наличие в Git команды mv выглядит несколько странным. Если вам хочется переименовать файл в Git, вы можете сделать что-то вроде: $ git mv file_from file_to и это отлично сработает. На самом деле, если вы выполните что-то вроде этого и посмотрите на статус, вы увидите, что Git считает, что произошло переименование файла: $ git mv README.txt README $ git status # On branch master # Your branch is ahead of ‘origin/master’ by 1 commit. # # Changes to be committed: # (use «git reset HEAD . » to unstage) # # renamed: README.txt -> README # Однако, это эквивалентно выполнению следующих команд: $ mv README.txt README $ git rm README.txt $ git add README Git неявно определяет, что было переименование, поэтому не важно переименуете вы файл так или используя команду mv . Единственное отличие состоит лишь в том, что mv это одна команда вместо трёх — это функция для удобства. Важнее другое — вы можете использовать любой удобный способ, чтобы переименовать файл, и затем воспользоваться add/rm перед коммитом. Pro Git

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *