Разное

Коммит git: Введение в Git. Что это такое и как использовать?

Содержание

Git commit | Atlassian Git Tutorial

Команда git commit делает для проекта снимок текущего состояния изменений, которые были добавлены в раздел проиндексированных файлов. Такие зафиксированные снимки состояния можно рассматривать как «безопасные» версии проекта — Git не будет их менять, пока вы явным образом не попросите об этом. Перед выполнением команды git commit необходимо использовать команду git add, чтобы добавить («проиндексировать») в проект изменения, которые будут сохранены в коммите. Эти две команды, git commit и git add, используются чаще всего.

Коммит в Git и коммит в SVN

Несмотря на одинаковое название, команда git commit не имеет ничего общего с командой svn commit. Этот общеупотребительный термин может запутать новичков в Git, имеющих опыт работы с SVN, поэтому важно подчеркнуть разницу. Разница между git commit и svn commit — это разница между моделью централизованного приложения (SVN) и моделью распределенного приложения (Git). В SVN при выполнении коммита изменения передаются из локального клиента SVN в удаленный централизованный общий репозиторий SVN. В Git репозитории распределены, коммиты снимков состояния выполняются в локальный репозиторий, и для этого совершенно не нужно взаимодействовать с другими репозиториями Git. Позже коммиты Git можно будет передать в произвольный удаленный репозиторий.

Порядок действий

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

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

Снимки состояния, а не различия

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

Такой подход позволяет выполнять многие операции в Git намного быстрее, чем в SVN, поскольку конкретную версию файла не нужно «собирать» из его различий — во внутренней базе данных Git находится уже готовая редакция каждого файла.

Модель снимков состояния Git влияет практически на все аспекты модели управления версиями, от инструментов ветвления и слияния до рабочих процессов при совместной работе.

Распространенные опции

 git commit

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

 git commit -a

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

 git commit -m "комментарий к коммиту"

Быстрая команда, которая создает коммит с указанным комментарием. По умолчанию команда git commit открывает локально настроенный текстовый редактор с предложением ввести комментарий к коммиту. При передаче параметра -m текстовый редактор не открывается, а используется подставленный комментарий.

 git commit -am "комментарий к коммиту"

Мощная пользовательская команда, состоящая из параметров -a и -m. Эта комбинация создает коммит всех проиндексированных изменений и добавляет к коммиту подставленный комментарий.

 git commit --amend

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

Примеры

Сохранение изменений с помощью команды commit

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

 git add hello.py

Эта команда добавит файл hello.py в раздел проиндексированных файлов Git. Проверить результат команды можно с помощью git status.

 git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: hello.py 

Окрашенный зеленым цветом вывод «new file: hello.py» сообщает о том, что файл hello.py будет сохранен при выполнении следующего коммита. Коммит выполняется с помощью указанной ниже команды.

git commit

Эта команда откроет текстовый редактор (настраиваемый через git config) для ввода комментария к коммиту и покажет список файлов, которые будут зафиксированы в этом коммите:

 # Введите комментарий к коммиту, описывающий внесенные изменения. Строчки, начинающиеся # с символа #, будут игнорироваться, а пустой комментарий приведет к отмене коммита. # В главной ветке # Коммит следующих изменений: # (используйте "git reset HEAD ..." для отмены коммита) # #modified: hello.py

Особых требований для комментариев к коммиту в Git нет, но обычно первая строка содержит описания коммита длиной до 50 символов, затем следует пустая строка и детальное пояснение того, что было изменено. Пример:

 Изменение сообщения, выводимого файлом hello.py
- Добавление в функцию sayHello() вывода имени пользователя - Добавление в функцию sayGoodbye() более понятного сообщения

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

Обновление коммита (параметр amend)

Продолжим работу с файлом hello.py из примера выше. Давайте внесем в файл hello.py новые изменения и запустим следующие команды:

 git add hello.py git commit --amend

Снова откроется настроенный текстовый редактор. Но на этот раз он будет содержать комментарий к коммиту, который мы уже вводили ранее. Это указывает на то, что мы не создаем новый коммит, а редактируем последний.

Резюме

Команда git commit является одной из основных и первостепенных функций Git. Для выбора изменений, которые будут добавлены в следующий коммит, сначала используется команда git add. Затем запускается команда git commit, которая создает снимок проиндексированных изменений на временной шкале истории проектов Git. Подробнее об использовании команды git add см. на соответствующей странице. Команда git status может использоваться для изучения состояния раздела проиндексированных файлов и ожидающего коммита.

Модели коммитов в SVN и в Git существенно отличаются, но из-за общей терминологии часто возникает путаница. Если вы начинаете работу в Git, имея опыт работы с SVN, вам будет полезно знать, что коммиты в Git — простая операция, которую следует выполнять часто. В SVN коммит — сложная операция, связанная с выполнением удаленного запроса, тогда как в Git коммиты выполняются локально и по более эффективному алгоритму.

Постигаем Git / Хабр

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

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

Рассмотрим, как разваливается обычный подход к разработке с git.

Отпочковываем ветку от master, работаем, сливаем обратно, когда закончили.

Большую часть времени это работает, как и ожидается, потому как master меняется после того, как вы сделали ответвление (Имеется в виду, что в master коммитят ваши коллеги — прим. переводчика.). Однажды вы сливаете ветку feature в master, но master не менялась. Вместо коммита слияния (merge commit) git просто передвигает указатель master на последний коммит, происходит fast forward.

Для пояснения механизма fast forward я позаимствовал картинку из одной известной статьи. Прим. переводчика.

К несчастью ваша ветка feature содержала промежуточные коммиты — частые коммиты, что бекапят работу, но захватывают код в нерабочем состоянии. Теперь эти коммиты неотличимы от стабильных коммитов в master. Вы можете с легкостью откатиться в этакое бедствие.

Итак, вы добавляется новое правило: «Использовать —no-ff при слиянии веток feature». Это решает проблему и вы двигаетесь дальше.

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

Вы локализуете баг вплоть до файла. Запускаете blame, чтобы увидеть, изменения за последние 48 часов. Вы знаете, что это невозможно, но blame сообщает, что файл не изменялся несколько недель. Выясняется, что blame выдает время исходного коммита вместо времени слияния ветки (логично, ведь merge commit пуст — прим. переводчика). Ваш первый промежуточный коммит изменил этот файл несколько недель назад, но изменение было влито только сегодня.

Костыль no-ff, поломанный bisect и невнятность blame — симптомы того, что вы забиваете гвозди отверткой.

Переосмысление контроля версий

Контроль версий нужен для двух вещей.

Первая — для помощи в написании кода. Есть необходимость синхронизировать правки со своей командой и регулярно бекапить свою работу.

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

