Что такое система контроля версий git
Что такое Git и для чего он нужен
В этом руководстве пойдёт речь об основах Git. Вы узнаете, зачем нужен контроль версий, как работают системы контроля версий. В дальнейшем информация позволит успешно освоить практическую работу с Git.
Какие задачи решает контроль версий
Независимо от выбранного языка или направления разработки, код, который пишет программист, остаётся обычным текстом, записанным в множестве файлов на диске. Эти файлы регулярно добавляются, удаляются и изменяются. Некоторые из них могут содержать сотни строчек кода, а другие тысячи. Файлы в тысячу строк кода — вполне нормальное явление в программировании.
Пока проект состоит из пары-тройки файлов, его разработка не создаёт никаких сложностей. Программист пишет код, запускает его и радуется жизни. Клиент доволен, заказчик тоже. С ростом кодовой базы появляются определённые неудобства, которые затем превращаются в реальные проблемы:
Представьте, что ваш проект состоит из сотни файлов и десятков тысяч строк кода. Вы делаете какую-то задачу, в процессе меняете 15 файлов и 300 строк кода и вдруг становится понятно, что эта задача больше не актуальна. На этом моменте нужно вернуться к состоянию исходного кода, которое было до изменений. И это только один из множества вариантов событий. Другой вариант — в процессе работы над кодом стало понятно, что нужно срочно внести исправление в рабочий проект (сайт). Новую задачу в нерабочем состоянии выкладывать на сайт нельзя, а это значит, что исправление нужно вносить в ту версию кода, которая была до начала реализации новой задачи.
Самый простой вариант решения, указанных выше проблем — копирование директорий. К сожалению, такой подход обладает только недостатками. Перенос изменений из одной директории в другую возможен только полной перезаписью, так как точечные изменения отследить невозможно (только по памяти). Как только папок станет две, вы сразу начнёте путаться в них. И всё равно этот способ никак не поможет работать над кодом одновременно двум людям.
Совместная разработка — это отдельная головная боль. Если два программиста работают над задачами, требующими исправления кода в одних и тех же файлах, то как они выполнят эту работу так, чтобы не повредить или перезаписать изменения другого разработчика?
К счастью, эту задачу решили ещё в 80-х годах. С тех пор инструментарий сильно развился и стал использоваться повсеместно не только для кода, но и, например, для написания и перевода книг. Решением является контроль версий. Выполняется он с помощью специальных программ, которые умеют отслеживать изменения кода. Вот некоторые из многочисленных возможностей данных систем:
В этом руководстве мы разберём общие принципы работы подобных программ.
Как работает контроль версий
Системы контроля версий (СКВ или VCS — Version Control System) часто встроены в инструменты, привычные даже далёким от программирования людям. Именно с них мы и начнём своё знакомство, а заодно погрузимся в соответствующую терминологию.
Сервисы синхронизации файлов между устройствами, такие как Dropbox, используются практически всеми. И все они отслеживают версии файлов, с которыми работают. Происходит это так: периодически программа синхронизирует локальные файлы с теми, которые находятся в хранилище сервиса. Если локальный файл отличается, и время его изменения – позже файла, находящегося на сервере, то файл на сервере становится частью истории изменений, а текущим становится последний изменённый файл.
На картинке выше текущая версия файла обозначена как current. Всё остальное – это предыдущие версии текущего файла. Как видно, Dropbox позволяет восстановить любую версию файла.
Обратите внимание на эту фразу:
Dropbox keeps a snapshot every time you save a file. (Дропбокс сохраняет снимок каждый раз, когда вы сохраняете файл)
Снимок (snapshot; разг. снепшот) – очень важное понятие, которое будет встречаться нам в будущем. Его ещё называют снимком состояния или даже мгновенным снимком (буквальный перевод), но для простоты будем называть его просто «снимок».
В данном случае, снимок – это сам файл после изменения. И чтобы лучше понять этот термин, посмотрим на альтернативу — дельту изменения (diff). Представьте, что вместо сохранения новой версии файла Dropbox бы вычислял разницу между новым и старым файлом (а это не сложно сделать для текстовых файлов) и сохранял только её. Зачем так делать, спросите вы? Такой подход позволяет сэкономить место на диске, хотя и вносит дополнительную сложность при работе с файлами.
В дальнейшем мы увидим, что разные инструменты используют разные подходы: некоторые работают с дельтой изменений, другие — со снимками. Кстати, термин «снимок» часто применяют к дискам. Например, можно сделать снимок диска и потом восстанавливаться с этой точки (прямо как в играх).
Другим хорошим примером использования контроля версий являются текстовые редакторы, в первую очередь онлайновые.
Сервис Google Docs автоматически делает снимки после каждого автосохранения (примерно раз в 5 секунд). Если документ за это время не изменился, то, естественно, новая версия не появляется. Множество таких версий образуют историю изменений.
На картинке выше история версий называется “Revision history”. Ревизия — базовое понятие систем контроля версий. Любое зафиксированное изменение в системе контроля версий называется ревизией.
Обратите внимание на то, что ревизия и снимок – это не одно и то же. Фиксация изменений создаёт ревизию, но сама ревизия может содержать внутри себя либо дельту изменений, либо снимок.
Кстати, процесс переключения между ревизиями также имеет своё название. Когда мы загружаем конкретную ревизию, то говорят, что переключаемся на неё (checkout).
Между ревизиями можно выявлять различия в случае, если СКВ использует снимки, что демонстрирует нам Microsoft Word на картинке выше. Эту функциональность невозможно переоценить,поскольку посмотреть «а что же изменилось» требуется постоянно не только при работе с кодом. Приведу пример из собственной практики: согласование разных юридических документов (договоров) происходит сквозь череду правок. После того, как юристы поправили договор, хочется увидеть, а что же там изменилось.
Более того, в системах Linux есть команда diff, с помощью которой можно выяснить различия между любыми файлами даже без использования СКВ. Эти изменения можно сохранить в файл, а затем, используя программу patch, применить к исходному файлу.
В программах, разобранных выше, создание ревизии привязано к автосохранению, но это не единственная стратегия. Всего используется три способа:
Последнее используется уже при работе с кодом.
Какие бывают системы контроля версий
Во всех предыдущих примерах мы рассматривали СКВ, встроенные прямо в программы, в частности, в текстовые редакторы. А СКВ для исходного кода отделены от используемых средств разработки (хотя могут быть дополнительно интегрированы с ними).
Это связано с тем что, исходный код, по сути, является набором текстовых (и бинарных) файлов. Кто, как и где будет их редактировать, заранее знать невозможно. Кроме того, автоматическое создание ревизий становится крайне неудобным.
В СКВ для кода процесс создания ревизии называется фиксацией (commit; разг. коммит). На работе вы будете часто слышать фразу «закоммитишь?» или «я закоммитил». Более того, обычно, вместо слова «ревизия» употребляют слово «коммит». И мы тоже так будем делать.
При работе с кодом важно, чтобы изменения в рамках одного коммита подчинялись определённым правилам. Только в таком случае можно будет воспользоваться всеми преимуществами СКВ. К таким требованиям относятся:
Кроме этих базовых, существует и множество других рекомендаций входящих в понятие «хороший коммит».
Какие бы вы не использовали СКВ, базовый рабочий процесс один. Выглядит он так:
Под репозиторием понимается набор файлов и директорий, которые находятся под контролем версий.
СКВ принято делить на поколения, каждое из которых сильно изменяло подходы к работе.
Первое поколение
Второе поколение
CVS, SourceSafe, Subversion
Работать в этих системах без доступа к серверу нельзя. Вы не сможете буквально ничего. Посмотреть историю, сделать коммит, откатиться на другую версию, всё это становится невозможно сделать без интернета.
Третье поколение
Git, Bazaar, Mercurial
Заключение
Вы узнали, для чего используют Git, а также принципы работы систем контроля версий. Эта информация поможет вам осваивать практическую работу с Git в рамках выбранной профессии. Вопросы задавайте в комментариях.
О системах контроля версий
Всем привет! Уже на следующей неделе в OTUS стартует «Супер-практикум по использованию и настройке GIT». Этому я и решил посвятить сегодняшнюю публикацию.
Введение
Системы контроля версий
Система контроля версий является прежде всего инструментам, а инструмент призван решать некоторый класс задач. Итак, система контроля версий – это система, записывающая изменения
в файл или набор файлов в течение времени и позволяющая вернуться позже к определенной версии. Мы хотим гибко управлять некоторым набором файлом, откатываться до определенных версий в случае необходимости. Можно отменить те или иные изменения файла, откатить его удаление, посмотреть кто что-то поменял. Как правило системы контроля версий применяются для хранения исходного кода, но это необязательно. Они могут применяться для хранения файлов совершенно любого типа.
Как хранить различные версии файлов? Люди пришли к такому инструменту как системы контроля версий не сразу, да и они сами бывают очень разные. Предложенную задачу можно решить с применением старого доброго copy-paste, локальных, централизованных или распределенных систем контроля версий.
Copy-paste
Известный метод при применении к данной задаче может выглядеть следующим образом: будем называть файлы по шаблону filename_
Данный способ является очень простым, но он подвержен различным ошибкам: можно случайно изменить не тот файл, можно скопировать не из той директории (ведь именно так переносятся файлы в этой модели).
Локальная система контроля версий
Следующим шагом в развитии систем контроля версий было создание локальных систем контроля версий. Они представляли из себя простейшую базу данных, которая хранит записи обо всех изменениях в файлах.
Одним из примеров таких систем является система контроля версий RCS, которая была разработана в 1985 году (последний патч был написан в 2015 году) и хранит изменений в файлах (патчи), осуществляя контроль версий. Набор этих изменений позволяет восстановить любое состояние файла. RCS поставляется с Linux’ом.
Локальная система контроля версий хорошо решает поставленную перед ней задачу, однако ее проблемой является основное свойство — локальность. Она совершенно не преднезначена для коллективного использования.
Централизованная система контроля версий
Централизованная система контроля версий предназначена для решения основной проблемы локальной системы контроля версий.
Для организации такой системы контроля версий используется единственный сервер, который содержит все версии файлов. Клиенты, обращаясь к этому серверу, получают из этого централизованного хранилища. Применение централизованных систем контроля версий на протяжении многих лет являлась стандартом. К ним относятся CVS, Subversion, Perforce.
Такими системами легко управлять из-за наличия единственного сервера. Но при этом наличие централизованного сервера приводит к возникновению единой точки отказа в виде этого самого сервера. В случае отключения этого сервера разработчики не смогут выкачивать файлы. Самым худшим сценарием является физическое уничтожение сервера (или вылет жесткого диска), он приводит к потерю кодовой базы.
Несмотря на то, что мода на SVN прошла, иногда наблюдается обратный ход — переход от Git’а к SVN’у. Дело в том, что SVN позволяет осуществлять селективный чекаут, который подразумевает выкачку лишь некоторых файлов с сервера. Такой подход приобретает популярность при использовании монорепозиториях, о которых можно будет поговорить позже.
Распределенная система контроля версий
Для устранения единой точки отказа используются распределенные системы контроля версий. Они подразумевают, что клиент выкачает себе весь репозиторий целиком заместо выкачки конкретных интересующих клиента файлов. Если умрет любая копия репозитория, то это не приведет к потере кодовой базы, поскольку она может быть восстановлена с компьютера любого разработчика. Каждая копия является полным бэкапом данных.
Все копии являются равноправным и могут синхронизироваться между собой. Подобный подход очень напоминает (да и является) репликацией вида master-master.
К данному виду систем контроля версий относятся Mercurial, Bazaar, Darcs и Git. Последняя система контроля версий и будет рассмотрена нами далее более детально.
История Git
В 2005 году компания, разрабатывающая систему контроля версий BitKeeper, порвала отношения с сообществом разработчиков ядра Linux. После этого сообщество приняло решение о разработке своей собственной системы контроля версий. Основными ценностями новой системы стали: полная децентрализация, скорость, простая архитектура, хорошая поддержка нелинейной разработки.
Заключение
Мы рассмотрели способы организации систем контроля версий, обсудили варианты решения поставленных перед этими системами задач, поговорили о преимуществах и недостатках каждого из них, познакомились с историей системы контроля версий Git.
Git: полное руководство
Оглавление Базовые концепции Настройка среды Жизненный цикл Операция Create Операция Clone Perform изменения Review изменения Commit изменения Push операция Update…
Оглавление
Git – это распределенная система контроля версий и управления исходным кодом с упором на скорость. Первоначально Git был разработан и разработан Линусом Торвальдсом для разработки ядра Linux. Git – это бесплатное программное обеспечение, распространяемое в соответствии с условиями GNU General Public License версии 2. В этом руководстве объясняется, как использовать Git для управления версиями проекта в распределенной среде при разработке веб-приложений и приложений, не основанных на веб-технологиях.
Это руководство поможет новичкам изучить базовые функции системы контроля версий Git. После завершения этого руководства вы обнаружите, что обладаете умеренным опытом в использовании системы контроля версий Git, откуда вы сможете перейти на следующий уровень.
Мы предполагаем, что вы собираетесь использовать Git для обработки всех уровней Java и не-Java проектов. Так что будет хорошо, если у вас будет некоторое знакомство с жизненным циклом разработки программного обеспечения и практические знания по разработке веб-приложений и приложений, не основанных на Интернете.
Базовые концепции
Система контроля версий
Система контроля версий (VCS) – это программное обеспечение, которое помогает разработчикам программного обеспечения работать вместе и вести полную историю своей работы.
Ниже перечислены функции VCS –
Ниже приведены типы VCS –
В этой главе мы сосредоточимся только на распределенной системе контроля версий и особенно на Git. Git подпадает под распределенную систему контроля версий.
Распределенная система контроля версий
Централизованная система контроля версий (CVCS) использует центральный сервер для хранения всех файлов и обеспечивает совместную работу команды. Но главный недостаток CVCS – это ее единственная точка отказа, то есть отказ центрального сервера. К сожалению, если центральный сервер выйдет из строя на час, то в течение этого часа никто вообще не сможет сотрудничать. И даже в худшем случае, если диск центрального сервера будет поврежден и надлежащая резервная копия не будет сделана, вы потеряете всю историю проекта. Здесь на сцену выходит распределенная система контроля версий (DVCS).
Клиенты DVCS не только проверяют последний снимок каталога, но также полностью зеркалируют репозиторий. Если сервер выходит из строя, то репозиторий с любого клиента можно скопировать обратно на сервер, чтобы восстановить его. Каждая выписка – это полная резервная копия репозитория. Git не полагается на центральный сервер, и поэтому вы можете выполнять множество операций, когда находитесь в автономном режиме. Вы можете фиксировать изменения, создавать ветки, просматривать журналы и выполнять другие операции в автономном режиме. Сетевое подключение требуется только для публикации ваших изменений и принятия последних изменений.
Преимущества Git
1. Бесплатный и открытый исходный код
Git выпускается под лицензией GPL с открытым исходным кодом. Он доступен бесплатно в Интернете. Вы можете использовать Git для управления проектами недвижимости, не платя ни копейки. Поскольку это открытый исходный код, вы можете загрузить его исходный код, а также внести изменения в соответствии с вашими требованиями.
2. Быстрый и маленький
Поскольку большинство операций выполняется локально, это дает огромное преимущество с точки зрения скорости. Git не полагается на центральный сервер; поэтому нет необходимости взаимодействовать с удаленным сервером для каждой операции. Основная часть Git написана на C, что позволяет избежать накладных расходов времени выполнения, связанных с другими языками высокого уровня. Хотя Git отражает весь репозиторий, размер данных на стороне клиента невелик. Это демонстрирует эффективность Git при сжатии и хранении данных на стороне клиента.
3. Неявное резервное копирование
Шансы на потерю данных очень редки, если их несколько копий. Данные, присутствующие на любой стороне клиента, отражают репозиторий, поэтому их можно использовать в случае сбоя или повреждения диска.
4. Безопасность
Git использует общую криптографическую хеш-функцию, называемую защищенной хеш-функцией (SHA1), для именования и идентификации объектов в своей базе данных. Каждый файл и фиксация проверяются и извлекаются по контрольной сумме во время проверки. Это означает, что невозможно изменить файл, дату, сообщение фиксации и любые другие данные из базы данных Git, не зная Git.
5. Нет необходимости в мощном оборудовании
В случае CVCS центральный сервер должен быть достаточно мощным, чтобы обслуживать запросы всей команды. Для небольших команд это не проблема, но по мере роста размера команды аппаратные ограничения сервера могут стать узким местом для производительности. В случае DVCS разработчики не взаимодействуют с сервером, если им не нужно отправлять или извлекать изменения. Вся тяжелая работа выполняется на стороне клиента, поэтому серверное оборудование действительно может быть очень простым.
6. Более легкое ветвление
CVCS использует дешевый механизм копирования. Если мы создадим новую ветвь, она скопирует все коды в новую ветку, поэтому это требует много времени и неэффективно. Кроме того, удаление и объединение ветвей в CVCS сложно и требует много времени. Но управлять ветками с помощью Git очень просто. Создание, удаление и объединение веток занимает всего несколько секунд.
Терминология DVCS
Локальный репозиторий
Каждый инструмент VCS предоставляет частное рабочее место в качестве рабочей копии. Разработчики вносят изменения на своем рабочем месте, и после фиксации эти изменения становятся частью репозитория. Git делает еще один шаг вперед, предоставляя им частную копию всего репозитория. Пользователи могут выполнять множество операций с этим репозиторием, например добавлять файл, удалять файл, переименовывать файл, перемещать файл, фиксировать изменения и многое другое.
Рабочий каталог и промежуточная область или индекс
Рабочий каталог – это место, где файлы извлекаются. В других CVCS разработчики обычно вносят изменения и фиксируют свои изменения непосредственно в репозитории. Но Git использует другую стратегию. Git не отслеживает каждый измененный файл. Каждый раз, когда вы фиксируете операцию, Git ищет файлы в промежуточной области. Только те файлы, которые присутствуют в промежуточной области, рассматриваются для фиксации, а не все измененные файлы.
Давайте посмотрим на основной рабочий процесс Git.
Предположим, вы изменили два файла, а именно «sort.c» и «search.c», и вам нужно два разных коммита для каждой операции. Вы можете добавить один файл в промежуточную область и выполнить фиксацию. После первой фиксации повторите ту же процедуру для другого файла.
Блобы(Blobs)
Блоб означает большой двоичный объект. Каждая версия файла представлена большим двоичным объектом. Большой двоичный объект содержит данные файла, но не содержит метаданных о файле. Это двоичный файл, и в базе данных Git он называется хеш-кодом SHA1 этого файла. В Git к файлам не обращаются по именам. Все адресовано по содержанию.
Древо(Trees)
Древо – это объект, представляющий каталог. Он содержит блобы, а также другие подкаталоги. Древо – это двоичный файл, в котором хранятся ссылки на большие двоичные объекты и деревья, которые также называются хешем SHA1 объекта древа.
Коммиты(Commits)
Коммит содержит текущее состояние репозитория. Коммит также называется хешем SHA1. Вы можете рассматривать объект фиксации как узел связанного списка. Каждый объект фиксации имеет указатель на родительский объект фиксации. От заданной фиксации вы можете вернуться назад, посмотрев на родительский указатель, чтобы просмотреть историю фиксации. Если у фиксации есть несколько родительских коммитов, то эта конкретная фиксация была создана путем слияния двух ветвей.
Ветви(Branches)
Ветви используются для создания еще одной линии развития. По умолчанию у Git есть основная ветка, такая же, как и в Subversion. Обычно ветка создается для работы над новой функцией. Как только функция завершена, она снова объединяется с основной веткой, и мы удаляем ветку. На каждую ветку ссылается HEAD, который указывает на последнюю фиксацию в ветке. Каждый раз, когда вы делаете коммит, HEAD обновляется последней фиксацией.
Теги(Tags)
Тег присваивает значимое имя определенной версии в репозитории. Теги очень похожи на ветки, но разница в том, что теги неизменяемы. Значит, тег – это ветка, которую никто не собирается изменять. После создания тега для конкретной фиксации, даже если вы создаете новую фиксацию, он не будет обновлен. Обычно разработчики создают теги для выпусков продуктов.
Клонировать(Clone)
Операция клонирования создает экземпляр репозитория. Операция клонирования не только проверяет рабочую копию, но также отражает весь репозиторий. Пользователи могут выполнять множество операций с этим локальным репозиторием. Единственный раз, когда в сеть включается, – это когда экземпляры репозитория синхронизируются.
Операция Pull копирует изменения из экземпляра удаленного репозитория в локальный. Операция Pull используется для синхронизации между двумя экземплярами репозитория. Это то же самое, что и операция обновления в Subversion.
Операция push копирует изменения из экземпляра локального репозитория в удаленный. Это используется для постоянного хранения изменений в репозитории Git. Это то же самое, что и операция фиксации в Subversion.
HEAD – это указатель, который всегда указывает на последнюю фиксацию в ветке. Каждый раз, когда вы делаете коммит, HEAD обновляется последней фиксацией. Головы веток хранятся в каталоге .git/refs/heads/
Revision
Revision представляет собой версию исходного кода. Редакции в Git представлены коммитами. Эти коммиты идентифицируются безопасными хэшами SHA1.
URL-адрес представляет собой расположение репозитория Git. URL-адрес Git хранится в файле конфигурации.
Настройка среды
Прежде чем вы сможете использовать Git, вам необходимо установить и внести некоторые базовые изменения конфигурации. Ниже приведены шаги по установке клиента Git в Ubuntu и Centos Linux.
Установка клиента Git
Если вы используете базовый дистрибутив Debian GNU/Linux, то команда apt-get сделает все необходимое.
И если вы используете дистрибутив GNU / Linux на основе RPM, используйте команду yum, как указано.
Настройка среды Git
Вы также можете настроить общесистемную конфигурацию. Git хранит эти значения в файле /etc/gitconfig, который содержит конфигурацию для каждого пользователя и репозитория в системе. Чтобы установить эти значения, вы должны иметь права root и использовать параметр –system.
Когда приведенный выше код компилируется и выполняется, он дает следующий результат:
Установка имени пользователя
Эта информация используется Git для каждого commit.
Установка идентификатора электронной почты
Эта информация используется Git для каждого commit.
Избегайте слияния коммитов для pulling
Вы делаете pull последних изменений из удаленного репозитория, и если эти изменения расходятся, то по умолчанию Git создает коммиты слияния. Этого можно избежать с помощью следующих настроек.
Цветовое выделение
Следующие команды включают выделение цветом для Git в консоли.
Установка редактора по умолчанию
По умолчанию Git использует системный редактор по умолчанию, который берется из переменной среды VISUAL или EDITOR. Мы можем настроить другой, используя git config.
Установка инструмента merge по умолчанию
Git не предоставляет инструмент merge по умолчанию для интеграции конфликтующих изменений в ваше рабочее древо. Мы можем установить инструмент merge по умолчанию, включив следующие настройки.
Вывод настроек Git
Чтобы проверить настройки Git в локальном репозитории, используйте команду git config –list, как показано ниже.
Приведенная выше команда даст следующий результат.
Жизненный цикл
В этой главе мы обсудим жизненный цикл Git. В следующих главах мы рассмотрим команды Git для каждой операции.
Общий рабочий процесс выглядит следующим образом –
Ниже показано графическое изображение рабочего процесса.
Операция Create
В этой главе мы увидим, как создать удаленный репозиторий Git; с этого момента мы будем называть его Git Server. Нам нужен сервер Git для совместной работы команды.
Создать нового пользователя
Приведенная выше команда даст следующий результат.
Создать пустой репозиторий
Создание пары ключей RSA Public / Private RSA
Давайте рассмотрим процесс настройки Git-сервера, утилита ssh-keygen генерирует пару публичных / частных ключей RSA, которые мы будем использовать для аутентификации пользователя.
Приведенная выше команда даст следующий результат.
ssh-keygen сгенерировал два ключа, первый из которых является частным (т.е. id_rsa), а второй – открытым (т.е. id_rsa.pub).
Примечание. Никогда не сообщайте свой ЧАСТНЫЙ КЛЮЧ другим людям.
Добавление ключей в authorized_keys
Предположим, что над проектом работают два разработчика, а именно Том и Джерри. Оба пользователя сгенерировали открытые ключи. Давайте посмотрим, как использовать эти ключи для аутентификации.
Том добавил свой открытый ключ на сервер с помощью команды ssh-copy-id, как показано ниже –
Приведенная выше команда даст следующий результат.
Точно так же Джерри добавил свой открытый ключ на сервер с помощью команды ssh-copy-id.
Приведенная выше команда даст следующий результат.
Отправление изменений в репозиторий
Мы создали чистый репозиторий на сервере и разрешили доступ двум пользователям. С этого момента Том и Джерри могут отправлять свои изменения в репозиторий, добавляя его как дистанционный.
Том создает новый каталог, добавляет файл README и фиксирует свое изменение как начальную фиксацию. После фиксации он проверяет сообщение фиксации, выполнив команду git log.
Приведенная выше команда даст следующий результат.
Том проверяет сообщение журнала, выполнив команду git log.
Приведенная выше команда даст следующий результат.
Том зафиксировал свои изменения в локальном репозитории. Теперь пришло время отправить изменения в удаленный репозиторий. Но перед этим надо добавить репозиторий как пульт, это разовая операция. После этого он может безопасно отправить изменения в удаленный репозиторий.
Примечание. По умолчанию Git отправляет только соответствующие ветки: для каждой ветки, которая существует на локальной стороне, удаленная сторона обновляется, если ветка с таким же именем уже существует там. В наших руководствах каждый раз, когда мы отправляем изменения в исходную главную ветку, используйте соответствующее имя ветки в соответствии с вашими требованиями.
Приведенная выше команда даст следующий результат.
Теперь изменения успешно зафиксированы в удаленном репозитории.
Операция Clone
У нас есть пустой репозиторий на сервере Git, и Том также выпустил свою первую версию. Теперь Джерри может просматривать свои изменения. Операция Clone создает экземпляр удаленного репозитория.
Джерри создает новый каталог в своем домашнем каталоге и выполняет операцию клонирования.
Приведенная выше команда даст следующий результат.
Джерри меняет каталог на новый локальный репозиторий и перечисляет его содержимое.
Perform изменения
Джерри клонирует репозиторий и решает реализовать основные строковые операции. Итак, он создает файл string.c. После добавления содержимого string.c будет выглядеть следующим образом:
Он скомпилировал и протестировал свой код, и все работает нормально. Теперь он может безопасно добавить эти изменения в репозиторий.
Операция Git add добавляет файл в область подготовки.
Git показывает вопросительный знак перед именами файлов. Очевидно, что эти файлы не являются частью Git, и именно поэтому Git не знает, что с этими файлами делать. Вот почему Git показывает вопросительный знак перед именами файлов.
Джерри добавил файл в область хранения, команда git status покажет файлы, присутствующие в области подготовки.
Чтобы зафиксировать изменения, он использовал команду git commit с опцией –m. Если мы опускаем опцию –m. Git откроет текстовый редактор, в котором мы можем написать многострочное сообщение commit.
Приведенная выше команда даст следующий результат –
После commit для просмотра сведений журнала он запускает команду git log. Он будет отображать информацию обо всех коммитах с их commit ID, commit author, commit date и хешем SHA-1 фиксации.
Приведенная выше команда даст следующий результат –
Review изменения
После просмотра деталей фиксации Джерри понимает, что длина строки не может быть отрицательной, поэтому он решает изменить тип возвращаемого значения функции my_strlen.
Джерри использует команду git log для просмотра деталей журнала.
Приведенная выше команда даст следующий результат.
Джерри использует команду git show для просмотра деталей коммита. Команда git show принимает в качестве параметра идентификатор фиксации SHA-1.
Приведенная выше команда даст следующий результат –
Он меняет тип возвращаемого значения функции с int на size_t. После тестирования кода он проверяет свои изменения, выполнив команду git diff.
Приведенная выше команда даст следующий результат –
Git diff показывает знак «+» перед новыми добавленными строками и «-» для удаленных строк.
Commit изменения
Джерри уже зафиксировал изменения и хочет исправить свой последний коммит. В этом случае поможет операция git 180. Операция изменения изменяет последний коммит, включая ваше сообщение коммита; он создает новый идентификатор коммита.
Перед операцией изменения он проверяет журнал коммита.
Приведенная выше команда даст следующий результат.
Теперь git log покажет новое сообщение коммита с новым идентификатором commit ID –
Приведенная выше команда даст следующий результат.
Push операция
Джерри изменил свой последний коммит, используя операцию amend, и он готов отправить(push) изменения. Операция Push сохраняет данные постоянно в репозитории Git. После успешной операции отправки другие разработчики смогут увидеть изменения Джерри.
Он выполняет команду git log, чтобы просмотреть детали коммита.
Приведенная выше команда даст следующий результат:
Перед операцией push он хочет просмотреть свои изменения, поэтому он использует команду git show для просмотра своих изменений.
Приведенная выше команда даст следующий результат:
Джерри доволен своими изменениями, и он готов отправить свои изменения.
Приведенная выше команда даст следующий результат:
Изменения Джерри были успешно отправлены в репозиторий; теперь другие разработчики могут просматривать его изменения, выполняя операцию клонирования или обновления.
Update операция
Изменение существующущей функции
Том выполняет операцию клонирования и находит новый файл string.c. Он хочет знать, кто добавил этот файл в репозиторий и с какой целью, поэтому он выполняет команду git log.
Приведенная выше команда даст следующий результат –
Операция Clone создаст новый каталог внутри текущего рабочего каталога. Он меняет каталог на вновь созданный каталог и выполняет команду git log.
Приведенная выше команда даст следующий результат –
После просмотра журнала он понимает, что файл string.c был добавлен Джерри для реализации основных строковых операций. Ему интересно узнать код Джерри. Итак, он открывает string.c в текстовом редакторе и сразу находит ошибку. В функции my_strlen Джерри не использует постоянный указатель. Итак, он решает изменить код Джерри. После модификации код выглядит следующим образом –
Приведенная выше команда даст следующий результат –
После тестирования он делает коммит своего изменения.
Приведенная выше команда даст следующий результат –
Приведенная выше команда даст следующий результат –
Добавить новую функцию
Тем временем Джерри решает реализовать функцию сравнения строк. Итак, он модифицирует string.c. После модификации файл выглядит следующим образом –
Приведенная выше команда даст следующий результат –
После тестирования он готов внести свои изменения.
Перед операцией push он проверяет фиксацию, просматривая сообщения журнала.
Приведенная выше команда даст следующий результат –
Джерри доволен изменениями, и он хочет их отправить.
Приведенная выше команда даст следующий результат –
Но Git не позволяет Джерри отправить свои изменения. Потому что Git определил, что удаленный репозиторий и локальный репозиторий Джерри не синхронизированы. Из-за этого он может потерять историю проекта. Чтобы избежать этого беспорядка, Git провалил эту операцию. Теперь Джерри должен сначала обновить локальный репозиторий, и только после этого он сможет внести свои изменения.
Получить последние изменения
Джерри выполняет команду git pull для синхронизации своего локального репозитория с удаленным.
Приведенная выше команда даст следующий результат –
После операции pull, Джерри проверяет сообщения журнала и находит сведения о commit Тома с commit ID cea2c000f53ba99508c5959e3e12fff493ba6f69.
Приведенная выше команда даст следующий результат –
Теперь локальный репозиторий Джерри полностью синхронизирован с удаленным репозиторием. Так что он может спокойно отправлять свои изменения.
Приведенная выше команда даст следующий результат –
Stash операция
Предположим, вы внедряете новую функцию для своего продукта. Ваш код находится в разработке, и внезапно приходит эскалация клиентов. Из-за этого вам придется отложить работу над новой функцией на несколько часов. Вы не можете сделать коммит своего частичного кода, а также не можете выбросить свои изменения. Поэтому вам нужно временное пространство, где вы можете сохранить свои частичные изменения, а затем сделать их коммит.
В Git операция stash берет ваши измененные отслеживаемые файлы, обрабатывает изменения и сохраняет их в стеке незавершенных изменений, которые вы можете повторно применить в любое время.
Теперь вы хотите сменить ветвь для эскалации клиентов, но не хотите делать коммит того, над чем еще работали; так что вы сохраните изменения. Чтобы отправить новый stash в свой стек, выполните команду git stash.
Теперь ваш рабочий каталог чист, и все изменения сохранены в стеке. Давайте проверим это с помощью команды git status.
Теперь вы можете смело переключать ветку и работать в другом месте. Мы можем просмотреть список сохраненных изменений, используя команду git stash list.
Предположим, вы разрешили проблему эскалации клиентов и вернулись к своей новой функции в поисках своего недоделанного кода, просто выполните команду git stash pop, чтобы удалить изменения из стека и поместить их в текущий рабочий каталог.
Приведенная выше команда даст следующий результат:
Move операция
Как следует из названия, операция move перемещает каталог или файл из одного места в другое. Том решает переместить исходный код в каталог src. Измененная структура каталогов будет выглядеть следующим образом –
Чтобы сделать эти изменения постоянными, мы должны отправить измененную структуру каталогов в удаленный репозиторий, чтобы другие разработчики могли это увидеть.
В локальном репозитории Джерри перед операцией pull будет показана старая структура каталогов.
Но после операции извлечения структура каталогов обновится. Теперь Джерри может видеть каталог src и файл, находящийся внутри этого каталога.
Rename операция
До сих пор и Том, и Джерри использовали ручные команды для компиляции своего проекта. Теперь Джерри решает создать Makefile для своего проекта, а также присвоить файлу собственное имя «string.c».
Git показывает R перед именем файла, чтобы указать, что файл был переименован.
После коммита он отправляет свои изменения в репозиторий.
Приведенная выше команда даст следующий результат –
Теперь другие разработчики могут просматривать эти изменения, обновляя свой локальный репозиторий.
Delete операция
Том обновляет свой локальный репозиторий и находит скомпилированный двоичный файл в каталоге src. После просмотра сообщения о фиксации он понимает, что скомпилированный двоичный файл был добавлен Джерри.
VCS используется для хранения только исходного кода, а не исполняемых двоичных файлов. Итак, Том решает удалить этот файл из репозитория. Для дальнейшей работы он использует команду git rm.
После коммита он отправляет свои изменения в репозиторий.
Приведенная выше команда даст следующий результат.
Исправление ошибок
Человеку свойственно ошибаться. Таким образом, каждая VCS предоставляет возможность исправлять ошибки до определенного момента. Git предоставляет функцию, которую мы можем использовать для отмены изменений, внесенных в локальный репозиторий.
Предположим, пользователь случайно внес некоторые изменения в свой локальный репозиторий, а затем хочет отменить эти изменения. В таких случаях важную роль играет операция возврата(revert).
Отмена незафиксированных изменений
Предположим, Джерри случайно изменяет файл из своего локального репозитория. Но он хочет отменить свою модификацию. Чтобы справиться с этой ситуацией, мы можем использовать команду git checkout. Мы можем использовать эту команду, чтобы вернуть содержимое файла.
Кроме того, мы можем использовать команду git checkout для получения удаленного файла из локального репозитория. Предположим, Том удаляет файл из локального репозитория, и мы хотим вернуть этот файл. Мы можем добиться этого, используя ту же команду.
Git показывает букву D перед именем файла. Это означает, что файл был удален из локального репозитория.
Примечание. Мы можем выполнить все эти операции до коммита.
Удаление изменений из промежуточной области
Мы видели, что когда мы выполняем операцию добавления, файлы перемещаются из локального репозитория в указанную область. Если пользователь случайно изменяет файл и добавляет его в промежуточную область, он может отменить свои изменения с помощью команды git checkout.
В Git есть один указатель HEAD, который всегда указывает на последний коммит. Если вы хотите отменить изменение в поэтапной области, вы можете использовать команду git checkout, но с командой checkout вы должны указать дополнительный параметр, то есть указатель HEAD. Дополнительный параметр указателя коммита указывает команде git checkout сбросить рабочее древо, а также удалить поэтапные изменения.
Предположим, Том изменяет файл из своего локального репозитория. Если мы просмотрим статус этого файла, он покажет, что файл был изменен, но не добавлен в область подготовки.
Статус Git показывает, что файл присутствует в промежуточной области, теперь верните его, используя команду git checkout, и просмотрите статус возвращенного файла.
Перемещение указателя HEAD с помощью Git Reset
Сделав несколько изменений, вы можете решить удалить эти изменения. Команда сброса Git используется для сброса или отмены изменений. Мы можем выполнить три различных типа операций сброса.
На диаграмме ниже показано графическое представление команды сброса Git.
Каждая ветка имеет указатель HEAD, указывающий на последнюю фиксацию. Если мы используем команду сброса Git с параметром –soft, за которым следует commit ID, тогда он сбросит только указатель HEAD, ничего не разрушая.
Теперь просмотрите последний commit ID, который будет соответствовать указанному выше commit ID.
Приведенная выше команда даст следующий результат.
Сбросим указатель HEAD.
Commit ID из файла изменен, теперь проверьте его, просмотрев сообщения коммита.
Приведенная выше команда даст следующий результат.
mixed
Git reset с параметром –mixed отменяет те изменения из промежуточной области, которые еще не были зафиксированы. Он отменяет изменения только из области подготовки. Фактические изменения, внесенные в рабочую копию файла, не затрагиваются. Сброс Git по умолчанию эквивалентен сбросу git – смешанному.
Если вы используете опцию –hard с командой сброса Git, она очистит промежуточную область; он сбросит указатель HEAD на последний коммит конкретного идентификатора фиксации и также удалит изменения локального файла.
Давайте проверим commit ID.
Приведенная выше команда даст следующий результат.
Джерри изменил файл, добавив однострочный комментарий в начале файла.
Он проверил это с помощью команды git status.
Приведенная выше команда даст следующий результат.
Статус Git показывает, что файл присутствует в промежуточной области. Теперь сбросьте HEAD с опцией – hard.
Команда сброса Git выполнена успешно, которая вернет файл из промежуточной области, а также удалит все локальные изменения, внесенные в файл.
Статус Git показывает, что файл был возвращен из промежуточной области.
Команда head также показывает, что операция сброса также удалила локальные изменения.
Tag операция
Операция Tag позволяет дать осмысленные имена конкретной версии в репозитории. Предположим, Том и Джерри решили пометить код своего проекта, чтобы впоследствии легко получить к нему доступ.
Создание тэгов
Если вы хотите пометить конкретный коммит, используйте соответствующий идентификатор COMMIT вместо указателя HEAD. Том использует следующую команду, чтобы поместить тег в удаленный репозиторий.
Приведенная выше команда даст следующий результат –
Просмотр тегов
Том создал теги. Теперь Джерри может просматривать все доступные теги, используя команду Git tag с параметром –l.
Джерри использует команду Git show, за которой следует имя тега, чтобы просмотреть дополнительные сведения о теге.
Приведенная выше команда даст следующий результат –
Удаление тегов
Том использует следующую команду для удаления тегов как из локального, так и из удаленного репозитория.
Patch операция
Patch – это текстовый файл, содержимое которого похоже на Git diff, но вместе с кодом в нем также есть метаданные о коммитах; например, commit ID, дата, сообщение коммита и т. д. Мы можем создать патч из коммитов, и другие люди могут применить их к своему репозиторию.
Джерри реализует функцию strcat для своего проекта. Джерри может создать путь своего кода и отправить его Тому. Затем он может применить полученный патч к своему коду.
Джерри использует команду Git format-patch для создания патча для последней фиксации. Если вы хотите создать патч для конкретной фиксации, используйте COMMIT_ID с командой format-patch.
Чтобы применить патч и создать коммит, используйте следующую команду –
Патч успешно применен, теперь мы можем просмотреть изменения с помощью команды git diff.
Приведенная выше команда даст следующий результат –
Управление ветвями
Операция Branch позволяет создать еще одно направление развития. Мы можем использовать эту операцию, чтобы разделить процесс разработки на два разных направления. Например, мы выпустили продукт для версии 6.0, и мы могли бы захотеть создать ветку, чтобы разработка функций 7.0 могла быть отделена от исправлений ошибок 6.0.
Создание ветки
Создана новая ветка; Том использовал команду git branch, чтобы вывести список доступных веток. Git показывает звездочку перед выбранной веткой.
Наглядное представление операции создания ветки показано ниже –
Переключение между ветками
Джерри использует команду git checkout для переключения между ветвями.
Ярлык для создания и переключения ветки
В приведенном выше примере мы использовали две команды для создания и переключения ветвей соответственно. Git предоставляет параметр –b с командой checkout; эта операция создает новую ветку и немедленно переключается на новую ветку.
Удаление ветки
Ветку можно удалить, указав параметр –D с командой git branch. Но перед удалением существующей ветки переключитесь на другую ветку.
Джерри в настоящее время находится на test_branch и хочет удалить эту ветку. Поэтому он переключает ветку и удаляет ветку, как показано ниже.
Теперь Git покажет только две ветки.
Переименовывание ветки
Джерри решает добавить поддержку широких символов в свой проект строковых операций. Он уже создал новую ветку, но имя ветки не подходит. Поэтому он меняет имя ветки, используя параметр –m, за которым следует имя старой ветки и имя новой ветки.
Теперь команда git branch покажет новое имя ветки.
Объединие двух ветвей
Джерри реализует функцию для возврата длины строки из строки широких символов. Новый код будет выглядеть следующим образом –
Приведенная выше команда дает следующий результат –
После тестирования он делает коммит и помещает свои изменения в новую ветку.
Обратите внимание, что Джерри переносит эти изменения в новую ветку, поэтому он использовал имя ветки wchar_support вместо главной ветки.
Приведенная выше команда даст следующий результат.
После фиксации изменений новая ветка будет выглядеть следующим образом –
Тому интересно, что делает Джерри в своей частной ветке, и он проверяет журнал ветки wchar_support.
Приведенная выше команда даст следующий результат.
Просматривая сообщения коммита, Том понимает, что Джерри реализовал функцию strlen для широких символов и ему нужна такая же функциональность в главной ветви. Вместо повторной реализации он решает взять код Джерри, объединив свою ветку с основной веткой.
После операции слияния главная ветвь будет выглядеть следующим образом:
Теперь ветка wchar_support объединена с главной ветвью. Мы можем проверить это, просмотрев сообщение о фиксации или просмотрев изменения, внесенные в файл string_operation.c.
Приведенная выше команда даст следующий результат.
После тестирования он отправляет свои изменения кода в основную ветку.
Перебазировать ветви
Команда Git rebase – это команда слияния веток, но разница в том, что она изменяет порядок коммитов.
Команда Git merge пытается поместить коммиты из других веток поверх HEAD текущей локальной ветки. Например, ваша локальная ветка имеет коммиты A-> B-> C-> D, а ветвь слияния имеет коммиты A-> B-> X-> Y, тогда git merge преобразует текущую локальную ветвь во что-то вроде A-> B-> C-> D-> X-> Y
Команда Git rebase пытается найти общего предка между текущей локальной веткой и ветвью слияния. Затем он отправляет коммиты в локальную ветвь, изменяя порядок коммитов в текущей локальной ветке. Например, если ваша локальная ветка имеет коммиты A-> B-> C-> D, а ветвь слияния имеет коммиты A-> B-> X-> Y, то Git rebase преобразует текущую локальную ветку во что-то вроде A- > B-> X-> Y-> C-> D.
Когда несколько разработчиков работают с одним удаленным репозиторием, вы не можете изменить порядок коммитов в удаленном репозитории. В этой ситуации вы можете использовать операцию rebase, чтобы поместить ваши локальные коммиты поверх коммитов удаленного репозитория, и вы можете отправить эти изменения.
Разрешение конфликтов
Внесение изменений в ветку wchar_support
Джерри работает над веткой wchar_support. Он меняет название функций и после тестирования делает коммит своих изменений.
Приведенная выше команда дает следующий результат –
После проверки кода он фиксирует свои изменения.
Приведенная выше команда даст следующий результат –
Выполнение изменений в главной ветви
Тем временем в главной ветке Том также меняет имя той же функции и передает свои изменения в главную ветку.
Приведенная выше команда дает следующий результат –
После проверки diff он фиксирует свои изменения.
Приведенная выше команда даст следующий результат –
В ветви wchar_support Джерри реализует функцию strchr для строки широких символов. После тестирования он фиксирует и отправляет свои изменения в ветку wchar_support.
Приведенная выше команда дает следующий результат –
После проверки он фиксирует свои изменения.
Приведенная выше команда даст следующий результат –
Разрешение конфликтов
Том хочет увидеть, что Джерри делает в своей частной ветке, поэтому он пытается получить последние изменения из ветки wchar_support, но Git прерывает операцию со следующим сообщением об ошибке.
Приведенная выше команда дает следующий результат –
Как разрешить конфликты
Из сообщения об ошибке видно, что существует конфликт в src/string_operations.c. Он запускает команду git diff, чтобы просмотреть дополнительные сведения.
Приведенная выше команда дает следующий результат –
Поскольку и Том, и Джерри изменили имя одной и той же функции, Git находится в замешательстве и просит пользователя разрешить конфликт вручную.
Том решает сохранить имя функции, предложенное Джерри, но оставил комментарий, добавленный им, как есть. После удаления маркеров конфликта git diff будет выглядеть так.
Приведенная выше команда дает следующий результат.
Поскольку Том изменил файлы, он должен сначала зафиксировать эти изменения, а после этого он сможет их извлечь.
Том разрешил конфликт, теперь операция извлечения завершится успешно.
Разные платформы
РУССКИЙGNU / Linux и Mac OS используют перевод строки (LF) или новую строку в качестве символа конца строки, тогда как Windows использует комбинацию перевода строки и возврата каретки (LFCR) для представления символа конца строки.
Чтобы избежать ненужных коммитов из-за этих различий в конце строки, мы должны настроить клиент Git для записи того же окончания строки в репозиторий Git.
Для системы Windows мы можем настроить клиент Git для преобразования окончаний строк в формат CRLF при извлечении и преобразования их обратно в формат LF во время операции фиксации. Следующие настройки сделают необходимое.
Для GNU / Linux или Mac OS мы можем настроить клиент Git для преобразования окончаний строк из CRLF в LF при выполнении операции проверки.
Интернет-репозитории
GitHub – это веб-хостинг для проектов разработки программного обеспечения, использующий систему контроля версий Git. Он также имеет стандартное приложение с графическим интерфейсом, доступное для загрузки (Windows, Mac, GNU / Linux) непосредственно с веб-сайта службы. Но в этом сеансе мы увидим только часть CLI.
Создание репозитория GitHub
Зайдите на github.com. Если у вас уже есть учетная запись GitHub, войдите с помощью этой учетной записи или создайте новую. Следуйте инструкциям на сайте github.com, чтобы создать новый репозиторий.
Push операция
Том решает использовать сервер GitHub. Чтобы начать новый проект, он создает новый каталог и один файл внутри него.
Приведенная выше команда даст следующий результат:
После проверки своего кода он инициализирует каталог с помощью команды git init и фиксирует свои изменения локально.
После этого он добавляет URL-адрес репозитория GitHub в качестве удаленного источника и отправляет свои изменения в удаленный репозиторий.
Операция push запросит имя пользователя и пароль GitHub. После успешной аутентификации операция завершится успешно.
Приведенная выше команда даст следующий результат:
С этого момента Том может отправлять любые изменения в репозиторий GitHub. Он может использовать все команды, обсуждаемые в этой главе, с репозиторием GitHub.
Pull операция
Том успешно отправил все свои изменения в репозиторий GitHub. Теперь другие разработчики могут просмотреть эти изменения, выполнив операцию клонирования или обновив свой локальный репозиторий.
Джерри создает новый каталог в своем домашнем каталоге и клонирует репозиторий GitHub с помощью команды git clone.
Приведенная выше команда дает следующий результат:
Он проверяет содержимое каталога, выполняя команду ls.