Git (3) Merge, Reset и Clone

Слияние

Вы уже прекрасно освоили коммитинг и ветвление, и нет нужды снова повторять отработанные пункты этого руководства. Однако прежде чем мы пойдем дальше, я прошу вас добавить еще один коммит в ветвь master. Пусть эта фиксация будет содержать новый файл D:\MyTestProject\MySweetheart.txt. Как вы понимаете, содержание этого файла я не вправе вам диктовать. Поэтому внесите в него сами то имя, которое сочтете нужным. И я тоже так сделаю. А вам не покажу. И вы никому не показывайте.

А еще я изменю содержание файла test_file.txt (да-да, в который раз уже), ведь его содержание не соответствует действительности: сейчас я бодр и готов к работе! Пожалуй, так в него и запишу: I’m in good spirits!

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




А теперь сделаем кое-что новенькое. В главном меню Git Gui выберем вкладку «Слияние»; далее «Локальное слияние». В новом окне мы видим некоторые настройки, которые можно произвести перед слиянием. Они не многочисленны, и нас интересует лишь ветвь, которую мы будем «вливать» в активную (1.). У нас имеется только две ветви, поэтому выбор «что во что вливать» не слишком велик.

image018

Примечание: Убедитесь, что активной является ветвь master. При таких настройках, other «вольется» в master, а не наоборот. Всегда проверяйте, какая ветвь активна!

Но прежде, чем жать «Слияние», давайте прикинем, что мы имеем (см. рисунок):

image019

Есть две ветви: master и other. Каждая из них содержит файлы. При слиянии все файлы other перейдут в master, а значит в master будут: MySweetheart.txt (как был этот файл – так и будет; отметка OK) и media\song.txt (просто унаследуется из other; зеленая стрелочка). А вот с файлом test_file.txt будут проблемы (красная стрелочка). Каждая из ветвей содержит этот файл, причем с разным текстом. В этом случае возникнет конфликт. Но, будьте уверены, мы сможем решить его! Поэтому теперь смело щелкаем «Слияние» (2.). Конечно же, проблема возникает.

image020

Git обнаружил пересекающиеся строки и теперь просит нас разрешить эту ситуацию. Это совсем несложно, достаточно открыть test_file.txt в текстовом редакторе и убрать ненужные строчки (как на рисунке ниже). Обратите внимание, Git сам совместил информацию из обоих файлов и разделил коллизирующие блоки линией из знаков ‘=’. В блоке HEAD находятся строки из master, в блоке other – из ветви other.

image021

Сделав необходимую правку и сохранив изменения в файле, откроем Git Gui и перечитаем файлы. Теперь все должно быть хорошо и можно с чистой совестью закончить слияние. Теперь проект примет следующий вид:

image022

Мы видим, что ветвь other замкнулась на master, но продолжила существовать. Она по-прежнему может быть выбрана активной, и от нее по-прежнему может быть ответвлена другая ветвь. Также в нее можно продолжать добавлять фиксации (например, если разработка фичи продолжается). В общем, можно делать все то, что мы уже делали ранее.

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

image023

Здесь же был разобран более сложный случай, и если вы справились с ним, то слияние без коллизий покажется вам сущим пустяком. Вот так-то. Как всегда напоминаю, было бы неплохо, если бы вы еще потренировались сливать ветви, прежде чем идти дальше. Разберите самостоятельно в своей «песочнице» случай, когда пересекаются несколько строк в одном файле. Или, еще лучше, несколько строк в нескольких файлах. Впрочем, если вы уверены, что все освоили, то можно идти дальше, как думаете?

Откаты (переходы)

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




Возврат делается через интерфейс gitk. Переключитесь на ветвь master (если она не является активной) и кликните ПКМ по второму коммиту в этой ветви. Сейчас мы «обрежем» ветвь master до второго коммита, т.е. оставим только первую и вторую фиксацию. Прочие коммиты этой ветви пропадут. Выберем из списка «Установить ветвь master на это состояние».

image024

В появившемся диалоговом окне Git предложит нам выбрать тип операции перехода. Давайте разберем все варианты.

  1. Легкий. При таком откате изменения в рабочем каталоге не произойдут, а также «под капотом» Git будет считать, что мы вообще не делали отката, а по-прежнему находимся на том же коммите, где и были. Этот тип перехода, как правило, используется для того, чтобы в дальнейшем ответвить от старого коммита текущей ветви новую ветвь, если вы по какой-то причине забыли сделать это ранее. При этом более новые коммиты не удалятся, к ним можно будет снова вернуться и продолжить работать с репозиторием.
  2. Смешанный. Этот тип перехода несколько похож на предыдущий, однако это не совсем так. При таком переходе рабочий каталог также не изменится, а вот все коммиты, следующие за тем, на который осуществляется переход, будут удалены. Таким образом получается, что мы вернемся ко второму коммиту master (это будет отображено в дереве проекта), а состояние рабочей папки останется таким же, как оно было на момент слияния ветвей master и other, т.е. не изменится. После этого мы сможем сделать новый коммит в ветвь master и он будет включать в себя все изменения, которые были внесены коммитами «Oh, my sweetheart!» и «Merge branch other». Этот переход применяется в тех случаях, когда между двумя фиксациями существует много промежуточных фиксаций, которые вносят незначительные изменения. Эти изменения, как правило, фиксируют в одном коммите, вместо тех нескольких.
  3. Жесткий. Наиболее интересный случай. При этом откате все коммиты, следующие за вторым в ветви master, прекратят свое существование, а файлы рабочей папки вернутся к состоянию, зафиксированному коммитом «Second commit». Именно этот тип мы выберем.