Традиционно эти две причины вступают в конфликт.

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

В совершенном мире каждое изменение истории версий лаконично и стабильно. Здесь нет промежуточных коммитов, что создают помехи. Здесь нет гигантских коммитов на 10 000 строк. Опрятная история позволяет откатывать правки или перекидывать их между ветками с помощью cherry-pick. Опрятную историю проще изучать и анализировать. Однако, поддержание чистоты истории подразумевает доведение всех правок до идеального состояния.

Так какой подход выбираете вы? Частые коммиты или опрятную историю?

Если вы работаете вдвоем над предрелизным стартапом, опрятная история подкупает несильно. Вы можете коммитить все подряд в master и выпускать релизы когда вам вздумается.

Как только значимость изменений увеличится, будь то рост команды разработки или размера пользовательской базы, вам понадобятся инструменты для поддержания порядка. Сюда входят автоматическое тестирование, code review и опрятная история.

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

Когда ваш проект достаточно разрастется, простой подход branch / commit / merge развалится. Время применения клейкой ленты закончилось. Вам нужна опрятная история изменений.

Git революционен, потому что он дает вам лучшее от двух миров. Можно делать частые коммиты в процессе разработки и чистить историю по окончании. Если это ваш подход, то умолчания git представляются более осмысленными (имеется в виду fast-forward по умолчанию при слиянии веток — прим. переводчика).

Последовательность действий

Думайте о ветках в разрезе двух категорий: публичные ветки и приватные.

Публичные ветки — это официальная история проекта. Коммит в публичную ветку должен быть лаконичным, атомарным и иметь хорошее описание. Он должен быть линейным. Он должен быть неизменен. Публичные ветки это master и release.

Приватная ветка для себя. Это ваш черновик на время решения задачи.

Наиболее безопасно хранить приватные ветки локально. Если вам требуется сделать push для синхронизации рабочего и домашнего компьютеров, например, сообщите вашим коллегам, что ветка ваша и что не стоит на нее опираться.

Не стоит вливать приватную ветку в публичную простейшим merge. Сперва подчистите вашу ветку инструментами вроде reset, rebase, merge —squash и commit —amend.

Представьте себя писателем, а коммиты главами книги. Писатели не публикуют черновики. Майкл Крайтон сказал: «Великие книги не написаны — они переписаны».

Если вы пришли с других VCS, изменение истории вам покажется табу. Вы исходите из того, что любой коммит высечен в камне. Следуя этой логике, нужно убрать «undo» из текстовых редакторов.

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

Если рассматривать историю как нечто незапятнанное, то fast-forward слияние не только безопасно но и предпочтительно. Оно поддерживает линейность истории, ее проще отслеживать.

Единственный оставшийся аргумент за —no-ff — это документирование. Можно использовать коммиты слияния для ассоциации с последней версией продакшн кода. Это антипаттерн. Используйте теги.

Рекомендации и примеры

Я использую 3 простых подхода в зависимости от размера изменения, времени работы над ним и того, как далеко ветка ушла в сторону.

Быстрая правка

Большую часть времени чистка это всего лишь squash коммит.
Допустим, я создал ветвь feature и сделал несколько промежуточных коммитов в течении часа.

git checkout -b private_feature_branch
touch file1.txt
git add file1.txt
git commit -am "WIP"

Как только я закончил, вместо простого merge, делаю следущее:

git checkout master
git merge --squash private_feature_branch
git commit -v

Затем трачу минуту на написание более подробного комментария к коммиту.

Правка побольше

Временами реализация фичи разрастается в многодневный проект с множеством мелких коммитов.

Я решаю, что моя правка должна быть разделена на более мелкие части, так что squash слишком грубый инструмент. (В качестве повседневного правила я спрашиваю себя: «Легко ли будет сделать code review?»)

Если мои промежуточные коммиты были логичным движением вперед, то можно использовать rebase в интерактивном режиме.

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

В ветке feature:

git rebase --interactive master

Откроется редактор со списком коммитов. Каждая строка это: команда, которая будет выполнена, SHA1 хэш и комментарий к коммиту. Внизу есть список возможных команд.

По умолчанию у каждого коммита стоит «pick», что означает «коммит не изменять».

pick ccd6e62 Work on back button
pick 1c83feb Bug fixes
pick f9d0c33 Start work on toolbar

Меняю команду на «squash», которая объединяет текущий коммит с предыдущим.

pick ccd6e62 Work on back button
squash 1c83feb Bug fixes
pick f9d0c33 Start work on toolbar

Сохраняю, теперь другой редактор запрашивает комментарий к объединенному коммиту. Все, готово.

Несостоявшиеся ветки

Возможно ветка feature просуществовала длительное время и в нее сливались другие ветки для поддержания ее актуальности. История сложна и запутана. Простейшее решение взять грубый diff и создать новую ветку.

git checkout master
git checkout -b cleaned_up_branch
git merge --squash private_feature_branch
git reset

Теперь рабочая директория полна моих правок и никакого наследия предыдущей ветки. Теперь берем и ручками добавляем и коммитим правки.

Резюмируем

Если вы боретесь с умолчаниями в git, спросите себя почему.

Считайте публичную историю неизменной, атомарной и легко прослеживаемой.

Считайте приватную историю изменяемой и гибкой.

Порядок действий таков:

  • Создаем приватное ответвление от публичной ветки.
  • Методично коммитим работу в эту приватную ветку.
  • Как только код достиг совершенства, приводим историю в порядок.
  • Сливаем упорядоченную ветку обратно в публичную.

Как генерировать осмысленные коммиты. Применяем стандарт Conventional Commits / Блог компании Яндекс / Хабр

Привычный хаос в названиях коммитов. Знакомая картина?

Наверняка вы знаете git-flow. Это отличный набор соглашений по упорядочиванию работы с ветками в Git. Он хорошо документирован и широко распространен. Обычно мы знакомы с правильным ветвлением и много говорим об этом, но, к сожалению, уделяем слишком мало внимания вопросу наименования коммитов, поэтому часто сообщения в Git пишутся бессистемно.

Меня зовут Ержан Ташбенбетов, я работаю в одной из команд Яндекс.Маркета. И сегодня я расскажу читателям Хабра, какие инструменты для создания осмысленных коммитов мы используем в команде. Приглашаю присоединиться к обсуждению этой темы.


Отсутствие договоренностей при наименования коммитов затрудняет работу с историей в Git. Такое было в нашей команде. До использования общего для всех регламента и внедрения автоматизации типичные коммиты выглядели следующим образом:

