Git как исключить коммиты из истории при слиянии в мастер-ветку?
Приветствую коллеги. Возможно вопрос очевиден, но очевидного ответа я так и не нашел. Предположим у нас есть мастер ветка в которой каждый коммит это выход новой версии/субверсии приложения. При желании добавить новую фичу, я копирую мастер-ветку, и в новой ветке может быть куча коммитов. Далее при слиянии эта куча включается в основную ветку. Как этого избежать? (если знаете как это сделать в SourceTree, вообще крутяк). Добра вам!))
Как нужно:
v 2.0.0
v 1.1.0
v 1.0.0
Как сейчас:
v 2.0.0
... (тут 20 коммитов по переходу на новую версию)
v 1.1.0
fix
API почти допилил, покрыть тестами основной класс
доверстать стили
v 1.0.0
UPD:
- Если коротко, то читайте ответ @fshp
- Если подробней, то читайте комментарии в соседнем решении
Спасибо, то что нужно. Руководство для начинающих:
1) Заходим в ветку в которую нужно внести правки
2) git merge --squash имя_ветки_из_которой_тянем_изменения
3) Ликуем!
Не так сработало. У меня эти команды "поменяли местами" мастер ветку и вторую ветку. Может с картинкой будет понятней. Во второй ветке в коммитах куча хлама, они исключительно для меня и не несут пользы остальным участникам работы над проектом. Нужно чтобы после слияния история этих коммитов была стерта, а не вписана в общую ветку.
Роман Башарин: специально только что проверил. все работает как и задумано в мастер ветке появляется новый коммит, который содержит в себе все необходимые изменения из feature
Роман Башарин: если мне не изменяет память, то squash собирает ветку в один коммит и вам реально за это могут отбить руки на больших ветках. По поводу удаления ветки - надо пробовать, но зачем её удалять?
padlyuck:
Вы предложили сделать в точности то, от чего автор пытается избавиться.
И если ветка смержена, то удалив её, вы удалите лишь указатель (на вашем скрине зелёный лейбл feature). Коммиты никуда не денутся и останутся в истории.
padlyuck, fshp:
Это вроде как Git flow, как я думал? Логика такая:
Есть общая мастер-ветка в которой каждый коммит это новая версия/субверсия, в общем есть строгая нумерация. Когда я начинаю разработку я копирую мастер-ветку - можно сказать, что это feature-ветка с моей новой фичей, так? Я работаю с нескольких компов и бывает так, что что-то не успел доделать и нужно уже ехать домой, я быстренько коммичу с каким-нибудь комментарием который будет понятен только мне, приезжаю в другое место и там разработка продолжается уже с последнего коммита. Мне удобно, понятно, не нужно париться над продумываем коммита. А когда фича более менее как-то готова и её можно влить в общую ветку или же к моей ветке кто-то присоединяется, я этот "мусор собираю в один оформленный коммит со всеми понятными комментариями.
Один офигенный коммит должен быть атомарным.
Что это значит?
1) Он должен быть рабочим. В идеале вы должны иметь возможность переключится на совершенно любую версию проекта, и она будет работать.
2) Он должен содержать лишь одно законченное изменение. В одном коммите не должно быть 2 фичи.
Для этого используется не squash (что в идеале вообще не должно использоваться), а rebase.
Т.е. после того, как вы сделали фичу, эту ветку нужно заребейзить - удалить отладочные сообщения, разбить коммиты на логические части. И, возможно перенести базу на последнюю версию.
Для чего это нужно:
1) Посмотрите на исходники linux. Там каждые 2.5 месяца десятки тысяч коммитов вливается. Если в этих коммитах будет промежуточный код (отладочные сообщения, неудачные реализации), то это невозможно будет читать. Мы можете затронуть во время работы сотню строк кода, а в итоге реальных изменений останется десяток. Другие разработчики с ума сойдут, читая ход ваших мыслей. Поэтому большинство коммитов в linux имеют размер в пару строк. Разработчик оставляет минимально необходимый патч. Это легко читать другим разработчикам.
2) Коммиты должны быть рабочими. Когда вам приспичит воспользоваться такими инструментами как bisect, вы будете проклинать себя за то, что ваш коммит не собирается и вы не можете его проверить.
Это может показаться сложно и нудно. Относитесь к этому как к части своих обязанностей. Вам же приходится работать с багтрекером, например, это не относится напрямую к программированию. Так же и система контроля версий не относится к программированию.
Подводя итог: в личной ветке делаете что угодно. Когда работа закончена, делаете ребейз, причёсываете коммиты. А затем делаете мерж без всяких squash и ff.
Большинство открытых проектов вас пошлют куда подальше, если вы пришлёте им не причёсанный патч. Даже если там будет супер-мега фича.
fshp:
Так всё таки чтобы "причесать" мою ветку где много "мусора" можно использовать squash? Зачем людям читать такое "не работает валидатор!! дописать класс отправки! класс апдейта не дописан, смотри gitignore".
Понятное дело, если фичер-ветка общая, то я должен сделать от неё своё ответвление и чаще вливать в общую ветку коммиты которые четко описаны и не ломают приложение, но в своей то клонированной ветке можно что угодно писать, если это удобно? И потом чтобы это при слиянии не попало в общую ветку использовать squash?
Роман Башарин: если же в ветке была такая работа, что грамотный ребейз сделает из ветки один коммит, то от свквоша это не будет отличатся (за исключением наличия мерж-коммита, который тоже можно убрать через ff).
fshp: а зачем тогда нужно создавать отдельную ветку, если у нас всего 1 коммит? В текущей внесли правки, узнали были ли изменения, если были, устраняем коллизии и заливаем сразу с коммитом.
Если у вас в рамке одной задачи было реализовано несколько фич или исправлено несколько багов, то squash сделает мегасукакоммит. Чего не должно быть.
Ок, а если только одна небольшая фича, но было несколько "служебных коммитов для себя" то тут правильно использовать squash? Тут дело не в том, что я ленюсь описать изменения, а то что нужно сделать коммит, чтобы я смог с другой машины доработать и часто между такими прыжками фича ещё сырая.
Роман Башарин: вы можете хоть сотню коммитов сделать. А затем squash. Проблем нет.
rebase может вести себя как squash, но не наоборот. Rebase более гибкий инструмент только и всего. И ещё раз повторюсь - правил нет. Это лишь моё мнение. Кто-то вам посоветует делать всё наоборот и будет прав.