Как сжимать коммиты в Git с помощью git squash
Aug 31, 2020 · 5 min read
Git squash — это прием, который помогает взять серию коммитов и уплотнить ее. Например, предположим: у вас есть серия из N коммитов и вы можете путем сжатия преобразовать ее в один-единственный коммит. Сжатие через git squash в основном применяется, чтобы превратить большое число малозначимых коммитов в небольшое число значимых. Так становится легче отслеживать историю Git.
Также этот прием используется при объединении ветвей. Чаще всего вам будут советовать всегда сжимать коммиты и выполнять перебазирование с родительской ветвью (например, master или develop ). В таком случае история главной ветки будет содержать только значимые коммиты, без ненужной детализации.
Как именно делать git squash
Возьмем для примера следующую историю Git:
Здесь видны последние три коммита. В сообщениях к ним поясняется, что мы добавили новый файл и какое-то содержимое. Лучше заменить их одним единственным коммитом о том, что произошло добавление нового файла с некоторым содержимым. Итак, давайте посмотрим, как сжать последние три коммита в один:
3 означает, что мы берем последние три коммита.
Здесь изменилось сообщение о коммите, и обратите внимание: три коммита “склеились” в один. Также изменился хэш коммита. Через git rebase всегда создается новый коммит, содержащий соответствующие изменения.
Так что используйте этот инструмент с осторожностью.
Помните: сжатие коммитов меняет историю Git, поэтому не рекомендуется сжимать ветвь, если вы уже отправили ее в удаленный репозиторий. Всегда выполняйте сжатие до того, как отправить пуш с изменениями.
Применение fixup для сжатия коммитов
Обратите внимание: хэш коммита также изменился, а сообщение о коммите берется из “основного” коммита, с которым были сжаты другие два.
Применение сжатия при слиянии ветвей
Git также предоставляет возможность сжатия при объединении ветвей. Во многих случаях она может оказаться полезной. Чтобы добавить новый функционал или поправить какие-то баги, нам понадобится то и дело что-то изменять в ветвях. Поэтому, когда мы будем готовы слить эти изменения в основную ветвь ( master или develop ), для начала следует применить сжатие.
Давайте рассмотрим следующую команду:
Она берет все коммиты из целевой ветви, сжимает их и сохраняет все изменения в текущей ветви. Затем вы можете зафиксировать все изменения в одном коммите. На примере это выглядит так:
Сжатие коммитов через Github
Возможность сжимать коммиты предоставляет и Github. Эта функция особенно полезна при пулл-реквесте.
Сначала производится сжатие, затем — слияние. Так что вместо пяти коммитов получится один.
Как видно на картинке, выполняется всего один коммит с соответствующим сообщением.
Спасибо за чтение! Надеюсь, вы почерпнули из статьи что-то новое 🙂
Как склеить коммиты и зачем это нужно
Другие материалы по Git
Когда вы открываете пулреквест, и ваш код смотрят и комментируют другие, бывает нужно что-то исправить. Обычно такие изменения мы комментируем сообщением вроде «Увеличил шрифт на 2px» или «Поменял оттенок фона в шапке». Такие маленькие изменения интересны только пока они в пулреквесте. Ревьювер (человек, который смотрит ваш код), может легко узнать, что и когда вы изменили, а не читать весь diff заново, а вы можете легко откатить коммит, если он не нужен. Но когда приходит время вливать пулреквест, эти маленькие коммиты теряют свою ценность. Поэтому лучше их склеить в один. Как — я расскажу вам сегодня.
Как подготовиться
Для некоторых операций из этой статьи гит будет открывать текстовый редактор. Во многих системах по умолчанию это Vim. Не самый дружелюбный для новичков. Чтобы вам было комфортно, установите в качестве гит-редактора ваш любимый редактор. Это делается с помощью команды:
Например, если у вас Mac OS, и вы хотите установить Atom в качестве редактора по умолчанию, введите:
А если у вас Windows, и вы хотите установить Notepad++ в качестве гит-редактора, ваша команда будет такая:
Вам нужно просто узнать команду для запуска вашего редактора и подставить её. Вот список команд для популярных редакторов.
Git — инструмент фронтендера
Пройдите обучение в HTML Academy, чтобы работать с системами контроля версий и другими инструментами как профессионал.
Как склеивать коммиты
Сначала узнаем, сколько коммитов нужно склеить. Эта команда покажет, какие коммиты у вас прибавились по сравнению с веткой master:
Отлично, у меня 5 коммитов. Теперь я хочу переписать историю с момента HEAD
Тут список моих коммитов и большой комментарий о том, что я могу сделать. Из списка комманд видно, что мы можем использовать squash или fixup для того, чтобы склеить коммиты. Первый пригодится тогда, когда вы хотите изменить коммит-месседж, а второй — когда хотите использовать коммит-месседж первого. Итак, чтобы склеить все коммиты, я делаю вот так:

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

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

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

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

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