SECRETMRKT-700: пропали логотипы партнеров
Приложение падает, поправил.
SECRETMRKT-701, SECRETMRKT-702: Отцентрировал картинки на всех ...

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

По этой причине мы внедрили в команде стандарт Conventional Commits, стали генерировать коммиты в консольной утилите commitizen и проверять результат с помощью commitlint. В результате коммиты изменились и стали выглядит так:

refactor(tutorial): оптимизировать работу эпиков в тултипах
feat(products): добавить банер с новогодними скидками
fix(products): исправить в банере формат даты

Читать историю и распознавать внесенные изменения стало проще. Мы не отказались от указания номеров задач, всё аккуратно перенесено внутрь коммитов согласно конвенции Conventional Commits.

Дальше я расскажу, как добиться схожего порядка в Git.


Лучшие практики, рекомендации и распространенные решения при наименовании коммитов

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

  • Статьи с общими советами по написанию коммитов. По большей части они вполне логичны и неплохо раскрывают тему, но чувствуется беспорядочность и отсутствие комплексного решения вопроса.
  • Стандарты по написанию коммитов. Их немного. Они представляют собой документы с четким перечнем правил, довольно часто написанных специально для крупной библиотеки или фреймворка. Эти стандарты подкупают системным подходом, популярностью и поддержкой в open-source сообществе.

Нам нужно больше порядка в коммитах!

Методология Conventional Commits выделяется на фоне других стандартов и заслуживает пристального изучения по ряду причин:

  1. Она хорошо документирована и проработана. В её спецификации даны ответы на наиболее распространенные вопросы.
  2. Создатели конвенции вдохновились требованиями к написанию коммитов, которые используются в популярном и проверенном временем фреймворке AngularJS.
  3. Правил конвенции придерживаются несколько крупных и популярных open-source библиотек (таких как yargs и lerna).
  4. К плюсам отнесу подготовку к автоматическому формированию Release Notes и Change Log.

Пример коммита по этому стандарту:

fix(products): поправить длину строки с ценой

Часть заголовков неправильно отображается в мобильной версии из-за ошибок
в проектировании универсальных компонентов.

МЕТА ДАННЫЕ: SECRETMRKT-578, SECRETMRKT-602


Основные тезисы Conventional Commits

  • Разработчик должен придерживаться следующей структуры коммитов:

    <type>(<scope>): <subject>

    <body>

    <footer>

  • У коммита должен быть заголовок, может быть тело и нижний колонтитул.
  • Заголовок коммита должен начинаться с типа (type), указывающего на специфику внесенных в кодовую базу изменений, и завершаться описанием.
  • Наряду с обязательными feat, fix (использование которых строго регламентировано), допускаются и другие типы.
  • У коммита может быть область (scope). Она характеризует фрагмент кода, которую затронули изменения. Область следует за типом коммита. Стандарт не регламентирует четкий список областей. Примеры областей: eslint, git, analytics и т.д.
  • Описание коммита должно быть сразу после типа/области.
  • Тело коммита может быть использовано для детализации изменений. Тело должно быть отделено от описания пустой строкой.
  • Нижний колонтитул следует использовать для указания внешних ссылок, контекста коммита или другой мета информации. Нижний колонтитул должен быть отделен от тела пустой строкой.
Кроме перечисленых в конвенции правил мы используем следущие популярные рекомендации:

  • В теле коммита пишем что было изменено и почему.
  • Используем следующие типы коммитов:











    buildСборка проекта или изменения внешних зависимостей
    ciНастройка CI и работа со скриптами
    docsОбновление документации
    featДобавление нового функционала
    fixИсправление ошибок
    perfИзменения направленные на улучшение производительности
    refactorПравки кода без исправления ошибок или добавления новых функций
    revertОткат на предыдущие коммиты
    styleПравки по кодстайлу (табы, отступы, точки, запятые и т.д.)
    testДобавление тестов
  • Пишем описание в повелительном наклонении (imperative mood), точно также как сам Git.

    Merge branch ‘fix/SECRETMRKT-749-fix-typos-in-titles’

  • Не закачиваем описание коммита знаками препинания.

Стандарт коммитов Conventional Commits используют котрибьюторы lerna


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


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

  1. Установим утилиту commitizen глобально (вам могут потребоваться права администратора).
    npm i -g commitizen
  2. Следом установим адаптер cz-customizable. Он нужен для настройки шаблона с вопросами, которым пользуется утилита commitizen.
    npm i -D cz-customizable
  3. Создадим файл commitizen.js, он нужен для настройки cz-customizable. Поместим созданный файл в директорию ./config/git. Рекомендую не захламлять корень проекта конфигурационными файлами и стараться группировать файлы в подготовленной для этого папке. Содержимое:Показать commitizen.js
    "use strict";
    
    module.exports = {
      // Добавим описание на русском языке ко всем типам
      types: [
        {
          value: "build",
          name: "build:     Сборка проекта или изменения внешних зависимостей"
        },
        { value: "ci", name: "ci:        Настройка CI и работа со скриптами" },
        { value: "docs", name: "docs:      Обновление документации" },
        { value: "feat", name: "feat:      Добавление нового функционала" },
        { value: "fix", name: "fix:       Исправление ошибок" },
        {
          value: "perf",
          name: "perf:      Изменения направленные на улучшение производительности"
        },
        {
          value: "refactor",
          name:
            "refactor:  Правки кода без исправления ошибок или добавления новых функций"
        },
        { value: "revert", name: "revert:    Откат на предыдущие коммиты" },
        {
          value: "style",
          name:
            "style:     Правки по кодстайлу (табы, отступы, точки, запятые и т.д.)"
        },
        { value: "test", name: "test:      Добавление тестов" }
      ],
    
      // Область. Она характеризует фрагмент кода, которую затронули изменения
      scopes: [
        { name: "components" },
        { name: "tutorial" },
        { name: "catalog" },
        { name: "product" }
      ],
    
      // Возможность задать спец ОБЛАСТЬ для определенного типа коммита (пример для 'fix')
      /*
      scopeOverrides: {
        fix: [
          {name: 'style'},
          {name: 'e2eTest'},
          {name: 'unitTest'}
        ]
      },
      */
    
      // Поменяем дефолтные вопросы
      messages: {
        type: "Какие изменения вы вносите?",
        scope: "\nВыберите ОБЛАСТЬ, которую вы изменили (опционально):",
        // Спросим если allowCustomScopes в true
        customScope: "Укажите свою ОБЛАСТЬ:",
        subject: "Напишите КОРОТКОЕ описание в ПОВЕЛИТЕЛЬНОМ наклонении:\n",
        body:
          'Напишите ПОДРОБНОЕ описание (опционально). Используйте "|" для новой строки:\n',
        breaking: "Список BREAKING CHANGES (опционально):\n",
        footer:
          "Место для мета данных (тикетов, ссылок и остального). Например: SECRETMRKT-700, SECRETMRKT-800:\n",
        confirmCommit: "Вас устраивает получившийся коммит?"
      },
    
      // Разрешим собственную ОБЛАСТЬ
      allowCustomScopes: true,
    
      // Запрет на Breaking Changes
      allowBreakingChanges: false,
    
      // Префикс для нижнего колонтитула
      footerPrefix: "МЕТА ДАННЫЕ:",
    
      // limit subject length
      subjectLimit: 72
    };
  4. Добавим в package.json ссылки на cz-customizable и созданный ранее конфигурационный файл:Показать часть package.json
    {
      "config": {
        "commitizen": {
          "path": "node_modules/cz-customizable"
        },
        "cz-customizable": {
          "config": "config/git/commitizen.js"
        }
      },
    }

  5. Давайте проверим получившийся результат. Наберите в терминале следующую команду:
    git cz

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

