Введение
Системы контроля версиями полезны, когда они могут рассказать историю всех изменений.
Эта история может быть как реальный рассказ о жизни и развитии программной системы.
Но может быть и кучкой коммитов, разобраться в которых нельзя и которые не несут пользы.
В больших системах путаница может быть невероятных размеров.
Такие модели как Git Flow сильно облегчают жизнь, но только в том случае, если разработчики аккуратно относятся к своей истории коммитов, когда каждый коммит — это небольшой (или даже совсем крохотный) рассказ об одном исправлении в системе.
Это исправление настолько маленькое, что разобраться в нем не составляет труда, а название коммита, данное разработчиком, такое прозрачное, что заглядывать в тело коммита нет нужды.
Вести аккуратную историю помогает команда git rebase. Основная ее цель “перетаскивать” коммиты из одного места в другое.
Также с помощью нее можно избавляться от ненужных коммитов, склеивать одни и менять порядок других.
Умение пользоваться командой git rebase придает уверенности при работе с репозиторием.
Указатели на коммиты
Некоторые названия настолько неудачно подобраны, что, услышав термин, человек сразу понимает о чем идет речь, понимает приблизительно правильно и у него нет причин разбираться глубже.
Речь идет о ветках
Часто представляют ветку, как речку, ответвляющуюся от бурной реки и текущую дальше самостоятельно.
Поэтому кажется, что при создании ветки происходит что-то важное.
На деле ветка это просто указатель на коммит. Разница между хешом и веткой лишь та, что ветка перескакивает с одного коммита на другой по мере их добавления.
В остальном, ветка — это буквенный синоним хеша
Проще говоря, ветка указывает на коммит. Поэтому если ответвить 5 веток от master, то все они будут указывать на один и тот же коммит.
Однако новые коммиты будут свои в каждой из веток.
Можно ли и обрезать, и отгибать?
Всё на первый взгляд хорошо и просто, но есть в этой бочке мёда и своя ложка дёгтя. Дело в том, что дереву, по большому счёту, «до лампочки», чего вы от него хотите, оно хочет и будет расти вверх, к свету. На практике это приводит к такой картине. Вы согнули ветку, а дерево (обычно ближе к месту изгиба) выпустило множество вертикальных побегов, как бы взамен согнутой.
Поэтому самый главный вывод для садовода – если вы начали формировать дерево, то ли это обрезка, то ли отгибание, бросать уже нельзя. Нужно из года в год и даже не один раз в год, продолжать начатое — удалять ненужное или отгибать очередную порцию вертикальных побегов.
Самым оптимальным вариантом для меня, оказалось сочетание двух методов формирования плодовых деревьев – обрезки и отгибания веток. Ветки молодых деревцев в основном отгибаю, формируя своеобразные ярусы, а на деревьях постарше сочетаю отгибание с обрезкой, стараясь формировать невысокую чашу. На мой взгляд, это самая удачная и удобная форма для любого плодового дерева.
Времени до начала вегетации ещё предостаточно и можно не спеша изучить и попробовать на своих деревьях этот «новый» метод, а обрезать, если что, всегда успеете.
Простой Rebase
Формат команды такой
Команда изменяет текущую ветку.
Переданный параметр — это просто указатель на новое начало коммитов. Пересоздаются (копируются) коммиты из диапазона ..HEAD .
То есть все предки текущего коммита (включая его самого) без предков коммита (включая его самого) .
Это то, что интуитивно можно назвать как “новые” коммиты.
Но в Merge все наоборот!
- При ребейзинге текущая ветка — ветка с задачей, а ребейзятся относительно главной ветки.
- При слиянии текущей задачи — переключаются на главную ветку и сливают ветку с задачей.
Правило простое — изменению подвержена всегда текущая ветка. Почти все команды в git следуют этому правилу.
- При ребейзинге главная ветка не трогается, изменяется ветка с задачей — она пересоздается в другом месте.
- При слиянии главная ветка изменяется — в ней создается мерж-коммит. Ветка с задачей наоборот остается в прежнем виде.
Поэтому при ребейзинге придется дважды переключаться с ветки на ветку
Однако если использоваться слияние для подтягивания изменений, то сценарий похожий
Разница есть только со сценарием завершения задачи
Таким образом, для того, чтобы определить “что и куда”, надо задать вопрос “какую ветку надо изменить?”.
Находиться следует в той ветке, которую надо изменить.
Какие приспособления понадобятся?
В принципе, если вы садовод ответственный, то можно использовать крепкую верёвку или проволоку, завязывая их вокруг ветки. А причём тут ответственность? Дело в том, что дерево растёт, а ветви утолщаются, рано или поздно эта ваша верёвка или проволока начнут впиваться в древесину и перекрывать отток питательных веществ из кроны к корням (кстати, это тоже повысит урожайность).
Лучше этого не делать, потом эта конструкция врастёт в кору и покалечит ветку. Самый лучший, на мой взгляд, вариант — это использовать широкие полосы крепкого синтетического материала, длиной примерно 20 см и шириной 3-5 см, по обеим сторонам которых установлены металлические люверсы. Я использую их диаметром 14 мм. Установить их можно либо в специальной мастерской, либо самостоятельно, используя нехитрые приспособления.
Такое крепление имеет большой зазор и не препятствует росту ветки, мало того, оно многоразовое. Легко устанавливается, снимается, переставляется с ветки на ветку, с одного дерева на другое. Кстати, именно такими «хомутами» пользуются профессиональные садоводы во всём мире.
В нужном месте, чтобы соблюдался правильный угол отхождения (ок. 60 градусов), в землю под небольшим углом вбивается колышек, и второй конец верёвки крепится к нему. Конечно, получается не очень удобно – верёвки мешают проходу и, главное, становится неудобно косить траву в районе приствольного круга. Можно попробовать (и иногда это удаётся) крепить конец верёвки к штамбу самого же дерева. Тогда получается компактно и даже по-своему красиво.
Обычно ветки фиксируют на один сезон. Поставили зимой или весной, вот и пусть стоят до осени, как правило, ветка за несколько месяцев «запоминает» это положение.
Кстати, отгибать ветки можно не только у плодовых деревьев для увеличения урожая, но и у декоративных, для устранения «однобокости» и придания дереву нужной формы кроны.
Обычно ветки фиксируют на один сезон. Игорь Билевич
Почему ветки нужно формировать горизонтально?
Давайте начнём немного издалека. Если где-то по соседству растёт плодовое дерево, за которым никто не ухаживает, или перестали ухаживать, то подойдите и внимательно его рассмотрите. Скорее всего, вы увидите большое количество вертикально растущих веток, которые наперегонки тянутся к свету. Садоводами давным-давно было замечено, что на таких вертикальных побегах практически нет плодов, на них не формируются цветочные почки. Зато формируется большое количество ростовых почек, которые, загущая друг друга, во что бы то ни стало стремятся вверх.
Естественно, нас садоводов такое положение вещей никак не устраивает, нам от плодового дерева нужен урожай. И опять же садоводами было замечено, что горизонтально расположенная ветка, наоборот, плодоносит очень обильно.
Итак, первое для чего нужно отгибать ветки плодовых деревьев — для увеличения урожая. Но не только…
Отгибая ветки от вертикального положения, мы как бы раскрываем крону, даём возможность солнечному свету проникнуть внутрь кроны и равномерно осветить каждую веточку. А это приводит к образованию большего количества цветочных почек, и, как следствие, дерево будет лучше плодоносить. Более того, открытая, незагущенная, хорошо продуваемая и прогреваемая крона меньше подвержена всяким заболеваниям, ведь влага там долго не задерживается, да и насекомым-вредителям выживать сложнее.
Ну и третий важный момент. Ведь плодовые деревья мы (большинство из нас) выращиваем для получения урожая. А это значит, что с деревом в течении сезона нужно проводить множество операций: обрезать, опрыскивать, лечить раны, собирать урожай. Согласитесь, всё это гораздо удобнее, проще, а главное, эффективней делать, если до каждой части дерева можно дотянуться рукой и не лазить при этом на лестницы, стремянки и прочие шаткие конструкции.
Не знаю, как у вас, а у меня всё то, до чего можно дотянуться рукой, получает максимальный уход, а то, что далеко (высоко), получает уход по остаточному принципу, мол, потом… успеется. Даже самый приятный момент сбора урожая на высоком дереве превращается в испытание, и зачастую плоды там и остаются или сами падают на землю, разбиваются и уже никому не нужны. Получается, вроде, и есть дерево в саду, и оно даёт урожай, а толку от него мало. Я считаю, 2,5 метра — это максимальная высота для плодового дерева, чтобы его можно было эффективно использовать и обрабатывать.
Оптимальным углом нагибания веток будет примерно 60 градусов
Пересоздание коммитов
Пересоздать коммит просто. Предположим типичную ситуацию — необходимо добавить фичу А. Создается отдельная ветка feature/A/super_code от ветки develop.
На данном этапе новая ветка указывает по-прежнему на самый свежий коммит.
Пусть фича мысленно разбивается на два коммита.
Первый коммит с успехом создается.
В это время в ветку develop добавляются важные коммиты с важным классом Х, без которого завершить фичу А не получится.
Что же делать? Подтягивать изменения. Можно слить ветку develop в ветку с задачей. Безопасно, но история будет подпорчена. Делается ребейзинг
Предполагается, что develop уже содержит новые коммиты, то есть, что уже были сделаны fetch/pull.
Как работает команда git rebase? В простом случае, это работает так:
- текущая ветка перестает указывать на текущий коммит
- коммиты, которые есть в текущей ветке, но которых нет в develop (то есть новые коммиты) пересоздаются от последнего коммита в develop
- текущая ветка начинает указывать на только что созданные коммиты
- старые коммиты остаются висячими — на них ветка с задачей больше не указывает
Ниже приведены три дерева коммита
Ветка с задачей исходит из актуального коммита
Код разработки обновился, ветка с задачей исходит из старого коммита
Выполнен ребейзинг, ветка с задачей исходит из актуального коммита
Стоит обратить внимание на хеш коммита до ребейзинга (8f26890) и после (3b16148). Разумеется, по старому хешу можно найти старый коммит
Создадим ветку, указывающую на старый коммит
Дерево коммитов:
Нетрудно видеть, что старый коммит остался в целости и сохранности, однако, если на него никто не указывает, то он не отображается в истории коммитов.
Такие висячие коммиты удаляются сборщиком мусора в последствии (например, через месяц).
Создание коммита
Каждый коммит (кроме начального) имеет родительский коммит, который для него аналог “предыдущего”.
Из одного коммита может выходить несколько дочерних коммитов.
Это делается с помощью ветвления. А так как ветки могут соединяться в одну, то у коммита может быть и несколько родительских коммитов.
Обычно их два, но есть возможность сделать merge трех и более коммитов одновременно.
Иногда коммит бывает создан не в том месте и не в то время.
Не в том месте означает, что он был создан не в той ветке, а не в то время означает, что коммит был создан, но потом ветка разработки обогатилась новым кодом и хочется пересоздать коммит, начиная с более свежего кода.
О структуре коммитов
Коммит — это изменения в файлах репозитория + дополнительная информация. Идентифицируются коммиты с помощью sha-1 хеша.
Коммиты с одинаковым хешем — одинаковые, с разными хешами — разные.
Коммит хранит дату создания, поэтому если создать два одинаковых по содержанию коммита, то они будут иметь разные хеши и будут разными.
Так происходит при выполнение команды git commit –amend — команда перезаписывает текущий коммит и даже если ничего не изменилось, хеш все равно станет новым.
Ребейзинг переприменяет коммиты, то есть создает коммиты с таким же содержанием, но в другом месте. Новые коммиты получат новые хеши.
Интерактивный Rebase
Ребейзинг позволяет также переписывать историю своих коммитов.
Одна из таких ситуаций.
В ветке с задачей 40 коммитов.
Последние 2 отвечают за добавления фичи, а предыдущие 38 — это долгий и опасный рефакторинг.
Для истории достаточно иметь один коммит для рефакторинга, поэтому эти коммиты следует склеить в один.
Такая команда делает то же самое, что и раньше, но перед этим открывает текстовый редактор, в котором можно изменить поведение по умолчанию.
Удаление записи о коммите — удаляет коммит, а точнее не создает его. Изменение порядка записей вызывает изменение порядка создания коммитов.