Сначала надо узнать хеш коммита, к которому этот коммит является правкой. Воспользуемся уже знакомым cherry :
Ага, вот он наш хеш. А теперь следующий коммит обозначим правкой к этому:
Необязательно в точности копировать весь хеш, достаточно первых 7 символов. Я обычно выделяю от начала и сколько выделится и копирую:

Добавим ещё несколько правок таким образом. Посмотрим изменения:
Отлично. А теперь склеим все эти коммиты. Только не вручную. Гит сделает это за нас:
И гит сам подставит слово fixup там, где нужно:
Просто сохраняем, и гит склеивает коммиты и использует коммит-месседж первого:

Как сжимать коммиты в Git с помощью git squash
Git squash — это прием, который помогает взять серию коммитов и уплотнить ее. Например, предположим: у вас есть серия из N коммитов и вы можете путем сжатия преобразовать ее в один-единственный коммит. Сжатие через git squash в основном применяется, чтобы превратить большое число малозначимых коммитов в небольшое число значимых. Так становится легче отслеживать историю Git.
Также этот прием используется при объединении ветвей. Чаще всего вам будут советовать всегда сжимать коммиты и выполнять перебазирование с родительской ветвью (например, master или develop ). В таком случае история главной ветки будет содержать только значимые коммиты, без ненужной детализации.
Как именно делать git squash
Возьмем для примера следующую историю Git:
Здесь видны последние три коммита. В сообщениях к ним поясняется, что мы добавили новый файл и какое-то содержимое. Лучше заменить их одним единственным коммитом о том, что произошло добавление нового файла с некоторым содержимым. Итак, давайте посмотрим, как сжать последние три коммита в один:
3 означает, что мы берем последние три коммита.
Как видите, для сжатия мы отметили последние два коммита с помощью команд squash или s .
Здесь изменилось сообщение о коммите, и обратите внимание: три коммита “склеились” в один. Также изменился хэш коммита. Через git rebase всегда создается новый коммит, содержащий соответствующие изменения.
Так что используйте этот инструмент с осторожностью.
Помните: сжатие коммитов меняет историю Git, поэтому не рекомендуется сжимать ветвь, если вы уже отправили ее в удаленный репозиторий. Всегда выполняйте сжатие до того, как отправить пуш с изменениями.
Применение fixup для сжатия коммитов
Обратите внимание: хэш коммита также изменился, а сообщение о коммите берется из “основного” коммита, с которым были сжаты другие два.
Применение сжатия при слиянии ветвей
Git также предоставляет возможность сжатия при объединении ветвей. Во многих случаях она может оказаться полезной. Чтобы добавить новый функционал или поправить какие-то баги, нам понадобится то и дело что-то изменять в ветвях. Поэтому, когда мы будем готовы слить эти изменения в основную ветвь ( master или develop ), для начала следует применить сжатие.
Давайте рассмотрим следующую команду:
Она берет все коммиты из целевой ветви, сжимает их и сохраняет все изменения в текущей ветви. Затем вы можете зафиксировать все изменения в одном коммите. На примере это выглядит так:
Сжатие коммитов через Github
Возможность сжимать коммиты предоставляет и Github. Эта функция особенно полезна при пулл-реквесте.
Сначала производится сжатие, затем — слияние. Так что вместо пяти коммитов получится один.
Как видно на картинке, выполняется всего один коммит с соответствующим сообщением.
Спасибо за чтение! Надеюсь, вы почерпнули из статьи что-то новое 🙂
Тонкости благополучного git-merge
Вступительное слово
Основными командами пользовательского уровня для ветвления в Git являются git-branch, git-checkout, git-rebase, git-log и, конечно же, git-merge. Для себя я считаю git-merge зоной наибольшей ответственности, точкой огромной магической энергии и больших возможностей. Но это достаточно сложная команда, и даже достаточно длительный опыт работы с Git порой бывает недостаточным для освоение всех ее тонкостей и умения применить ее наиболее эффективно в какой-либо нестандартной ситуации.
Попробуем же разобраться в тонкостях git-merge и приручить эту великую магию.
Здесь я хочу рассмотреть только случай благополучного слияния, под которым я понимаю слияние без конфликтов. Обработка и разрешение конфликтов — отдельная интересная тема, достойная отдельной статьи. Я очень рекомендую так же ознакомиться со статьей Внутреннее устройство Git: хранение данных и merge, содержащей много важной информации, на которую я опираюсь.
Анатомия команды
Если верить мануалу, команда имеет следующий синтаксис:
По большому счету, в Git есть два вида слияния: перемотка (fast-forward merge) и «истинное» слияние (true merge). Рассмотрим несколько примеров обоих случаев.
«Истинное» слияние (true merge)
Мы отклоняемся от ветки master, чтобы внести несколько багов улучшений. История коммитов у нас получилась следующая:
Выполним на ветке master git merge feature :
Посмотрим историю коммитов в тестовом репозитории, который я создал специально для этого случая:
А теперь посмотрим информацию о коммите (M):
Мы видим двух родителей, объект-дерево, соответствующее данному состоянию файлов репозитория, а так же информацию о том, кто виновен в коммите.
Посмотрим, куда ссылается указатель master:
Действительно, он теперь передвинут на коммит (M).
Squash и no-commit
В случае применения такого слияния коммиты ветки feature не будут включены в нашу историю, но коммит Sq будет содержать все их изменения:
Позже, в случае выполнения «классического» git merge feature можно исправить это. Тогда история примет следующий вид:
Перемотка (fast-forward merge)
Рассмотрим другой случай истории коммитов:
Все как и в прошлый раз, но теперь в ветке master нет коммитов после ответвления. В этом случае происходит слияние fast-forward (перемотка). В этом случае отсутствует коммит слияния, указатель (ветка) master просто устанавливается на коммит Y, туда же указывает и ветка feature:
Стратегии слияния
Стратегия resolve
Здесь C — общий коммит двух веток, дерево файлов, соответствующее этому коммиту, принимается за общего предка. Анализируются изменения, произведенные в ветках master и feature со времен этого коммита, после чего для коммита (M) создается новая версия дерева файлов в соответствии с пунктами 4 и 5 нашего условного алгоритма.
Стратегия recursive
Для иллюстрации этой стратегии позаимствуем пример из статьи Merge recursive strategy из блога «The plasticscm blog»:
Итак, у нас есть две ветки: main и task001. И так вышло, что наши разработчики знают толк в извращениях: они слили коммит 15 из ветки main с коммитом 12 из ветки task001, а так же коммит 16 с коммитом 11. Когда нам понадобилось слить ветки, оказалось, что поиск реального предка — дело неблагодарное, но стратегия recursive с ее конструированием «виртуального» предка нам поможет. В результате мы получим следующую картину:
]
Выполнение рекурсивного слияния с этой опцией будет более продвинутым вариантом стратегии subtree, где алгоритм основывается на предположении, как деревья должны совместиться при слиянии. Вместо этого в этом случае указывается конкретный вариант.
Стратегия octopus
Эта стратегия используется для слияние более чем двух веток. Получившийся в итоге коммит будет иметь, соответственно, больше двух родителей.
Данная стратегия предполагает большую осторожность относительно потенциальных конфликтов. В связи с этим порой можно получить отказ в слиянии при применении стратегии octopus.
Стратегия ours
Не следует путать стратегию ours и опцию ours стратегии recursive.
Стратегия ours — более радикальное средство.
Стратегия subtree
Для иллюстрации данной стратегии возьмем пример из главы Слияние поддеревьев книги «Pro Git».
Добавим в наш проект новые удаленный репозиторий, rack:
Ясно, что ветки master и rack_branch имеют абсолютно разные рабочие каталоги. Добавим файлы из rack_branch в master с использованием squash, чтобы избежать засорения истории ненужными нам фактами:
Теперь файлы проекта rack у нас в рабочем каталоге.
Что такое Squashing commits в git?
Что означает Squashing commits в git. Как сквош совершает в Github?
Я новичок в Git, и я попросил назначить ошибку новичка в coala-analyzer. Я исправил ошибку, и теперь меня попросили раздавить мои коммиты. Как мне это сделать?
3 ответов
вы можете думать о Git как о расширенной базе данных моментального снимка вашего рабочего каталога(ов).
одной из очень приятных особенностей Git является возможность переписать историю фиксации.
Основная причина этого заключается в том, что большая часть такой истории актуальна только для разработчика, который ее создал, поэтому ее необходимо упростить или сделать более приятной перед отправкой в общий репозиторий.
давя совершения означает, с идиоматической точки зрения с точки зрения, чтобы переместить изменения, внесенные в указанную фиксацию, в ее родитель, чтобы вы закончили с одной фиксацией из двух.
Если вы повторите этот процесс несколько раз, вы можете уменьшить n совершить один.
визуально, если вы начали свою работу в commit tagged старт, вы хотите, чтобы этот
вы можете заметить, что новый коммит имеет немного более темный оттенок синего. Это намеренный.
в Git squashing достигается с помощью Rebase, специальной формы под названием Интерактивные Перебазирования.
Упрощение при переназначении набора коммитов в ветвь B, вы применяете все изменения, внесенные этим коммитов, как они были сделаны, начиная с B вместо их первоначального предка.