Обязательно посмотрите на пример работы настроенной утилиты commitizen и подключенного к нему адаптера cz-cusomizable


  1. Установим в проект husky и commitlint:
    npm i -D husky @commitlint/cli
  2. С помощью husky добавим проверку коммитов. Для этого в package.json сразу после скриптов добавим следующий хук и укажем в нем ссылку на файл commitlint.js:Показать часть package.json
    {
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "husky": {
        "hooks": {
          "commit-msg": "commitlint -E HUSKY_GIT_PARAMS -g './config/git/commitlint.js'"
        }
      },
      "devDependencies": {
        "@commitlint/cli": "^7.2.1",
        "husky": "^1.1.3",
    }
  3. Создадим файл commitlint.js, необходимый для корректной работы линтера. Поместим созданный файл в директорию ./config/git. Содержимое файла:Показать commitlint.js
    // Файл создан на основе @commitlint/config-conventional
    
    module.exports = {
      rules: {
        // Тело коммита должно начинаться с пустой строки
        "body-leading-blank": [2, "always"],
    
        // Нижний колонтитул коммита должен начинаться с пустой строки
        "footer-leading-blank": [2, "always"],
    
        // Максимальная длина заголовка 72 символа
        "header-max-length": [2, "always", 72],
    
        // Область всегда только в нижнем регистре
        "scope-case": [2, "always", "lower-case"],
    
        // Описание не может быть пустым
        "subject-empty": [2, "never"],
    
        // Описание не должно заканчиваться '.'
        "subject-full-stop": [2, "never", "."],
    
        // Тип всегда только в нижнем регистре
        "type-case": [2, "always", "lower-case"],
    
        // Тип не может быть пустым
        "type-empty": [2, "never"],
    
        // Перечислим все возможные варианты коммитов
        "type-enum": [
          2,
          "always",
          [
            "build",
            "ci",
            "docs",
            "feat",
            "fix",
            "perf",
            "refactor",
            "revert",
            "style",
            "test"
          ]
        ]
      }
    };

Всё. Теперь все коммиты будут проверяться перед отправкой в репозиторий 🙂

Обязательно посмотрите на пример работы настроенной утилиты commitlint


Так что выбрать commitizen или commitlint?

И то, и другое! В связке они приносят отличный результат: первый генерирует коммиты, второй их проверяет.

Почему стандарты рекомендуют использовать повелительное наклонение?

Это крайне интересный вопрос. Коммит это изменение кода, сообщение в коммите можно расценивать как инструкцию по изменению этого кода. Сделать, изменить, добавить, обновить, поправить  — всё это конкретные инструкции для разработчика.

Кстати, повелительное наклонение рекомендовано в самой системе версионирования Git:

[[imperative-mood]]
Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
to do frotz", as if you are giving orders to the codebase to change
its behavior.

Зачем придерживаться каких-либо конвенций? Стоит ли тратить на это время? Какой в этом профит?

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

Попробуйте и поделитесь результатом.

Полезные ссылки:

Git для начинающих. Часть 5. Создание репозитория и первый коммит

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

Для того чтобы создать репозиторий, для начала, создайте папку, в которой он будет располагаться. В нашем случае это будет каталог с названием repo.

> mkdir repo

Теперь перейдем в этот каталог.

>cd repo

Создадим в нем пустой git репозиторий.

> git init

Если мы посмотрим на список коммитов, которые были отправлены в репозиторий, то увидим, что он пустой – это правильно, т.к. мы пока только создали репозиторий и ничего ещё туда не отправляли.

> git log
fatal: your current branch 'master' does not have any commits yet

Для просмотра состояния рабочего каталога воспользуемся командой git status.

> git status
On branch master

Initial commit

nothing to commit (create/copy files and use "git add" to track)

Создадим в нашем каталоге пустой файл.

> touch README.md

Теперь, если мы выполним команду git status, то увидим, что в нашем каталоге появился один неотслеживаемый файл: README.md.

> git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        README.md

nothing added to commit but untracked files present (use "git add" to track)

Добавим, созданный файл в stage. Stage (или cache) – это хранилище для файлов с изменениями, информация о которых попадет в единый коммит. Stage является элементом архитектуры трех деревьев, на базе которой построен git, более подробно смотрите здесь. Для добавления файла README.md в stage необходимо воспользоваться командой git add.

> git add README.md

Если изменение было произведено в нескольких файлах, и мы хотим их все отправить в stage, то вместо имени файла поставьте точку.

Выполним git status для того, чтобы посмотреть на то, что сейчас происходит в нашем каталоге.

> git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   README.md

Как видно, в stage был добавлен один файл с именем README.md и теперь представленный набор изменений готов к отправке в репозиторий – т.е. к коммиту. Сделаем это.

> git commit -m "[create repository]"
[master (root-commit) 500067c] [create repository]
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md

Проверим статус каталога.

> git status
On branch master
nothing to commit, working tree clean

Как видно с момента последнего коммита никаких изменений в рабочем каталоге не производилось.

Теперь взглянем на список коммитов.

> git log
commit 500067cc0b80643d38e2a24e9e0699031ada6be3
Author: Writer <[email protected]>
Date:   Mon Feb 12 22:51:14 2018 +0500

    [create repository]

Из приведенной информации видно, что был отправлен один коммит, который имеет ID: 500067cc0b80643d38e2a24e9e0699031ada6be3, более подробно об идентификаторах будет рассказано в следующих уроках. Автор данного коммита Writer, он (коммит) был создан Mon Feb 12 22:51:14 2018 +0500, с сообщением:  [create repository]. Это довольно подробная информация, когда коммитов станет много, такой формат вывода будет не очень удобным, сокращенный вариант выглядит так.

> git log --oneline
500067c [create repository]

Подведем небольшое резюме вышесказанному.

Создание пустого репозитория.

> git init

Добавление файлов в stage.

> git add filename

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

> git commit -m “message”

Просмотр статуса каталога.

> git status

Просмотр коммитов в репозитории.

> git log

Просмотр коммитов в репозитории с сокращенным выводом информации.

> git log --oneline

Отличный курс по git  делают ребята из GeekBrains, найдите в разделе “Курсы” курс “Git. Быстрый старт”, он бесплатный!

<<< Часть 4. Архитектура Git   Часть 6. Просмотр информации по коммитам >>>

Как склеить коммиты и зачем это нужно — Блог HTML Academy

Когда вы открываете пулреквест, и ваш код смотрят и комментируют другие, бывает нужно что-то исправить. Обычно такие изменения мы комментируем сообщением вроде «Увеличил шрифт на 2px» или «Поменял оттенок фона в шапке». Такие маленькие изменения интересны только пока они в пулреквесте. Ревьювер (человек, который смотрит ваш код), может легко узнать, что и когда вы изменили, а не читать весь diff заново, а вы можете легко откатить коммит, если он не нужен. Но когда приходит время вливать пулреквест, эти маленькие коммиты теряют свою ценность. Поэтому лучше их склеить в один. Как — я расскажу вам сегодня.

Как подготовиться

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

git config --global core.editor 

Например, если у вас Mac OS, и вы хотите установить Atom в качестве редактора по умолчанию, введите:

git config --global core.editor "atom --wait"

А если у вас Windows, и вы хотите установить Notepad++ в качестве гит-редактора, ваша команда будет такая:

git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"

Вам нужно просто узнать команду для запуска вашего редактора и подставить её. Вот список команд для популярных редакторов.

Как склеивать коммиты

Сначала узнаем, сколько коммитов нужно склеить. Эта команда покажет, какие коммиты у вас прибавились по сравнению с веткой master:

git cherry -v master

А эта — сколько их:

git cherry -v master | wc -l

git cherry -v master

Отлично, у меня 5 коммитов. Теперь я хочу переписать историю с момента HEAD~5, т.е. с того, что было 5 коммитов назад. Для этого я делаю так:

git rebase -i HEAD~5

флаг -i — значит в интерактивном режиме. У меня открывается такой файл:

git rebase -i HEAD~5

Тут список моих коммитов и большой комментарий о том, что я могу сделать. Из списка комманд видно, что мы можем использовать squash или fixup для того, чтобы склеить коммиты. Первый пригодится тогда, когда вы хотите изменить коммит-месседж, а второй — когда хотите использовать коммит-месседж первого. Итак, чтобы склеить все коммиты, я делаю вот так:

Сквош коммитов

То есть я говорю гиту «используй первый коммит, а остальные приклей к нему». Потом я сохраняю файл и закрываю его. Гит склеивает коммиты и предлагает мне ввести коммит-месседж (показывает коммит-месседжи всех склеенных коммитов):

Коммит-месседжи склеенных коммитов

Я хочу оставить только последний:

Коммит-месседж результирующего коммита

Сохраняю файл и смотрю лог:

git log

Ура, остался один коммит с нужным сообщением.

Теперь нужно вашу работу отправить на ваш гит-сервер. Обычно вы делаете это с помощью git push, но сейчас вам это не удастся:

git push

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

git push --force

git push --force

Теперь всё получилось! Используйте форс только тогда, когда вы уверены в своих действиях!

Как автоматизировать ребейз

Обычно всё-таки нужно оставить коммит-месседж первого изменения, типа «Сверстал то-то», остальные коммиты — просто правки к нему. Число правок иногда доходит до 15, не очень удобно сидеть и писать везде squash. Можно сделать так, чтобы коммиты автоматически присквошивались к нужному, только для этого нужно их правильно коммитить. Предположим, вы поменяли файл и хотите закоммитить изменения как правку по ревью:

git status

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

git cherry -v master

Ага, вот он наш хеш. А теперь следующий коммит обозначим правкой к этому:

git commit --fixup <хеш нужного коммита>

Необязательно в точности копировать весь хеш, достаточно первых 7 символов. Я обычно выделяю от начала и сколько выделится и копирую:

git commit --fixup

Изменения закоммитились с сообщением fixup! Сообщение того коммита. Наша история теперь выглядит вот так:

git log

Добавим ещё несколько правок таким образом. Посмотрим изменения:

git cherry -v master

Отлично. А теперь склеим все эти коммиты. Только не вручную. Гит сделает это за нас:

git rebase -i --autosquash HEAD~4

И гит сам подставит слово fixup там, где нужно:

git rebase -i --autosquash

Просто сохраняем, и гит склеивает коммиты и использует коммит-месседж первого:

Результат автосквоша

Ура, теперь вы умеете склеивать коммиты!

Как объединить коммиты в Git

Для объединения одного или более коммитов в один можно использовать либо команду git reset, либо команду git rebase. Рассмотрим оба варианта.

Объединение коммитов (с использованием git rebase)

Чтобы объединить два или более последних коммитов в один используется команда git rebase с ключом -i (интерактивный режим).

Для примера объединим последние 2 коммита в один. Выполняем команду:

git rebase -i HEAD~2

Откроется текстовый редактор, в котором первые две строки соответствуют последним двум коммитам:

pick ab37583 Added feature 1.
pick 3ab2b83 Added feature 2.

# Rebase e46d230..3ab2b83 onto e46d230 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
...

В начале каждой строки стоит слово pick. Вам необходимо изменить слово pick на squash или просто на букву s у второй строки. Это означает, что данный коммит будет объединен с предыдущим коммитом. Итак, замените pick на s, у вас должно получиться что-то вроде:

pick ab37583 Added feature 1.
s 3ab2b83 Added feature 2.
...

Сохраните изменения и закройте редактор.

Снова откроется редактор, в котором вам предлагается ввести сообщение к коммиту, который и является объединением двух коммитов:

# This is a combination of 2 commits.
# This is the 1st commit message:

Added feature 1.

# This is the commit message #2:

Added feature 2.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

Отредактируйте сообщение к коммиту, сохраните изменения, и закройте редактор.

В результате вы получите коммит, который был объединен из двух последних коммитов.


Если вам нужно объединить не 2, а три или больше коммитов, то в исходной команде необходимо указать соответствующие количество. Например, чтобы объединить 5 коммитов используем команду:

git rebase -i HEAD~5

В таком случае pick нужно будет заменить на squash (s) уже у 4 коммитов.

pick ab37583 Added feature 1.
s 3ab2b83 Added feature 2.
s bf43de1 Added feature 3.
s 10bccc1 Added feature 4.

Если вам нужно объединить несколько коммитов, которые не являются последними, то в команде git rebase -i HEAD~n вместо HEAD необходимо указать хеш коммита (SHA1), а после символа тильда количество коммитов, которое вы хотите объединить. В данном случае речь идет о коммитах, сделанных раньше, чем коммит, хеш которого вы указали в команде. Пример:

git rebase -i ae88544~3

На самом деле при выполнении данной команды в текстовом редакторе откроется список коммитов, начиная с HEAD, то есть их там будет больше трех (так как в нашем примере хеш ae88544 не совпадает с HEAD).

Объединение коммитов (с использованием git reset)

Для объединения двух и более последних коммитов с использованием git reset необходимо выполнить последовательно следующие команды:

git reset --soft HEAD~n
git commit --amend

Вместо n — необходимо указать количество коммитов, которые вы хотите объединить.
После выполнения второй команды вы должны будете ввести сообщение (комментарий) для нового объединенного коммита.

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

git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"

Как изменить сообщение коммита в Git

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

В этой статье объясняется, как изменить сообщение о самых последних или старых коммитах в Git.

 

Команда git commit –amend позволяет вам изменить самое последнее сообщение о коммите.

 

Чтобы изменить сообщение самого последнего коммита, который не был передан в удаленный репозиторий, передайте его снова, используя флаг –amend.

  1. Перейдите в каталог хранилища в вашем терминале.
  2. Выполните следующую команду, чтобы поправить (изменить) сообщение о последнем коммите:
    git commit --amend -m "New commit message."

    Команда выполняет перезапись самого последнего коммита новым.

    Опция -m позволяет записать новое сообщение в командной строке без открытия редактора сессии.

 

Перед изменением сообщения о коммите вы также можете добавить другие ранее забытые изменения:

git add .git commit --amend -m "New commit message."

 

Измененный коммит – это новый объект с другим SHA-1. Предыдущий коммит больше не будет существовать в текущей ветке.

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

Если вы изменили сообщение о самом последнем введенном коммите, вам придется принудительно нажать его.

  1. Перейдите в хранилище.
  2. Исправьте сообщение о последнем введенном коммите:
    git commit --amend -m "New commit message."

     

  3. Принудительно нажмите, чтобы обновить историю удаленного хранилища:
    git push --force branch-name

     

Если вам нужно изменить сообщение о старых или нескольких коммитах, вы можете использовать интерактив git rebase для изменения одного или нескольких старых коммитов.

Команда rebase переписывает историю коммитов, и настоятельно не рекомендуется перебазировать коммиты, которые уже переданы в удаленный репозиторий Git .

  1. Перейдите в хранилище, содержащее сообщение фиксации, которое вы хотите изменить.
  2. Введите git rebase -i HEAD~N, где N число коммитов для выполнения перебазирования. Например, если вы хотите изменить 4-й и 5-й последние коммиты, введите:
    git rebase -i HEAD~5

    Команда отобразит последние X коммитов в текстовом редакторе по умолчанию :

    pick 43f8707f9 fix: update dependency json5 to ^2.1.1
    pick cea1fb88a fix: update dependency verdaccio to ^4.3.3
    pick aa540c364 fix: update dependency webpack-dev-server to ^3.8.2
    pick c5e078656 chore: update dependency flow-bin to ^0.109.0
    pick 11ce0ab34 fix: Fix spelling.
    
    # Rebase 7e59e8ead..11ce0ab34 onto 7e59e8ead (5 commands)

     

  3. Переход к линии сообщения фиксации, который вы хотите изменить, и замените pick на reword:
    reword 43f8707f9 fix: update dependency json5 to ^2.1.1
    reword cea1fb88a fix: update dependency verdaccio to ^4.3.3
    pick aa540c364 fix: update dependency webpack-dev-server to ^3.8.2
    pick c5e078656 chore: update dependency flow-bin to ^0.109.0
    pick 11ce0ab34 fix: Fix spelling.
    
    # Rebase 7e59e8ead..11ce0ab34 onto 7e59e8ead (5 commands)

     

  4. Сохраните изменения и закройте редактор.
  5. Для каждого выбранного коммита открывается новое окно текстового редактора. Измените сообщение о коммите, сохраните файл и закройте редактор.
    fix: update dependency json5 to ^2.1.1

     

  6. Принудительно отправить изменения в удаленный репозиторий:
    git push --force branch-name

     

Чтобы изменить самое последнее сообщение о коммите, используйте команду git commit –amend и, чтобы изменить более старое или несколько сообщений о коммите git rebase -i HEAD~N.

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

Если вы столкнулись с проблемой или у вас есть отзыв, оставьте комментарий ниже.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Git Commit | Учебник Atlassian Git

Команда git commit делает снимок текущих изменений проекта. Зафиксированные снимки можно рассматривать как «безопасные» версии проекта — Git никогда не изменит их, если вы явно не попросите об этом. Перед выполнением git commit команда git add используется для продвижения или «стадии» изменений проекта, которые будут сохранены в фиксации. Эти две команды git commit и git add — две из наиболее часто используемых.

Git commit vs SVN commit

Хотя у них одно и то же имя, git commit не что иное, как svn commit . Этот общий термин может ввести в заблуждение новичков в Git, имеющих опыт работы с svn, и важно подчеркнуть разницу. Чтобы сравнить git commit и svn commit , нужно сравнить централизованную модель приложения (svn) с моделью распределенного приложения (Git). В SVN фиксация передает изменения с локального клиента SVN в удаленный централизованный общий репозиторий SVN.В Git репозитории распределены, моментальные снимки фиксируются в локальном репозитории, и это не требует абсолютно никакого взаимодействия с другими репозиториями Git. Позднее коммиты Git могут быть отправлены в произвольные удаленные репозитории.

Как это работает

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

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

Снимки, а не отличия

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

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

Модель моментальных снимков

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

Общие опции

  git commit  

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

  git commit -a  

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

  git commit -m "сообщение фиксации"  

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

  git commit -am "сообщение фиксации"  

Сочетание клавиш для опытных пользователей, объединяющее параметры -a и -m .Эта комбинация немедленно создает фиксацию всех поэтапных изменений и принимает встроенное сообщение фиксации.

  git commit --amend  

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

Примеры

Сохранение изменений с фиксацией

В следующем примере предполагается, что вы отредактировали некоторый контент в файле с именем hello.py в текущей ветке и готовы зафиксировать его в истории проекта. Сначала вам нужно обработать файл с помощью git add , затем вы можете зафиксировать поэтапный снимок.

  git добавить hello.py  

Эта команда добавит hello.py в область подготовки Git. Мы можем проверить результат этого действия с помощью команды git status .

  git status На главном сервере ветки Изменения, которые необходимо зафиксировать: (используйте команду «git reset HEAD ...» для отключения) новый файл: hello.py  

Зеленый выходной новый файл: hello.py указывает, что hello.py будет сохранен при следующей фиксации. Из коммита создается выполнение:

  git commit  

Откроется текстовый редактор (настраиваемый с помощью git config ), запрашивающий сообщение журнала фиксации вместе со списком того, что было зафиксировано:

  # Пожалуйста, введите сообщение фиксации для ваших изменений.Строки, начинающиеся с символа «#», будут проигнорированы, а пустое сообщение прерывает фиксацию. # На главном сервере # Изменения, которые необходимо зафиксировать: # (используйте "git reset HEAD ..." для отмены постановки) # # изменено: hello.py  

Git не требует, чтобы сообщения о фиксации соответствовали каким-либо конкретным ограничениям форматирования, но канонический формат заключается в том, чтобы суммировать всю фиксацию в первой строке менее чем из 50 символов, оставить пустую строку, а затем подробное объяснение того, что было изменено. Например:

  Измените сообщение, отображаемое при приветствии.py 
- Обновите функцию sayHello () для вывода имени пользователя - Измените функцию sayGoodbye () на более дружелюбное сообщение

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

Как обновить (исправить) коммит

Чтобы продолжить с примером hello.py выше. Давайте сделаем дальнейшие обновления для hello.py и выполним следующее:

  git add hello.py git commit --amend  

Это снова откроет настроенный текстовый редактор. Однако на этот раз он будет предварительно заполнен сообщением фиксации, которое мы ввели ранее. Это означает, что мы не создаем новый коммит, а редактируем последний.

Резюме

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

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

.

git commit — Сохранение изменений в локальном репозитории

Команда «commit» используется для сохранения ваших изменений в локальном репозитории.

Обратите внимание, что вы должны явно указать Git , какие изменения вы хотите включить в фиксацию до , запустив команду «git commit». Это означает, что файл не будет автоматически включаться в следующую фиксацию только потому, что он был изменен. Вместо этого вам нужно использовать команду «git add», чтобы отметить желаемые изменения для включения.

Также обратите внимание, что в Git (не как в Subversion) фиксация — это , а не , автоматически передаваемая на удаленный сервер. Использование команды «git commit» сохраняет только новый объект фиксации в локальном репозитории Git . Обмен коммитами должен выполняться вручную и явно (с помощью команд «git fetch», «git pull» и «git push»).

Шпаргалка по Git

Не нужно запоминать все эти команды и параметры: получите нашу популярную «Шпаргалку по Git» — бесплатно!

Важные параметры

-м <сообщение>

Устанавливает сообщение фиксации. Обязательно дайте краткое описание, которое поможет вашим товарищам по команде (и вам самому) понять, что произошло.

Включает в эту фиксацию все измененные в данный момент файлы. Однако имейте в виду, что неотслеживаемые (новые) файлы не включаются.

- изменить

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

Совет
Простая фиксация в башне

Если вы используете клиент Tower Git, выполнить фиксацию очень просто: просто проверьте измененные файлы, которые вы хотите включить, и введите свое сообщение фиксации. Вы даже можете добавлять отдельные фрагменты и строки из файла (вместо всего файла)!

Примеры использования

Для базового рабочего процесса вы можете использовать команду «git add» для внесения изменений в следующую фиксацию.Фактическая команда фиксации затем завершит упомянутые изменения в новом объекте фиксации:

  git добавить index.html css / styles.css
git commit -m "Изменить заголовки и стиль на главной странице"
  

Если у вас есть много измененных файлов в вашей рабочей копии — и вы хотите, чтобы все они были включены в следующую фиксацию — вы можете использовать параметр «-a» и тем самым пропустить шаг «git add»:

  git commit -a -m «Изменить заголовки и стиль на домашней странице»
  

Параметр «—amend» пригодится, например, если вы неправильно набрали сообщение последнего коммита или забыли добавить изменение.В следующем примере будет исправлен самый последний коммит, перезаписав его сообщение и добавив еще одно изменение:

  git добавить забытый-change.js
git commit --amend -m "Новое сообщение фиксации"
  

Узнать больше

.

git изменить | Учебник Atlassian Git

Введение

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

Основная задача

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

Git имеет несколько механизмов для хранения истории и сохранения изменений. Эти механизмы включают в себя: Commit --amend , git rebase и git reflog .Эти параметры предоставляют мощные возможности настройки рабочего процесса. К концу этого руководства вы познакомитесь с командами, которые позволят вам реструктурировать ваши коммиты Git и избежать ошибок, которые обычно встречаются при перезаписи истории.

Изменение последней фиксации: git commit --amend

Команда git commit --amend — удобный способ изменить самую последнюю фиксацию. Он позволяет комбинировать поэтапные изменения с предыдущей фиксацией вместо создания совершенно новой фиксации.Его также можно использовать для простого редактирования предыдущего сообщения фиксации без изменения его снимка. Но изменение не просто изменяет самую последнюю фиксацию, оно полностью заменяет ее, то есть измененная фиксация будет новой сущностью со своим собственным ref. Для Git это будет выглядеть как новый коммит, который на схеме ниже обозначен звездочкой (*). Есть несколько распространенных сценариев использования git commit --amend . Мы рассмотрим примеры использования в следующих разделах.

Изменить последнее сообщение коммита Git

  git commit --amend  

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

Преждевременные коммиты происходят постоянно в ходе вашего повседневного развития. Легко забыть подготовить файл или неправильно отформатировать сообщение фиксации. Флаг --amend — удобный способ исправить эти мелкие ошибки.

  git commit --amend -m "обновленное сообщение фиксации"  

Добавление параметра -m позволяет передать новое сообщение из командной строки без запроса на открытие редактора.

Изменение зафиксированных файлов

Следующий пример демонстрирует общий сценарий разработки на основе Git. Допустим, мы отредактировали несколько файлов, которые хотели бы зафиксировать в одном снимке, но потом забываем добавить один из файлов в первый раз. Исправление ошибки — это просто вопрос постановки другого файла и фиксации с флагом --amend :

  # Отредактируйте hello.py и main.py git add hello.py git commit # Поймите, вы забыли добавить изменения из main.py git add main.py git commit --amend --no-edit  

Флаг --no-edit позволит вам внести поправку в ваш коммит, не изменяя его сообщение о коммите. Полученный коммит заменит неполный, и будет выглядеть так, как будто мы зафиксировали изменения в hello.py и main.py в одном снимке.

Не изменять публичные коммиты

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

Резюме

Напомним, git commit --amend позволяет вам взять самую последнюю фиксацию и добавить к ней новые поэтапные изменения. Вы можете добавить или удалить изменения из промежуточной области Git, чтобы применить их с фиксацией --amend . Если нет внесенных изменений, --amend все равно предложит вам изменить журнал сообщений последней фиксации.Будьте осторожны при использовании --amend для коммитов, совместно используемых с другими членами команды. Внесение изменений в фиксацию, которая используется другим пользователем, потенциально потребует запутанного и длительного разрешения конфликтов слияния.

Изменение старых или нескольких коммитов

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

В этих или подобных случаях, когда важно сохранить чистую историю проекта, добавление параметра -i в git rebase позволяет запустить rebase interactive . Это дает вам возможность изменять отдельные коммиты в процессе, а не перемещать все коммиты.Вы можете узнать больше об интерактивном перебазировании и дополнительных командах перебазирования на странице git rebase.

Изменение зафиксированных файлов

Во время перебазирования команда edit или e приостановит воспроизведение перебазирования для этого коммита и позволит вам внести дополнительные изменения с помощью git commit --amend Git прервет воспроизведение и выдаст сообщение:

  Остановлено на 5d025d1 ... форматирование Теперь вы можете изменить фиксацию с помощью git commit --amend Когда вы будете удовлетворены своими изменениями, запустите git rebase --continue  
Несколько сообщений

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

  • Reword или ‘r’ остановит воспроизведение с перебазированием и позволит вам переписать отдельное сообщение фиксации во время.
  • Squash or ‘s’ во время воспроизведения с перебазированием любые коммиты, помеченные как s , будут приостановлены, и вам будет предложено отредактировать отдельные сообщения фиксации в объединенное сообщение. Подробнее об этом в разделе коммитов сквоша ниже.
  • Fixup или «f» имеет тот же эффект комбинирования, что и сквош. В отличие от сквоша, фиксация фиксации не прерывает воспроизведение перебазирования, чтобы открыть редактор для объединения сообщений фиксации. Сообщения коммитов, отмеченных ‘f’, будут отброшены в пользу сообщения предыдущего коммита.
Squash сохраняет чистую историю

Команда s «squash» — вот где мы видим истинную полезность rebase. Squash позволяет вам указать, какие коммиты вы хотите объединить с предыдущими.Это то, что обеспечивает «чистую историю». Во время воспроизведения смещения Git будет выполнять указанную команду rebase для каждой фиксации. В случае сквош-коммитов Git откроет ваш настроенный текстовый редактор и предложит объединить указанные сообщения коммита. Весь этот процесс можно визуализировать следующим образом:

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

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

Резюме

Git rebase дает вам возможность изменять свою историю, а интерактивное ребазирование позволяет вам делать это, не оставляя «грязного» следа. Это дает свободу делать и исправлять ошибки и совершенствовать вашу работу, сохраняя при этом чистую линейную историю проекта.

Защитная сетка: git reflog

Справочные журналы, или «рефлоги» — это механизм, который Git использует для записи обновлений, применяемых к подсказкам ветвей и другим ссылкам на коммиты. Reflog позволяет вам вернуться к коммитам, даже если на них не ссылаются никакие ветки или теги. После перезаписи истории журнал ссылок содержит информацию о старом состоянии ветвей и позволяет при необходимости вернуться в это состояние. Каждый раз, когда ваша подсказка ветки обновляется по какой-либо причине (путем переключения ветвей, ввода новых изменений, перезаписи истории или просто путем добавления новых коммитов), новая запись будет добавляться в журнал ссылок.В этом разделе мы подробно рассмотрим команду git reflog и рассмотрим некоторые распространенные применения.

Использование

  git рефлог  

Здесь отображается журнал ссылок для локального репозитория.

  git reflog - относительная дата  

Здесь отображается журнал с относительной датой (например, 2 недели назад).

Пример

Чтобы понять git reflog , давайте рассмотрим пример.

  0a2e358 HEAD @ {0}: reset: перемещение в HEAD ~ 2 0254ea7 HEAD @ {1}: checkout: перемещение с 2.2 для мастера c10f740 HEAD @ {2}: checkout: переход от мастера к 2,2  

В приведенном выше журнале ссылок показан переход от мастера к ветке 2.2 и обратно. Оттуда происходит полный сброс до более старого коммита. Последнее действие представлено вверху с пометкой HEAD @ {0} .

Если окажется, что вы случайно вернулись назад, в журнале регистрации будет указано, что мастер фиксации указывает на (0254ea7) до того, как вы случайно сбросили 2 фиксации.

git reset --hard 0254ea7

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

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

Для получения дополнительной информации см. Нашу страницу git reflog .

Сводка

В этой статье мы обсудили несколько методов изменения истории git и отмены изменений git.Мы внимательно рассмотрели процесс git rebase. Некоторые ключевые выводы:

  • Есть много способов переписать историю с помощью git.
  • Используйте git commit --amend , чтобы изменить последнее сообщение журнала.
  • Используйте git commit --amend , чтобы внести изменения в самую последнюю фиксацию.
  • Используйте git rebase , чтобы объединить коммиты и изменить историю ветки.
  • git rebase -i дает гораздо более точный контроль над модификациями истории, чем стандартный git rebase.

Узнайте больше о командах, которые мы рассмотрели, на их отдельных страницах:

.

базовых команд Git | Учебник Atlassian Git

git чистый

Удаляет неотслеживаемые файлы из рабочего каталога. Это логический аналог git reset, который (обычно) работает только с отслеживаемыми файлами.

Связанные руководства

Отмена изменений: git clean

git commit —amend

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

Связанные руководства

Переписываем историю: git commit —amend

git fetch

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

Связанные руководства

Синхронизация: git fetch
Ссылки и Reflog: Refspecs
Синхронизация: git pull

git init

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

Связанные руководства

Настройка репозитория: git init

git rebase -i

Флаг -i используется для начала интерактивного сеанса перенастройки. Это обеспечивает все преимущества обычного перебазирования, но дает вам возможность добавлять, редактировать или удалять коммиты по ходу выполнения.

Связанные руководства

История перезаписи: git rebase -i

git reflog

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

Связанные руководства

История перезаписи: git reflog

git удаленный

Удобный инструмент для администрирования удаленных подключений. Вместо того, чтобы передавать полный URL-адрес командам fetch, pull и push, он позволяет использовать более понятный ярлык.

Связанные руководства

Синхронизация: git remote

.

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

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