Pull to refresh
35
0
Valentin Nechayev @netch80

Программист (backend/сети)

Send message

Кусок работы определяется задачей и логической связностью, иначе можно каждую строчку делать отдельным коммитом.

Тут всё правильно.

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

А вот тут - как раз лучше бисектом найти точку, где что-то сломалось, в любом случае, что у вас есть - отладчик, логи или что...

И что такое "обычные проекты"? Для меня вот "обычные проекты" это сетевые демоны всех видов, на протоколах, где тайминги критичны хотя бы в пределах единиц секунд. Отладчик там точно не подходит, а логи анализировать - только когда довёл до конкретных пары коммитов, где сломался тест.

И что это дает в плане полезности?

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

Поэтому каждый коммит должен компилироваться и проходить тесты. А дальше деление на добавление функционала, удаление функционала, рефакторинг, стилевые правки всех видов, причём лучше всего в обратном порядке от того, как я перечислил.

​1. Не вижу в предыдущей дискуссии признаков, что libfoo своя (ваш же пример с libabc и libdef этого не показывает).

​2. Я видел реальные случаи когда внутренняя же библиотека бывает в несовместимых одновременно используемых версиях, никакая монорепа не исправит это.

Типичная ситуация рабочего процесса, создающая такое, выглядит как:

-- Нам нужно сделать чтобы оно умело запускать ракету на Марс! Для этого нам надо переделать всё API!

-- Не вопрос, ваша библиотека используется в 125 проектах по полётам на Луне, доработайте их все.

-- Мы не можем, у нас нет ресурсов разбираться в этой столетней легаси! Пусть их хозяева правят!

-- Они не могут это сделать сейчас, очередь задач на пять лет.

-- Но нам нужно это исправить!

-- Отлично, делайте версию 4 и кладите рядом, пусть полёты на Марс будут на версии 4.

(фейспалмы слева, фейспалмы справа...)

Так вот - коллега, каким чудесным образом, по-вашему, монорепа исправит этот сценарий? Она сама по себе запретит форки и несовместимость форкнутых версий? Она создаст лишнее время у тех, кому надо "поменять всё API"? Она даст последним чудесное понимание происходящего в чужих проектах со всей их многолетней спецификой?

Почему я не могу в это поверить? ;)

ведь libfoo всегда и у всех одной версии.

Из чего это следует? ;))

Технологического ограничения против этого нет ни в одной VCS, и не должно быть.

Так если им надо присутствовать в одном бинаре, то пофиг в такой ситуации, собирается он из монорепы или из разных реп.

Я говорил про техдолг в принципе. В случае непредсказуемых внешних зависимостей - вы безусловно правы, приходится останавливать всё. Только в январе у нас такое было трижды - есть один проект, который вёлся с ежесуточным автомержем изменений от аплинка...

Переход на версию +1 библиотеки 1 тянет за собой переход на версию +5 библиотеки 2, так как обе версии выложены одним коммитом.

Предполагаю, будет в этом случае сделаны рядом libmoo3 и libmoo4, и разные проекты будут тянуть за собой разные версии, указанные явно :)

Форк такого рода в Git достаточно дешёвый. Главное, чтобы старая версия не сохранялась ещё надцать лет после того, как удалён последний использовавший её проект.

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

Поэтому должна быть не "максимальный приоритет", а "гарантированная полоса ресурсов". Даже 10% лучше, чем ничего. Иногда, конечно, нужно больше.

Если требуется коммерческое обоснование - тут уже зависит от рельефа местности, но аналогии с затратами на уборщиц и на страховые выплаты должны показать направление.

Если вы под "принадлежит ветке" понимаете "сохранил id ветки в момент коммита", то да, разница есть. В Git не используется никакого такого автомата, а если надо указать, в рамках какой разработки сделан коммит, то это пишется явно в его сообщении.

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

MqExtension

Я видел и пробно использовал его. Даже близко не похоже и очень неудобно.

Ну и shelve еще есть, который больше подходит для стиля работы в HG -
прячем все, что не идет в коммит, прячем все, что не идет в пуш.

Эта штука ещё тупее, практически равна stash.

В Git же наоборот - надо указывать в стейжинг все, что идет в коммит, и ветки которые идут в пуш.

Групповой push тоже есть, но не рекомендуется.

Процесс именно что усложнился. Сейчас мне проще с той же целью (чтобы
что проверил – то и закоммитил) закоммитить во временную ветку,
вернуться на рабочую и по частям переносить из временной, собирая
отдельные коммиты.

Это удобный вариант, но совсем не обязательный. Я в большинстве случаев обхожусь без временной ветки.

я в те времена ставил TortoiseHg, там работа с shelve (продвинутый аналог git stash) очень удобная.

А TortoiseGit не даёт того же?

Никаких ребейсов и форс-пушев вообще не нужно.

Если ограничивать себя тем же уровнем функциональности и набором возможных flow, то и в гите их точно так же не нужно. Но Git позволяет сильно больше и гибче с минимумом усилий.

Самое приятное, что можно слиться с любой веткой из любой другой.

Я однажды сделал merge с совершенно другой кодобазой, и это сработало. О чём это говорит, кроме того, что я ошибся? ;)

Более того, любой коммит - всегда тег, который принадлежит ветке. Это сильно облегчает задачу поиска изменений.

В Git коммит тоже принадлежит ветке и имеет свой id. Что не так?

В hg есть аналог rebase и он намного проще и предсказуймей Git.