image025

После выбора типа операции перехода «Жесткий…»(1.) мы кликаем «Окей» (2.). На первый взгляд ничего не изменилось, но это совсем не так! Дело в том, что нам нужно обновить состояние проекта в gitk, чтобы он заметил изменения. Для этого выберете «Файл → Перечитать». Вот теперь мы видим, что дерево проекта вернулось к состоянию, в котором находился проект на момент окончания раздела «Ветвление» (помните такой раздел?). Если же вы откроете рабочую папку, то увидите, что некоторые файлы в ней также откатились к своим ранним версиям, а иные и вовсе перестали существовать.

image026

С прочими типами переходов я предлагаю вам ознакомиться самостоятельно в «песочнице». А я перехожу к заключительному этапу.

Пушинг и клонирование

На данном этапе предполагается, что вы уже освоили все основные команды для работы с локальным репозиторием и можете самостоятельно решать, когда делать коммит, когда ветвление, а когда слияние, и в каком все это порядке. Если вы не уверены в собственных силах и знаниях, рекомендуется закрепить пройденное тренировкой в собственном репозитории-«песочнице». А если вы готовы идти дальше, то я не вправе вас больше задерживать.

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

Итак, чтобы ваши изменения были запомнены в локальном репозитории нужно:

  1. Внести эти изменения в рабочую папку.
  2. Добавить файлы в очередь на индексацию.
  3. Закоммитить изменения, предварительно заполнив поле комментария.

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

  1. Отправить изменения на сервер (запушить).

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

image027

В поле «Исходное положение» (1.) нужно указать адрес удаленного репозитория, а в поле «Каталог назначения» – путь, по которому будет располагаться склонированный репозиторий на вашем компьютере. Кстати, на самом деле папка sfml-game-test не располагается по заданному пути; Git сам создаст ее и поместит туда клон хранилища. После заполнения обозначенных полей можно нажать «Склонировать» (3.).

image028

Примечание: Вообще-то, существует несколько протоколов обмена данными между клиентом и сервером. Я не считаю нужным рассказывать здесь об этом. Но вам нужно знать, что при введенных мною данных будет использоваться протокол https. Подробнее можно почитать тут. Также обратите внимание, что мною был указан адрес хранилища sfml-game-test, и, если вы, как и я, являетесь участником этого проекта, то можете указать тот же адрес. В противном случае, вам следует указать адрес другого репозитория, к которому вы имеете доступ.

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

Давайте добавим тренировочный коммит в склонированный репозиторий, который является локальным, а потом запушим изменения на сервер. Если вы участник проекта sfml-game-test, то создайте в папке junk папку со своим ником и добавьте туда какой-нибудь файл. Если вы не являетесь участником данного проекта, то можете внести любое изменение в рабочую папку по своему вкусу. После этого сделайте фиксацию, как делали это прежде. Как только закончите с коммитингом, можно переходить к отправке изменений на сервер. Для этого в основном  окне Git Gui выберете «Внешние репозитории», а затем «Отправить…» или просто нажмите кнопку «Отправить» слева от поля для комментариев.

image029

В окне отправки нужно выбрать ветвь, которую вы будете отправлять (3.) Репозиторий назначения вы можете задать двумя путями: указать адрес явно (5.) или выбрать из внесенных в переменные (4.). В данном случае выбрана переменная origin, соответствующая репозиторию-образцу, с которого ранее мы склонировали нашу копию. Жмем «Отправить» (6.).

После этого Git попросит вас ввести логин и пароль от вашей учетной записи на сайте хостинга (GitHub в данном случае). Через некоторое время изменения будут отправлены на сервер и вы увидите ваш файл в глобальном хранилище. Я, например, отправил туда свой HelloWorld. А что отправили вы?

image030

Стоит заметить, что если ветвь, в которую вы вносите изменения, была изменена другим участником, пока вы вносили свои изменения, Git выдаст соответствующую ошибку и предложит вам синхронизировать ваш репозиторий с сервером. Но обычно таких ошибок не возникает, т.к. в ХОРОШИХ проектах каждый программист имеет собственную ветвь, в которой делает что хочет (а вернее, что нужно). На всякий случай покажу, что ошибка будет выглядеть примерно так:

image031

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

А еще вы можете получать изменения с сервера и обновлять уже существующий локальный репозиторий. Для этого используется функция «Внешние репозитории → Получение из → <имя репозитория>». При таком способе синхронизации вы получите все изменения с сервера, но также и сохраните свои. Попробуйте этот способ самостоятельно.

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

Заключение без выводов

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

Большое спасибо за внимание!

Автор

MatrixDeity

MatrixDeity

Хреновый модератор

Буду благодарен, если поделитесь:
SFML вопросы, прошу, задавайте на форуме.

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