Комментарии 117
Локальное слияние коммитов бывает удобнее в том случае, когда в истории смешаны разные типы изменений: рефакторинги, хаки, собственно фичи, побочные изменения и т.п. В таком случае рулит интерактивный ребэйз, позволяющий аккуратно разложить всё по полочкам. Жаль, что этот момент в статье почти не раскрыт.
Интерактивный ребейз, когда из 100 нанокоммитов делается 2-3-4-5 логически-атомарных коммитов — хорошо.
А что, если те самый 2-3-4-5 коммитов были декомпозированы на разные задачи изначально? Тогда их делают разные разработчики и они отдельно тестируются. В итоге мы приходим к ситуации, когда у нас не 1 feature-бранч из 4 коммитов, а 4 feature-бранча из 1 коммита и тогда становится уместным сделать им автоматический squash до того самого единственного коммита.
Но вообще, это уже начинает упираться в вопрос о размерах конкретных задач в конкретной команде на конкретном проекте. И в этот момент лучше использовать гибкость git'а и адаптировать его под командный процесс, чем самим прогибаться. Как я говорил в статье, я убежден что каким-то камандам/разработчикам может никогда и не понадобиться уходить от классического GitFlow.
в gitlab есть protected branches: т.е. в ветку вообщне нельзя коммитить напрямую — только merge-request'ами
в bitbucket server есть то же самое, но как минимум двумя способами — хуками или правами на юзеров\групп.
защищаешь master + develop + release/* и всё, враг не пройдёт.
ой, не туда ответил. писал для VladimirAndreev
В статье говорится о ситуации «Перед вливанием feature-бранча в итоговый». В этот момент все работы по feature-бранчу завершены и он мержится в итоговый. Для того, чтобы история была линейной, мы в любом случае вынуждены сделать force-пуш.
Но вы всё верно говорите, так как затрагиваете момент активной работы над бранчем. В этот момент force-пуш лучше не использовать или делать это с уведомлением всех заинтересованных лиц. В своей команде, путем декомпозиции задач до логически атомарных, мы максимально стараемся избегать ситуаций, при которых несколько человек работают над отдельным бранчем. Тогда градус проблем от force пуша понижается практически до нуля, так как в большинстве случаев разработчик никому не навредит, кроме себя.
смушает git push --force. рано или поздно этим можно разрушить репозиторий
git reflog
если форсить ветку с уже созданным пулл-реквестом, это сразу становится видно в overview (github, stash, etc.), что сразу настораживает заинтересованных лиц
Зато я вижу огромнейшую кучу минусов, что человек делал делал работу, коммитил, соответственно запомнил он всю свою работу именно с теми коммитами, которые он сам делал. А потом нужно порыться в истории, и уже сам разработчик не может вспомнить зачем что и почему, т.к. история коммитов уже другая.
В истории рыться очень непросто, если она выглядит так, как на первом скриншоте — просто потому что история в экран монитора помещаться перестает. Вдвойне непросто рыться в истории, если рыться приходится другому разработчику а в самой истории куча коммитов вида «fix blah-blah-blah»
Зачем смотреть на графическое представление? Тут ответ на самом деле прост. Прийти в эту точку можно в два шага.
1. Я смотрю на строчку кода и пытаюсь выяснить в рамках какой задачи и зачем автор её добавил. Для этого я смотрю к какому коммиту привязана эта строчка. Если в сообщении к коммиту я виже «issue-1 исправлена ролевая модель», то все хорошо. Я получил ответ и не потратил много времени. Если же я вижу «fix bug, refactoring» или что-то в этом духе (что часто возникает при частых коммитах в длинных бранчах), то перехожу на шаг 2.
2. Иду анализировать историю коммитов (те самые картинки на скринах), чтобы понять в рамках каких работ был сделан этот коммит. И если история очень грязная, то это занимает немало времени. Хотя все могло бы закончиться на шаге 1, будь она чистой.
Почему вы не используете mercurial?
"Так исторически сложилось. " ©
Когда-то давно, когда не было никаких github и все радовались gitosis, прошла успешная миграция с SVN на Git. А сейчас причин для очередной миграции просто нет, так как возможности git'а полностью покрывают все потребности командной работы.
Судя по тому, что вы описали в предыдущем комментарии — покрывают не все потребности. В меркуриале нет этой проблемы и её не приходится решать переписыванием истории.
https://yadi.sk/i/VjRj8FmVreQL4
мастер и 2 фичеветки, каждая из них подливает изменения из мастера. из на 3 полезных коммита у меня получилось 4 мерджа. И я всёещё не понимаю как меркуриал уберег меня от каши в истории.
1. Отпочковали фича-ветку от главной
2. разработали фичу (n коммитов).
3. во время разработки время от времени забирали себе основную ветку (к — служебных слияний).
4. один раз влили в основную ветку. — 1 слияние.
И да, я отношусь с тем, кто не понимает, зачем нужна чистая история. Всмысле, что в ней такого чистого после ребейза.
И да, в hg мы не используем jit-flow. Одна ветка = одна версия. Ветка со временем выходит в пререлиз и в релиз. В момент смены состояний даже коммита делать не нужно, т.к. статус релизности ветки имхо можно и нужно отслеживать на сервере интеграции а не в репозитории.
На мой взгляд все иначе. И статья и мой комментарий рассказывают именно о том, как покрыть возникшие потребности используя возможности git'а.
Весь смысл "чистой истории" в том, чтобы понимать, какую цель несёт каждое конкретное изменение кода. Если цель непонятна или размыта, то сложнее отличить действительно полезный код от какого-то мусора или откровенно вредного кода. Проблема в том, что история коммитов, которая получается в процессе работы, далеко не всегда бывает логична и удобна для чтения.
Представим, что процесс работы происходил так:
- Начал пилить фичу, реализовал половину
- Влепил локальный хак, чтобы упростить дальнейшую работу
- Сделал ещё кусочек фичи
- Понял, что для последего этапа фичи надо сделать рефакторинг, отвёл на него ещё один коммит
- Доделал фичу
- Выпил локальный хак
Что, сильно поможет такая история? Человеку, читающему историю изменений, придётся сначала спрашивать себя "WTF, что это он тут сделал? ЗАЧЕМ????", а потом видеть rollback и фиксировать в голове лишние данные — "так это был хак, оказывается! надо его игнорировать". Аналогично и с фичей, разбитой на три разных куска. Надо понять, что они друг с другом связаны, разобраться в этой связи, отделить значащие коммиты от незначащих и т.д. Это всё лишние операции, которые ухудшают понимание кода.
Куда приятнее иметь дело с такой цепочкой:
- Предварительный рефакторинг (Коммит 4 из предыдущей истории)
- Собственно, новая фича (Слитые коммиты 1, 3, 5)
Коммиты аккуратно слиты так, чтобы в каждом из них было только одно логичное и цельное изменение, то понимать их гораздо проще. Так, тут рефакторинг, он модифицирует интерфейс, но не меняет поведения — и это действительно прослеживается в коде. Так, тут фича, она использует новый интерфейс понятным образом, лишнего кода не содержит, недостающего кода тоже не содержит. Коммиты с хаками вообще не попадают в историю, потому что они будут только мешаться, затрудняя понимание. Теперь при чтении в голове приходится держать куда меньше нерелевантной информации, что весьма существенно, потому что число факторов внимания, удерживаемых в голове, у людей весьма ограничено.
Если мне нужно понять, что вообще делает этот код — я смотрю в название ветки, в которой указано, что в ней пилилось. Если же мне нужно более узко понять, что делают вот эти две строчки — я смотрю каждый коммит разработчика, в котором эти две строчки затрагивались и читаю сообщение к каждому коммиту.
А ежели я буду видеть один огромный сквашенный коммит с кучей зелёненьких строчек, то я из него точно не пойму, что делают конкретно эти две строчки в середине огромного добавленного блока.
Я при объединении коммитов исхожу из принципа "логической завершённости", как это описано во множестве рекомендаций по стилю (к примеру, здесь). Во время текущей работы у меня чаще всего создаётся много (по нескольку десятков) очень мелких коммитов, каждый из которых не обязательно является логически завершённым. Объединением коммитов я стараюсь добиться именно этой завершённости. Вовсе не обязательно кидаться в крайность и сливать всё в один мега-коммит. Часто бывает, что это только противоречит принципу "одно законченное изменение". В идеале, после слияния в ветке из 20-30-40 коммитов остаётся несколько (1-2-5) цельных законченных изменений.
Git flow, будем честны, используют не все и не везде, поэтому вариант "я смотрю в название ветки, в которой указано, что в ней пилилось" не всегда возможно применять. Ориентация на "цельные коммиты" является более универсальной, потому что она пригождается в любом workflow.
Вас никто не заставляет заходить в фичеветки — смотрите мерж-коммиты — там как раз у вас будет "добавлена фича такая-то" и все изменения одной пачкой, безо всяких хаков. Ваше разделение на "предварительный рефакторинг" (зачем он?) и "собственно фичу" (одним огромным патчем) — не имеет смысла.
Вас никто не заставляет заходить в фичеветки — смотрите мерж-коммиты
Это тестовый пример обратной реинтеграции изменений без rebase. 3 разработчика работали в 3 ветках и периодически подтягивали изменения друг-друга при помощи merge. Внимательный читатель несомнено обратит внимание на то, что в данном commit hell'е непосредственно в ветку merge-rebase-3 сделан один (ОДИН!) коммит.
Вы лучше выложите сам репозиторий, а не скриншоты любимой IDE :-)
Я ж говорю — тестовый случай. Накидал за 5 минут по аналогии со случаями из профессиональной практики..
Я очень против «чистоты истории коммитов», удаления мердженных фича-веток, ребейза, переписывания истории (вообще фу). Причина этому одна — я не вижу никаких плюсов для этого на практике.
Напоминает религиозные страхи. А на самом деле.
- Одно из главных правил git — commit frequently (комитьтесь чаще). Пачка из 100+ коммитов в develop ветке — отличный подарок всем, кто в отличие от вас хотят читать историю.
- Набор коммитов в фича-ветке — это мысли разработчика при работе над фичей. На кой черт мне нужно читать потом в главной ветке весь этот поток сознания?
- Неудаление смердженных веток — это вообще аут. У нас сейчас в JIRA id тасков перевалило за 4700. По-вашему у меня в репозитории должно быть 4700 старых веток?
- Представьте ситуацию: я ваш заказчик, вы имеете в develop ветке фичи: 1 (13 коммитов), 2 (27 коммитов), 3 (5 коммитов), 4 (19 коммитов), 5 (2 коммита). Я прошу: задеплой мне прямо сейчас на прод фичи 3 и 5. Остальные — не нужно, я хочу протестировать их отдельно. Ваши действия?
переписывания истории (вообще фу)
Одно из главных правил git — commit frequently (комитьтесь чаще). Пачка из 100+ коммитов в develop ветке — отличный подарок всем, кто в отличие от вас хотят читать историю.
Слепое следования правилам до добра не доводит. Всё же коммит должен быть более менее осмысленным набором изменений, который как минимум компилируется и сопровождается осмысленным сообщением.
Набор коммитов в фича-ветке — это мысли разработчика при работе над фичей. На кой черт мне нужно читать потом в главной ветке весь этот поток сознания?
А для чего вам нужна история кроме как для понимания что и почему изменял разработчик?
Неудаление смердженных веток — это вообще аут. У нас сейчас в JIRA id тасков перевалило за 4700. По-вашему у меня в репозитории должно быть 4700 старых веток?
Это родовая травма гита. Переезжайте на меркуриал — там с этим проблем нет, так как ветки можно закрывать.
Представьте ситуацию: я ваш заказчик, вы имеете в develop ветке фичи: 1 (13 коммитов), 2 (27 коммитов), 3 (5 коммитов), 4 (19 коммитов), 5 (2 коммита). Я прошу: задеплой мне прямо сейчас на прод фичи 3 и 5. Остальные — не нужно, я хочу протестировать их отдельно. Ваши действия?
Почитайте про github flow.
Всё же коммит должен быть более менее осмысленным набором изменений, который как минимум компилируется и сопровождается осмысленным сообщением.
Ага, именно для этого делается squash и фича заходит в develop одним коммитом с осмысленным и красивым сообщением. Но это не значит, что разработчик не может в feature-branch накоммитить 100 коммитов до этого.
А для чего вам нужна история кроме как для понимания что и почему изменял разработчик?
История мне нужна для того, чтобы понимать, что и как поменялось с принятием фичи в develop. Какие файлы поменялись, сколько всего файлов поменял разработчик на протяжении работы с данной фичей. А видеть 100 коммитов с сообщениями вроде: fixed / update / fix / 1… мне совершенно неинтересно.
Это родовая травма гита. Переезжайте на меркуриал
Пфффф, отличный совет. Также рассмотрю от вас совет переписать проект с PHP на Java, потому что у PHP тоже сплошные родовые травмы, развестись с женой, потому что нынешняя не хочет готовить мне блинчики с икрой, и, как апофигей, предложение переехать в другую страну, потому что в нынешней коррупция высокая.
Почитайте про github flow
Пафосно, но мимо. github flow никак не решает поставленную задачу. Они лишь гарантируют, что master всегда готов к деплою. Молодцы, чо. Но задачка состояла в другом.
Ага, именно для этого делается squash и фича заходит в develop одним коммитом с осмысленным и красивым сообщением. Но это не значит, что разработчик не может в feature-branch накоммитить 100 коммитов до этого.
Ну а без squash фича заходит в develop… одним единственным merge-коммитом с осмысленным и красивым сообщением.
А видеть 100 коммитов с сообщениями вроде: fixed / update / fix / 1… мне совершенно неинтересно.
Ну так и давайте по рукам за такие сообщения. На самом деле вам нужны ветки, настоящие ветки, а не просто указатели на коммиты.
Пфффф, отличный совет.
Вы попробуйте, это очень просто.
Пафосно, но мимо. github flow никак не решает поставленную задачу. Они лишь гарантируют, что master всегда готов к деплою. Молодцы, чо. Но задачка состояла в другом.
Ваша проблема из-за ветки develop в которую навалена куча всякого недоделанного мусора и от которого начинают зависеть все остальные ветки. В hithub flow до деплоя ветки живут отдельно друг от друга. Перед деплоем создаётся интеграционная ветка, куда сливаются фичи 3 и 5, тестируются, деплоятся, снова тестируются и только потом попадают в master, откуда во все остальные ветки. До вливания в мастер в любой момент можно выпилить интеграционную ветку и собрать новую из другого набора фич.
Создалось впечатление, что на одном проекте работаем. У нас правда тикетов за 15К перевалило, но заказчик у нас явно один и тот же :)
1. не смотрю коммиты в девелопе, смотрю принятые пулл реквесты в него
2. смотреть п. 1
3. тоже не вижу проблемы в 5000 ветках, где они мне помешают то? Опять же, нигде ещё не приходилось смотреть весь список веток в репозитории
4. создаю новую ветку от develop, мержу в неё две нужные фичи, выкладываю. UPD: перечитал вопрос, не понял его. Что значит имеем в dev ветке 5 фичей с n коммитами?
не смотрю коммиты в девелопе, смотрю принятые пулл реквесты в него
Вы не смотрите, а кто-то возможно смотрит. Например, я хочу посмотреть, какие таски я задеплоил между двумя тегами. Я просто делаю:
git log 2.11..2.12
И получаю красивый список тасков. А вы получите 100+ коммитов с непонятными описаниями.
Это лишь один из примеров.
тоже не вижу проблемы в 5000 ветках
репа начинает дичайше тормозить
создаю новую ветку от develop, мержу в неё две нужные фичи, выкладываю. UPD: перечитал вопрос, не понял его. Что значит имеем в dev ветке 5 фичей с n коммитами
Вы запилили 5 фич, QA проверили, все ок, зарелизились, а через недельку ваш заказчик говорит: чувак, у меня конверсии упали. Давай, пили мне A/B тест: выложи мне на один сервер 1, 3, 5 фичу, а на второй сервер — 2, 4. Отдельные релизные ветки, да, сработают, но после нахождения причины в них появятся новые коммиты с фиксами, которые нужно мерджить и мы снова получаем бардак и нечитабельную историю.
git checkout develop
git merge --squash feature/...
git commit -am '#issue comment'
git push origin develop
git branch -D feature/...
git push origin :feature/...
В итоге история у нас выглядит примерно так:
* <1234567> 2016-05-06 [dev1] (HEAD, origin/develop, develop) version bump
| * <1234567> 2016-05-06 [dev1] (tag: 1.52, master, origin/master) Merge branch 'develop'
| |\
| |/
|/|
* | <1234567> 2016-05-06 [dev1] #99 feature 99
* | <1234567> 2016-05-05 [dev2] #98 feature 98
* | <1234567> 2016-05-04 [dev1] version bump
| * <1234567> 2016-05-04 [dev1] (tag: 1.51) Merge branch 'develop'
| |\
| |/
|/|
* | <1234567> 2016-05-04 [dev1] #97 feature 96
* | <1234567> 2016-05-03 [dev2] #96 feature 97
* | <1234567> 2016-05-02 [dev1] version bump
| * <1234567> 2016-05-02 [dev1] (tag: 1.50) Merge branch 'develop'
| |\
| |/
|/|
* | <1234567> 2016-05-02 [dev1] #97 feature 96
* | <1234567> 2016-05-01 [dev2] #96 feature 97
Тут даже невооруженным взглядом видно, что происходило в проекте: кто, что и когда сделал, что и когда пошло в релиз.
Зачем нужны промежужточный коммиты в фиче бранче, вообще не понятно. За все три года работы по такой модели я ни от одного из коллег не слышал, что ему нужно было знать, что было в промежуточных коммитах.
Действительно может показаться что информации маловато. Но в случае с GitHub/GitLab/BitBucket, часть сообщения «#96» — это ссылка на баг-трекер, что позволяет в один клик добраться до нужной информации. На мой взгляд это очень удобно.
Я с этим и не спорю. Устраивать холивар на тему "Все ли коммиты должны привязываться к задачам и все ли задачи должны быть заведены в багтрекере" я точно не планировал. Я лишь говорил о том, что даже минимум информации в сообщении к коммиту может дать быстрый доступ к дополнительной информации. При наличии дополнительных инструментов в распоряжении команды, конечно же.
PS: Децентрализации git'а для меня конечно же не новость. Вот только мне ещё ни разу не приходилось встречаться с командами, которые используют git в формате p2p, без выделенного remote-репозитория, к которому подвязаны различные инструменты из области CI. Хотя скорее всего такие команды существуют.
Не могу не согласиться. Лично я ещё очень надеюсь, что Upsource составит сильную конкуренцию. Он безумно удобен для проведения Code Review, но вот с поддержкой различных flow по работе с самим репозиторием было не очень (во всяком случае обещалось это ещё в 1.0, но когда я последний раз смотрел на него, этого функционала там ещё не было).
PS: Хотя вот на сайте сейчас для версии 3.0 говорится об интеграции с pull request'ами на github. В каком виде это реализовано не знаю, может кто-то в комментариях подскажет или сам @JetBrains расскажет на какой-нибудь конференции :)
— сделать rebase+squash
— обновления делать исключительно amend
— в качестве назначения использовать фиктивный ref, о котором надо помнить
— когда приходит добрый сосед и мержится, надо ручками опять делать ребэйз
Короче, мне это сильно напоминает старые добрые времена SVN по количеству рукопашной работы.
Мне такая модель тоже нравится. Многие опен-сорсный код на гитхабе (по крайней мере в мире Ruby) использует эту модель очень и очень успешно
Разработчики A и B создали ветки featureA и featureB от ветки develop.
Сделали изменения, сделали коммит, сделали rebase на текущее состояние develop, сделали push.
Последний коммит в ветке develop — X.
В первой ветке история коммитов «X — A», во второй «X — B».
Главный разработчик мерджит в develop сначала ветку featureA. Там возможен fast forward.
Потом мерджит ветку featureB. Тут уже fast forward не получится, потому что порядок коммитов другой.
Получается, тому кто мерждит, надо сначала вручную сделать rebase ветки featureB на новое состояние develop?
Сказали скоро будет )
Вам не кажется странным, что вопрос отображения вы решаете не средствами отображения, а средствами редактирования? У TortoiseGit есть режим "Compressed Graph" делающий именно то, что вам нужно.
Вынужден не согласиться. Проблемы чистоты истории влияют не только на отображение.
Да, как я упомянул в статье, у нас есть ключи для терминального git log
и различные способы фильтрации для GUI клиентов. Тут вы конечно правы и это несколько поможет в проблеме анализа истории и улучшит её визуализацию. Но на этом проблемы не заканчиваются.
Помимо анализа истории возникает необходимость работы с нею. Классический для нас кейс, когда заказчик очень быстро меняет требование к скоупу релиза и просит добавить/убрать из поставки любой набор функционала, который ему захочется. В этой ситуации работать с merge-коммитами далеко не так удобно, как если бы их не было.
А как быть с багфиксами в feature-бренче?
У меня на проекте — так:
- Отдельный багфикс в отдельном hotfix-бранче
- После проверки squash hotfix-бранча
- merge hotfix-бранча в develop
- squash hotfix в develop (нечего ему неприкаянным висеть)
- git push -f
- Все разработчики делают git fetch && git rebase -i origin/develop
PS: Не подходит для open-source проектов, где мы не можем заставить всех сделать последний пункт. Впрочем, squash feature/hotfix бранчей нередко требуют и в open-source проектах. И это — правильно
Так ведь squash как раз и дает читабельность истории.
Проблема с squash в том, что так в один коммит попадает множество не связанных между собой изменений, которые должны в истории храниться отдельно
Если вы работаете в ветке только с одной фичей, а не с десятком, то все изменения будут связаны между собой как раз этой самой фичей.
1) Требование создавать по отдельному pull request на каждый баг фикс сильно отяжеляет разработку бюрократией (коммиты напрямую в основные ветки строго запрещены)
2) Типичное для ревью требование отделять коммиты с форматированием от коммитов с семантикой очень полезно и впоследствии при git bisect. Это касается и реализации больших фич — грустно было бы обнаружить, что проблема возникла из-за одного цельного коммита на +5000 -5000.
У сохранении истории коммитов есть, впрочем, свои недостатки. Главные — нужно настраивать CI для тестирования всех коммитов, а не только HEAD; не удобного способа проследить связь между коммитом и pull request. В планах попытаться решить последнюю проблему через https://git-scm.com/docs/git-notes
У нас бывали случаи, когда в одной ветке делалось несколько фиксов. В этом случае после code review разработчик просто делал squash не всех в один, а группировал по фичам. В конечном итоге merge одного pull request давал столько коммитов в develop ветке, сколько багфиксов делалось в этой ветке.
Разработчик может забыть, забить, пропустить и в дереве коммитов окажется вот это. И дальше что? А если у нас 100 коммитов по фиче? Никакой разработчик не будет выдумывать уникальные и красивые сообщения для каждого коммита.
squash — нужен действительно только тогда, когда первоначальная реализация фичи была не совсем верная. Нет никаких доводов против мерджа как есть фичи сделанной за несколько коммитов, каждый из которых осмысленный и не ломал тесты(ну вы же делаете push каждый раз после коммита, да?)
rebase поверх — для того чтоб CI отработал на той версии кода которая получится после merge в основную ветку.
Все. squash'им только ненужные коммиты, а ребейсим и прогоняем CI чтоб держать общую ветку в рабочем состоянии. А чистая история это побочный продукт, а не самоцель.
Вы правы, чистая история конечно же не может быть самоцелью и для нас она таковой не являются. На мой взгляд ситуация такова.
Есть потребности (они же цели):
- Тестировать актуальную версию исходного кода
- За минимальное время находить информацию, являющуюся причиной изменения исходного кода
- Иметь возможность быстро реагировать на частые изменения скоупа
Есть средство, гарантирующее удовлетворение обозначенным потребностям — это чистая история. На собственной практике мы убедились, что она действительно это гарантирует.
И есть инструменты (rebase, squash и т.д.), позволяющие организовать чистую историю.
Не гарантирует. Допустим вы влили фичи 1, 2 в одну ветку develop, при этом в 1 внесли кучу изменений, от которых зависит 2, который вы ребейснули поверх 1 или даже срезу с 1 и стартанули. Теперь вам нужно выкатить в продакшен фичу 2 без фичи 1. Ваши действия? А если в develop 10 фич, которые также друг от друга зависят? Вам придётся очень постараться, чтобы выудить из всех фич лишь те изменения, которые необходимы тем фичам, что вы собираетесь деплоить.
Ну и ещё пара весёлых историй из жизни "чистой истории":
https://habrahabr.ru/post/179123/
https://habrahabr.ru/post/179673/
Мои действия очевидны — ручная кропотливая работа. Когда речь заходит об изменениях скоупа, которые затрагивают зависимые друг от друга изменения, то тут никакой flow не спасет от ручной работы. Поэтому речь всё-таки шла больше о логически атомарных изменениях.
В любом случае для принятия какого-то flow на вооружение команды, его нужно пропускать через призму многих факторов, в том числе и внешних. Когда я писал, что "серебряной пули нет", я не лукавил. Так же как и GitFlow, я не считаю Rebase Flow идеальным. У получаемых возможностей всегда есть цена и риски, о которых нужно знать. Приведенные вами примеры тому подтверждение.
За ссылки спасибо. Хотя я больше сторонник превентивных мер воздействия :) Когда же дело дошло до bisect, то тут хорошего мало, как на это не посмотри.
По поводу потребностей:
1) Какое событие инициирует тесты? (вы ведь про ci?)
2) Используйте номер таска в названии коммита.
3) Не до конца понял эту потребность. Какую информацию предоставляет «частое изменение скоупа, полученное из истории гита»?
Я просто не встречал ситуацию на практике, когда мне нужно было использовать графическое представление истории.
Не особо понимаю практический смысл такой чистой истории. Если вам не сложно, не могли бы вы пояснить его?
Не совсем понимаю, что конкретно требует пояснения. Старался сделать в это в самой статье, включая ссылки на сторонние статьи. Да и в комментариях уже много информации. Если конкретизируете вопрос по непонятному моменту, постараюсь прокомментировать.
1) Какое событие инициирует тесты? (вы ведь про ci?)
Ну это очень зависит от команды и проекта. У кого-то тесты работают несколько часов и их запускают по крону. У кого-то все тесты проходят за несколько секунд и можно прогонять их после каждого коммита.
2) Используйте номер таска в названии коммита.
Хорошая практика. В своей команде мы её используем.
3) Какую информацию предоставляет «частое изменение скоупа, полученное из истории гита»?
Никакую. Частое изменение скоупа влечет за собой активную работу с бранчами, откуда возникает потребность выполнять эту работу с минимальными сложностями за минимальное время.
Я просто не встречал ситуацию на практике, когда мне нужно было использовать графическое представление истории.
Вы действительно никогда не пользовались командой git log
? На мой взгляд это достаточно странно, хотя быть может каким-то командам в их процессах оно действительно не требуется. Главное ведь, чтобы командная работа была эффективной и без боли :)
1) У нас тесты запускаются по факту пуша в ветку и собирают самую актуальную версию ветки (на момент начала сборки). Просто не вижу, как это может быть связано с грязной историей.
3) Не встречал проблем с активной работой с бранчами. Как раз наоборот. Чем их больше, тем проще работать командой. А насчет изменения скоупа. Его разве не проще просматривать в трекере задач?
Насчет команды git log. Пользовался из консоли обычно для того, чтобы откатить свои последние коммиты (git reset). Для того, чтобы найти последние изменения мне хватает ide. Аннотаций или истории файла вполне хватает. Если по истории, то это обычно 1-5 коммитов (включая мерж коммиты). На дерево не смотрел ни разу, если не считать случаев из любопытства. Для того, чтобы понять, как работает функционал, я обычно смотрю в тесты, а не в историю. Единственное, что я могу сейчас предположить, это то, что возможно у вас слишком перенасыщенные классы. Я такие классы советую дробить на более мелкие. Если класс выполняет строго отведенную ему задачу, то его код редко меняется. А разгрузив таким образом основной класс, вы разгрузите и историю изменений этого класса. Возможно проблема кроется в другом.
Просто не вижу, как это может быть связано с грязной историей.
В контексте этой ветки коментариев речь идет о том, что когда вы тестируете бранч, не являющийся линейным продолжением текущего состояния проекта, то вы потенциально тестируете бранч с конфликтами. Если тестирование например ручное или автоматизированное, но долгое, то очень дорого обойдется вам это тестирование, так как после разрешения конфликтов нужен будет полный ретест. Поэтому многие стремятся как можно быстрее избавляться от конфликтов, используя мерж или, как в описанном в этой статье флоу, ребейз.
3) Его разве не проще просматривать в трекере задач?
Куда-то совсем не туда. Прочитайте пункт 4 из этого комментария ещё раз. В данном случае речь идет именно об этом изменении скоупа. Утром заказчику нужна поставка с фичами А и Б, а к обеду он уже хочет А, Д и выкинуть поставленную вчера В.
На дерево не смотрел ни разу, если не считать случаев из любопытства.
GUI представление, ни что иное, как визуализация операции git log. Пользовались им, значит смотрели дерево. В какой программе вы на него смотрели, SourceTree или консоль, это не так важно.
возможно у вас слишком перенасыщенные классы
Описываемый в статье флоу потребовался команде из нескольких десятков человек. Из сухой статистики: проекту 4 года, чисто тикетов перевалило за 15К, а число строчек кода уже давно за миллион. В этих условиях могу с уверенностью утверждать, что каких только классов у нас нет, в том числе полно перенасыщенных :))
По скоупам понял. Могу вам только посочувствовать =( Тут уже никакой workflow не подходит. Вероятно в данном случае ваш подход наиболее продуктивный. Спасибо за пример. Однако, если говорить о хоть каком-то workflow, то в этом я не вижу особой необходимости.
Ну назвать пару коммитов одного файла деревом трудно, но думаю можно и так сказать. Тогда могу сказать, что грязная история лично мне не мешала. Но на вкус и цвет =) А проект по сухому описанию похож на ваш.
Напоследок могу пожелать вам поменьше конфликтов. Спасибо, было приятно и полезно пообщаться.
Я всегда могу в 100 коммитах сделать задачу, влить в мастер / девелоп с осмысленным комментарием. И история не будет захламлена этой сотней коммитов, потому как они в отдельной ветке и не мешаются при просмотре истории основной ветки.
А если кто-то захочет разобраться с тем, как я делал задачу — ему доступна история моих коммитов с комментариями по каждому шагу.
И я против изменения истории коммитов.
Я могу понять, зачем это Open Source проектам. Или в очень больших проектах со сложным workflow…
Ну а в прочих случаях, максимум, который я готов допустить — локальное изменение истории неопубликованных коммитов, например для исправления опечаток или чтобы не проводить слияние одноименных веток.
P.S. Интересно то, что в «А что хотелось бы?» показана практически история коммитов из mercurial, где каждый коммит подписан «к какой ветке он относится».
Все так. И если на историю просто смотреть, то фильтров отображения будет более чем достаточно. Но бывает так, что команде приходится часто манипулировать коммитами из истории. И тогда сложно отрицать, что revert/cherry-pick отдельного коммита заметно проще и занимает меньше времени, по сравнению с аналогичными операциями для merge-коммитов.
Еще есть вариант просто систематизировать поставку коммитов, чтобы команда делала все коммиты красиво, если хочется красивой истории без изменения истории. Как положительный момент — аккуратные коммиты и разработчики.
скажем, подсчитать количество звезд на небе, которые видны в данный момент.
и потом в 50 местах подшаманить формулы с учетом этого самого количества.
как вы не знаю, лично у меня в этой фичаветке будет 51 коммит. минимум.
Мне кажется VladimirAndreev имел ввиду, что в одном коммите будет реализована функция подсчета видимых звезд, а потом будут 50 отдельных коммитов, в которых будут правиться соответственно 50 мест, в которых эта функция требуется.
И в чём прелесть однострочных коммитов?
Мне кажется в комментарии VladimirAndreev речь не шла про однострочные коммиты. Это был абсолютно искуственный пример, демонстрирующий правило "commit frequently". Если разработчику удобнее и привычнее делать десяток коммитов в день, то почему нет.
Не то, чтобы я против мелких коммитов, но я за осмысленные коммиты, причем, подчеркиваю, именно в процессе разработки. Вы же не коммитите «feature #N, line 1», «feature #N, line 2», ..., «feature #N, line 50», вы коммитите "«feature #N». Если вполне реально влить законченное изменение одним коммитом, так почему бы так не сделать, а не делать 50 коммитов, а потом их объединять?
Вы правда считаете, что стоит навязывать разработчику формат работы с локальным репозиторием? Лично мне всё равно, что делает разработчик моей команды со своим локальным репозиторием, если результат при этом удовлетворяет всем командным договоренностям.
Ну например в IDEA и он не нужен, там автосохранение :) Но если взять тот же ctrl+s, то люди тоже не сразу к нему пришли. Пару раз весь набранный текст исчезнул в след за крешем редактора или оси и начали чаще сохранять.
Думаю аналогичная история есть и у сторонников очень частых коммитов. Пару раз стоит потерять отличную наработку (изначально таковой не казавшуюся) не сделав промежуточный коммит и личный рабочий процесс немного меняется. Мне правда сложно судить, так как я не считаю себя столь уж частым коммитером. Но учитывая продвинутость современных инструментов разработки могу точно утверждать, что накладные расходы на частые коммиты минимальны — хоткей в IDE и коммит готов.
Также удобно смотреть diff между отдельными шагами. Например, делаем класс для работы с внешним API, и на время разработки отключили реальные запросы, добавив в начало функции
return
. Если просто сохранять, то среди сотни новых строк его можно не заметить, а если перед добавлением сделать промежуточный коммит, то будет видно, что файл изменился.
Rebase Flow. Способ приготовления и его поддержка в GitHub, GitLab, BitBucket