снова обратите внимание на разные оттенки синего.
интерактивная rebase позволяет выбрать, как фиксация должна быть rebased, если вы запустите эту команду:
в конечном итоге вы получите файл, который перечислит фиксацию, которая будет перезагружена
Я не называл коммиты, но эти четыре предназначены для коммитов из старт to глава
самое приятное в этом списке то, что это редактируемые.
Вы можете опустить коммиты, или вы можете сквош них.
Все, что вам нужно сделать, это изменить первое слово сквош.
если вы закроете редактор и не найдете конфликтов слияния, вы получите эту историю:
в вашем случае вы не хотите перебазироваться в другую ветку, а скорее в предыдущую фиксацию.
Чтобы преобразовать историю, как показано в самом первом примере, у вас есть запустить что-то вроде
измените «команды» на сквош для всех коммитов, кроме первого, а затем закройте редактор.
примечание об изменении истории
в git commit никогда не редактируются, их можно обрезать, сделать недоступными, клонировать, но не изменять.
Когда вы rebase, вы фактически создаете новые коммиты.
Старые из них больше не доступны никаким ref, поэтому не отображаются в история, но они все еще там!
это то, что вы на самом деле получили для rebase:
если вы уже подтолкнули их куда-то, переписывание истории на самом деле сделает ветку!
Это означает объединение нескольких коммитов в один. Взгляните на :
предостережение: только делать это на коммиты, которые не имеют был нажат внешний репозиторий. Если у других есть работа с коммитами, которые вы собираетесь удалить, может возникнуть множество конфликтов. Просто не переписывайте свою историю, если она была передана другим.
Итак, предположим, вы только что сделали несколько небольших коммитов, и вы хотите сделать из них один больший. История нашего репозитория в настоящее время выглядит так:
последние 4 коммита были бы намного счастливее, если бы они были завернутый вместе, так что давайте сделаем это через интерактивную перебазировку:
Итак, здесь произошло несколько вещей. Прежде всего, я сказал Git, что хочу перебазировать последние четыре коммита, где HEAD находится с HEAD
4. Теперь Git поместил меня в Редактор с приведенным выше текстом и небольшим объяснением того, что можно сделать. У вас есть много вариантов, доступных для вас с этого экрана, но прямо сейчас мы просто раздавим все в одну фиксацию. Так, изменение первых четырех строк файла на это сделает трюк:
в основном это говорит Git объединить все четыре коммита в первый коммит в списке. Как только это будет сделано и сохранено, появится другой редактор со следующим:
поскольку мы объединяем так много коммитов, Git позволяет вам изменять сообщение нового коммита на основе остальных коммитов, участвующих в процессе. Отредактируйте сообщение по своему усмотрению, затем сохраните и закройте его. Однажды это сделано, ваши коммиты были успешно раздавлены!
и если мы снова посмотрим на историю…
