Вы допустили в фразе "кастрирован и импотентен" десяток ошибок.

И результаты его работы намного безопаснее.

Для безопасности в Git есть reflog и ветки, которые позволяют фиксировать любое состояние с возможностью его вернуть.

Ну, и использовать его там приходится гораздо реже.

Потому что всех устраивает, что в коммитах всё перемешано?

есть удобный инструмент для переноса их туда-обратно, вплоть до отдельных строк

А до правок текста тех строк, что отправляются (например, убрать комментарий типа "а вот тут главное")? Ну и это отдельный инструмент, а в Git оно в коробке.

Но я согласен в том, что проверять надо по уровню отправляемого коммита. Можно остальное скинуть в stash, но я предпочитаю делать `git co HEAD~1` или аналог, а потом вернуться. Stash он один на рабочую копию, а не на ветку.

Потому что процесс, аналогичный привычному, резко усложнился.

Там нет усложнения, просто надо делать чуть иначе. Для построчного stash я не знаю, а вот `add -i` и `add -e` решают задачу. А "набрать в индекс" желательно, чтобы проверить, что же собрал... ну или последовательно amendʼом набирать правки.

И эти сущности не пропадают только от того, что кто-то решил почистить список указателей от неактуальных.

Именно что пропадают. Вмержили в транк - осталась только запись в сообщении коммита.

Терять информацию - это в основе всегда неправильный вариант.

Верно. Поэтому сообщение коммита начинаем с "MOO-1234: Fix moo frequency for most cow breeds". По этому "MOO-1234" выясняется и всё остальное. А как ветка была локально названа у конкретного коммиттера - уже неважно, да хоть "херня которая не даёт выспаться".

И угадывает гит просто отвратительно.

Повторюсь, я "за" сохранение метаинформации об изменениях, если коммиттер хочет этого и предоставляет её. Но при той юзербазе, что есть, отсутствие этой возможности означает минимальную потребность в ней. Какой-нибудь целевой плагин тут был бы, конечно, в тему.

Я плюсанул, но подозреваю, что дело в случае Меты не в лежащем внизу тулинге, а в желании гнать фичи на максимальной скорости...

структуру (не исходники) которого пришлось значительно изменить.

Ну вот это можно уже изучать на предмет оптимизации, конечно, хотя бы плагинами...

А rerere в git не помогает? Вроде как раз для такого и задумана, после первой попытки, где надо таки разгрести вручную.

Как вам а) убедиться, что этот фикс не вызывает новых проблем в других
проектах;

Ну давайте смотреть на процесс. Вот есть изменение в libmoo. У нас монорепа на 200k продуктов. Нам надо отловить те, которые зависят от libmoo напрямую - это шаг 1. Как мы будем это искать? Наверняка есть какой-то список. Вести его в монорепе или в разбросе - нет разницы, всё равно добавлять вручную. (В автопоиск по всему дереву - не верю.)

CI автомат? Ему точно так же нужен явный список. А после этого вытаскивать отдельные подветки толстой репы (не тащить же её целиком!) или отдельные маленькие репы - разницы нет, или второе даже проще.

На любой такой коммит CI должен всё проверить.

Шаг 2 - проекты, связанные с зависящими (типа сетевого взаимодействия) - тем более тоже на основании явно описанных связей.

Так для чего мудохаться с моно?

(На самом деле есть одна тонкость с субмодулями: для некоторых ситуаций нужно хукать замену URL к модулям. Но это в тысячи раз проще поддержки монореп.)

б) доставить этот фикс на другие проекты (и не когда-нибудь, а
поскорее).

О, вот тут действительно интересный вопрос. Если сводный коммит на библиотеку и все её зависимости, типа добавили один аргумент в функцию её API.

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

В Gerrit существует уже 10 лет, типа такого: https://gerrit-review.googlesource.com/c/plugins/scripts/+/411660
см. "relation chain" и номера patchsetʼов: после правки в предыдущем в цепочке следующие надо обновить или локально с пушем, или через средства сервера. В Мете изобрели велосипед.

А если использовать gui, то можно и отдельные diff'ы в отдельных файлах включать в коммит. И в git и в hg.

Вот.

​1. В Git для этого не нужен какой-то отдельный GUI, всё из коробки.

2. Git позволяет это делать (без GUI, `add --e`) даже не с отдельными диффами, а со строками. Критично, когда в таком диффе на 2 строки изменения, которые должны пойти на сервер, 3 на отладочную печать и 4 на комментарий для себя, что тут происходит и почему.

Может, для мелких дежурных правок такое и не нужно, но для задачи типа моей текущей сейчас, где сплошное "сигнал пошёл через обсервер в состояние вложенной FSM", мои комментарии "какого хера? уточнить это место" не должны идти в коммит даже если они на хинди.

​3. После я пересобираю правки и, например, переименования идут в один коммит, doxygen-пояснения - в другой (если их не было, потому что вот такая кодобаза), а функциональные правки - в третий. И только после этого я выставляю это в виде чистого, аккуратного результата, который легко ревьюить сейчас, читать даже через пару лет, прогонять через CI или bisect в любой момент.

А с Mercurial и его "вам это не нужно" в коммиты шли бы грязь, грязь и грязь из разнородных изменений и "я тут ещё одно место добавил и заодно функции описал".

В hg неудобно переписывать историю на сервере, да.

Польза от staging возникает задолго до пуша на сервер.

Information

Rating
5,038-th
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity