Когда я предложил использовать у себя «калибровку по известным данным» вроде 0x55 мне в ответ предложили гораздо более простую вещь: просто смотрите какова минимальная длина нуля. Учитывая, что UART передаёт нулевой бит, затем наименее значимый, вероятность поймать правильный результат уже на первом бите первого байта произвольной посылки примерно 50 %.
Так про тестирование при температуре хорошо бы в статье написать. И там слово «самосинхронизация», хоть и есть, но не поясняется. Где она в коде я не вижу.
qBitTorrent, вообще‐то, имеет открытый исходный код (и libtorrent тоже). Патч к нему надёжнее, чем бинарный патч, он слишком зависит от стабильности выхода используемого автора компилятора.
А теперь нужно взять паяльный фен и жидкий азот с системой подачи и посмотреть куда всё уплывёт при нагреве до максимальной (по datasheet’у) и охлаждении до минимальной температур, а также при разных номиналах питания. Судя по datasheet’у, мало того, что на заводе калибруют с точностью до 10 % (пункт 18.4.1) — до 2 % можете закалиброваться сами. Так ещё и частота сильно плывёт в зависимости от температуры, на те же 10 % примерно (пункт 19.12). И, к тому же, datasheet может и врать, иногда сильно.
Обвинению нужно доказать, что ДП есть. Джиму нужно доказать, что ДП нет. Если и судья, и Джим хотя бы примерно понимают тему, то только одной картинки не хватит — её вполне можно набрутить. Но чем больше обвинение набрутит такого, что будет выглядеть как картинки со скрытым ДП, тем легче будет убедить судью — сложность нахождения f(M()), дающей на выходе ДП у сразу нескольких картинок слишком быстро растёт.
Джону вообще практически ничего светить не должно (кроме требования убрать картинку или убрать сообщение из картинки) — для передачи стеганографического сообщения достаточно доступности в сети всего одной картинки, f и M важнее. Если Джон не автор картинки, то он просто укажет, что картинка в сети уже была, для обвинения Джона уже придётся доказывать знание им f и M.
Для Джима есть вторая линия защиты: если обвинение набрутит f и M, то можно докапываться до того, откуда они это взяли. Потому что доказательство того, что f и M нельзя набрутить является фактически доказательством того, что некоторый алгоритм шифрования гарантированно требует некоторого минимального времени на шифрование сообщение на любом современном компьютере (в т.ч. оснащённом фермой ASIC, заточенной под данную задачу), а этого ещё никто ни для какого алгоритма не сделал; так что обвинению всегда можно предъявить, что они набрутили f и M, даже если вы не знаете, возможно ли это в принципе на современном железе.
Третья линия: обвинение должно искать f и M только для картинок, более ранних дубликатов (таких, что выглядят одинаковыми и M(P) == M(Pdup), но попиксельное совпадение не обязательно) которых в сети нет. Если обвинение сделает ошибку с дупликатом, то её придётся объяснять — нельзя добавить сообщение в уже опубликованную картинку, это нарушает причинно‐следственные связи. (Линия слабее, Джим тоже может набрутить…)
В общем, как я вижу ситуацию: слишком заморочный и наукоёмкий (обвинению ещё нужно понять, как набрутить: это выглядит для меня возможным, но реализаций и сроков я вам не назову) способ подставить человека. И слишком ограниченный: позволяет только обвинить в передаче информации, передача которой запрещена законом.
Что значит «вдруг выясняется»? Стеганография не обложена стандартами, если некоторая фотография P позволяет скрыть передачу n бит данных методом M, то вы всегда можете найти такую функцию f(M(P)), что на её выходе будет детское порно, занимающее n бит или менее. Нужно только постараться найти такую f(), которая будет выглядеть применимой для обмена скрытыми и зашифрованными сообщениями, «n бит или менее» одно из необходимых условий. Или, скорее, «правильный» ключ для любого современного алгоритма шифрования, известные реализации которого позволяют использовать его без аутентификации (аутнефикация усложнит нахождение ключа) — что не так уж невозможно, если учесть что для брутфорса можно использовать все достаточно большие или достаточно длинные последовательности мелких картинок, выложенных Джимом, все алгоритмы шифрования, удовлетворяющие условиям («современный» — без известных уязвимостей), все достаточно неприглядные картинки детского порно и, собственно, все возможные ключи — с таким набором переменных можно сообразить какой‐нибудь способ закончить брутфорс побыстрее.
Если до такого дойдёт, то логичной линией защиты будет указать на осуществимость подставы и указать, что у других картинок Джима и Джона применение такой же f(M(P)) выдаёт мусор.
Feature-toggl’ы не всегда возможны и увеличивают затраты на разработку — их нужно создавать, их нужно убирать, с ними нужно научить работать CI. Review тоже придётся делать чаще, при этом не обладая всей картиной: уже готовые классы и описание задачи reviewer увидит сразу, а насколько готовые классы оптимальны для задачи — нет, нужно выспрашивать у автора, какая картина у него в голове; к тому же я не удивлюсь, если в ходе работы над сложной задачей разработчик часто сначала будет допиливать что может до включения в master, а потом выпиливать это обратно. И это в дополнение к затратам на поддержание «чистоты» истории. А refactoring требуется не только legacy, хотя обширный, может, и реже — смотря что не учли при разработке архитектуры. В trunk-based с флагами я пока вижу только «давайте увеличим трудозатраты программистов и reviewer’ов (часто — других программистов) на то, чтобы тимлид смог читать „чистую“ историю».
На review идёт уже результат слияния, он ничем не отличается от результата rebase+squash, кроме того, что вместо одного коммита с одним описанием есть последовательность. История со слияниями более подробна, понятность также ограничена авторами изменений и не всегда сильно страдает, а усилий нужно делать меньше. Понять «о чём думал автор» в случае спорных решений легче при последовательности изменений с описаниями, а сама модель более лояльна к большим изменениям, которые нельзя минимизировать.
Может и кажется, что легче, но если вы не делаете ещё и squash, то это абсолютно бесполезно, потому как вы анализируете не то, что реально было, а конфликты никуда не деваются, просто теперь размазаны и логику их разрешений опять никто не объснит. А если вы делаете, то вы получаете последовательность огромных патчей, из описания которой значительная часть логики автора пропала при squash; и, дополнительно, логику автора для разрешения конфликтов никто не объясняет и тут, просто теперь все притворяются, что никаких конфликтов не было.
И, самое весёлое, последовательность сплюснутых огромных коммитов в виде патчей соответствует последовательности разниц (в виде патчей) между первыми родителями при использовании слияний. Т.е. вы для «лёгкости анализа» зазря выкидываете кучу информации, ничего взамен реально не получая.
Куда сливать пачку коммитов? Предполагается сливать master в длинную ветку, пока она не готова, если такое слияние зачем‐то требуется (возникли конфликты, был проведён рефакторинг, …), а не длинную ветку в master. Гарантировать работоспособность коммитов не нужно, но не нужно и делать их менее рабочими, чем они есть. Полный squash — это та же самая потеря точности bisect. А при rebase без squash будут цепочки конфликтов.
Относительно хаоса: а зачем вы используете историю, что оно вас волнует? Я вижу основные три применения: annotate, bisect при проблемах и создание списка изменений. Для bisect чем больше коммитов, тем лучше (если они, конечно, достаточно рабочие). Для annotate тоже. Для списка изменений git вполне позволяет вам пройтись только по «первым родителям», которыми будут слияния веток в master, а не слияния master в ветки, так что это только вопрос «насколько адекватны описания слияний».
Как я уже говорил в обсуждении ThreeFlow (начало здесь) просто разрешите merge, и никогда не делайте rebase для больших ветвей, за исключением редактирования истории (в смысле rebase --interactive, но без собственно rebase; у mercurial на это есть histedit, для git’а пришлось написать длинный alias, который определяет, с каким аргументами нужно вызвать rebase --interactive, чтобы ничего никуда не переносить и, к тому же, не уничтожить случайно слияния). «Периодический rebase» с лёгкостью незаметно переведёт пачку коммитов в ещё менее рабочее состояние, чем они были до этого, что отрицательно скажется на точность bisect, если в ветке найдутся ошибки.
На работе у меня Windows (7, WSL нету), там не ELF’ы и objcopy есть разве что в cygwin (у меня тоже установлен). И вряд ли всё так просто: нужно разместить безусловный переход по строго определённому адресу (вектора прерываний), а сама программа должна быть по нулевому адресу. И ещё к аргументам нужно добавить, как минимум, -march=i386 -static -Os. И нужно понять как записывать и считывать регистры специального назначения. Разобраться можно, но зачем?
Помимо этого написание программы на ассемблере позволило использовать «память» в режиме «только чтение», обошедшись без стека и без собственно реализации записи в память — самой памяти в системе никогда не было, была имитация на FPGA, которую тоже нужно написать.
А ещё в природе есть такая вещь, как i386 в корпусе PQFP. У нас под него писали на ассемблере, потому что nasm может сразу выдать Intel hex, содержащий только нашу программу, а возиться для получения аналогичного результата на C никому не хотелось.
Здесь не только «кому как удобнее», есть ещё и объективные показатели. У разных разработчиков разные приоритеты этих показателей, а в разных проектах разные вероятности различного рода конфликтов, но «правильный» ответ под конкретную ситуацию найти можно. Возможно, наши споры помогут кому‐то это сделать.
По поводу добавления изменения в X: я иногда оставляю изменения с неправильной концепцией в ветке просто чтобы показать reviewer’у, что «я проверил эту альтернативу (другую зависимость, другой подход к созданию новой функциональности, …), и она не работает». Пояснения либо в описании изменения, либо в комментариях PR, но не в комментариях кода, если только нет оснований полагать, что кто‐то не должен пытаться использовать эту альтернативу опять. Тут чисто вопрос какие формы коммуникации в команде приемлемы — где провальные решения предполагается документировать и предполагается ли их документировать вообще; ну и вопрос, насколько причёсанная история нужна, тоже.
rerere у меня включён. Но я ни разу не видел, чтобы он сработал против «цепочки конфликтов», и не знаю, с чего бы он вообще должен бы сработать на ней: никогда нет никаких «recorded resolutions» для первого rebase (а цепочка конфликтов, тем не менее, есть), их никогда и не будет, если в начале цепочки конфликтов после следующего rebase в конфликтующий код вносятся изменения (что, скорее всего, так).
А «почему не использовать»: не везде разрешено. Кроме того, конкретно в Neovim для меня изменение означало, что я всегда могу использовать merge для больших веток, независимо от того, есть ли там мешающие конфликты или merge требуется для других целей (например, потому что иначе не пройдёт проверка clint.py). git ri я и так всегда использую до последнего во всех проектах (пока у меня нет причин хотеть быть основанным на последнем master).
Исправления, затем rebase+fixup? Чем это поможет? Вот люди переименовали в master функцию foo в функцию bar, я её использовал в коммите X, а потом в коммите Y решил, что здесь больше подойдёт функция baz. Если нет конфликтов после rebase и нет проваленных тестов (а их нет, т.к. переименованная функция более не используется, а использовалось в новом коде, который в master отсутствует и конфликтов не добавляет), то «исправления, затем rebase+fixup» не поможет, нет причин делать исправления. Поможет, если я буду запускать тесты после каждого коммита из rebase, но это именно то, что я имею ввиду под «не очень».
И, самое главное: зачем нужна «настоящая история изменений»: попробуйте делать bisect с точностью до конкретного коммита конкретной feature ветки, а не с точностью до коммитов слияний. Если вы пропустили такую проблему при rebase, то у вас куча коммитов в результате не скомпилируется, а более всего подверженные проблеме длинные ветки так же чаще всего добавляют проблем.
Поэтому никогда никаких rebase, пока я могу их не делать. И git ri, поскольку авторы git обожают сваливать в одну кучу слабо связанную (семантически) функциональность, ещё иногда её даже не позволяя использовать отдельно. К тому же, даже если я хочу именно изменить историю и перенести ветку, гораздо проще сначала только изменить историю, потом только перенести ветку: так легче исправлять свои ошибки, и легче их вообще увидеть (у меня тут конфликт, потому что я промахнулся с тем, куда делать squash/fixup, или потому что в master что‐то поменяли?).
Мой отличается только тем, что я вместо sh написал dash (у Gentoo в качестве sh стоит bash, а мне нужно проверять такие вещи на чём‐то поближе к POSIX shell).
Ну и последнее. Каждый рабочий день я начинаю с того, что делаю ребейз своей текущей задачи на dev. Это ведь не сложно, верно?
Если там конфликты в том месте, которое вы активно (т.е. в нескольких коммитах) редактировали, то вы имеете хорошие шансы получить цепочку конфликтов при rebase и делать кучу бесполезных действий для их решения. И даже если конфликтов как бы нет, есть шансы сделать изменения некорректными и не заметить: к примеру, если функция была удалена в файле, который вы не меняли, а вы её у себя используете. Заметить при тестах и исправить ситуацию одним изменением легко, исправить по всей ветке — не очень. Поэтому я в своё время уговорил команду Neovim, что для больших PR можно (и нужно) делать merge, а не rebase. А у себя (и в wiki Neovim) имею команду git ri, которая как бы rebase --interactive, только ничего никуда не переносит, лишь даёт отредактировать историю либо с начала ветки, либо с последнего merge.
Когда я предложил использовать у себя «калибровку по известным данным» вроде 0x55 мне в ответ предложили гораздо более простую вещь: просто смотрите какова минимальная длина нуля. Учитывая, что UART передаёт нулевой бит, затем наименее значимый, вероятность поймать правильный результат уже на первом бите первого байта произвольной посылки примерно 50 %.
Так про тестирование при температуре хорошо бы в статье написать. И там слово «самосинхронизация», хоть и есть, но не поясняется. Где она в коде я не вижу.
Именно эта процедура «заново накладывать патч и пересобирать» и является более надёжной, так что я бы не сказал «без разницы».
qBitTorrent, вообще‐то, имеет открытый исходный код (и libtorrent тоже). Патч к нему надёжнее, чем бинарный патч, он слишком зависит от стабильности выхода используемого автора компилятора.
А теперь нужно взять паяльный фен и жидкий азот с системой подачи и посмотреть куда всё уплывёт при нагреве до максимальной (по datasheet’у) и охлаждении до минимальной температур, а также при разных номиналах питания. Судя по datasheet’у, мало того, что на заводе калибруют с точностью до 10 % (пункт 18.4.1) — до 2 % можете закалиброваться сами. Так ещё и частота сильно плывёт в зависимости от температуры, на те же 10 % примерно (пункт 19.12). И, к тому же, datasheet может и врать, иногда сильно.
Обвинению нужно доказать, что ДП есть. Джиму нужно доказать, что ДП нет. Если и судья, и Джим хотя бы примерно понимают тему, то только одной картинки не хватит — её вполне можно набрутить. Но чем больше обвинение набрутит такого, что будет выглядеть как картинки со скрытым ДП, тем легче будет убедить судью — сложность нахождения
f(M())
, дающей на выходе ДП у сразу нескольких картинок слишком быстро растёт.Джону вообще практически ничего светить не должно (кроме требования убрать картинку или убрать сообщение из картинки) — для передачи стеганографического сообщения достаточно доступности в сети всего одной картинки,
f
иM
важнее. Если Джон не автор картинки, то он просто укажет, что картинка в сети уже была, для обвинения Джона уже придётся доказывать знание имf
иM
.Для Джима есть вторая линия защиты: если обвинение набрутит
f
иM
, то можно докапываться до того, откуда они это взяли. Потому что доказательство того, чтоf
иM
нельзя набрутить является фактически доказательством того, что некоторый алгоритм шифрования гарантированно требует некоторого минимального времени на шифрование сообщение на любом современном компьютере (в т.ч. оснащённом фермой ASIC, заточенной под данную задачу), а этого ещё никто ни для какого алгоритма не сделал; так что обвинению всегда можно предъявить, что они набрутилиf
иM
, даже если вы не знаете, возможно ли это в принципе на современном железе.Третья линия: обвинение должно искать
f
иM
только для картинок, более ранних дубликатов (таких, что выглядят одинаковыми иM(P) == M(Pdup)
, но попиксельное совпадение не обязательно) которых в сети нет. Если обвинение сделает ошибку с дупликатом, то её придётся объяснять — нельзя добавить сообщение в уже опубликованную картинку, это нарушает причинно‐следственные связи. (Линия слабее, Джим тоже может набрутить…)В общем, как я вижу ситуацию: слишком заморочный и наукоёмкий (обвинению ещё нужно понять, как набрутить: это выглядит для меня возможным, но реализаций и сроков я вам не назову) способ подставить человека. И слишком ограниченный: позволяет только обвинить в передаче информации, передача которой запрещена законом.
Что значит «вдруг выясняется»? Стеганография не обложена стандартами, если некоторая фотография P позволяет скрыть передачу n бит данных методом M, то вы всегда можете найти такую функцию f(M(P)), что на её выходе будет детское порно, занимающее n бит или менее. Нужно только постараться найти такую f(), которая будет выглядеть применимой для обмена скрытыми и зашифрованными сообщениями, «n бит или менее» одно из необходимых условий. Или, скорее, «правильный» ключ для любого современного алгоритма шифрования, известные реализации которого позволяют использовать его без аутентификации (аутнефикация усложнит нахождение ключа) — что не так уж невозможно, если учесть что для брутфорса можно использовать все достаточно большие или достаточно длинные последовательности мелких картинок, выложенных Джимом, все алгоритмы шифрования, удовлетворяющие условиям («современный» — без известных уязвимостей), все достаточно неприглядные картинки детского порно и, собственно, все возможные ключи — с таким набором переменных можно сообразить какой‐нибудь способ закончить брутфорс побыстрее.
Если до такого дойдёт, то логичной линией защиты будет указать на осуществимость подставы и указать, что у других картинок Джима и Джона применение такой же
f(M(P))
выдаёт мусор.Там написано «статистический», а не «статический».
Feature-toggl’ы не всегда возможны и увеличивают затраты на разработку — их нужно создавать, их нужно убирать, с ними нужно научить работать CI. Review тоже придётся делать чаще, при этом не обладая всей картиной: уже готовые классы и описание задачи reviewer увидит сразу, а насколько готовые классы оптимальны для задачи — нет, нужно выспрашивать у автора, какая картина у него в голове; к тому же я не удивлюсь, если в ходе работы над сложной задачей разработчик часто сначала будет допиливать что может до включения в master, а потом выпиливать это обратно. И это в дополнение к затратам на поддержание «чистоты» истории. А refactoring требуется не только legacy, хотя обширный, может, и реже — смотря что не учли при разработке архитектуры. В trunk-based с флагами я пока вижу только «давайте увеличим трудозатраты программистов и reviewer’ов (часто — других программистов) на то, чтобы тимлид смог читать „чистую“ историю».
На review идёт уже результат слияния, он ничем не отличается от результата rebase+squash, кроме того, что вместо одного коммита с одним описанием есть последовательность. История со слияниями более подробна, понятность также ограничена авторами изменений и не всегда сильно страдает, а усилий нужно делать меньше. Понять «о чём думал автор» в случае спорных решений легче при последовательности изменений с описаниями, а сама модель более лояльна к большим изменениям, которые нельзя минимизировать.
Может и кажется, что легче, но если вы не делаете ещё и squash, то это абсолютно бесполезно, потому как вы анализируете не то, что реально было, а конфликты никуда не деваются, просто теперь размазаны и логику их разрешений опять никто не объснит. А если вы делаете, то вы получаете последовательность огромных патчей, из описания которой значительная часть логики автора пропала при squash; и, дополнительно, логику автора для разрешения конфликтов никто не объясняет и тут, просто теперь все притворяются, что никаких конфликтов не было.
И, самое весёлое, последовательность сплюснутых огромных коммитов в виде патчей соответствует последовательности разниц (в виде патчей) между первыми родителями при использовании слияний. Т.е. вы для «лёгкости анализа» зазря выкидываете кучу информации, ничего взамен реально не получая.
Куда сливать пачку коммитов? Предполагается сливать master в длинную ветку, пока она не готова, если такое слияние зачем‐то требуется (возникли конфликты, был проведён рефакторинг, …), а не длинную ветку в master. Гарантировать работоспособность коммитов не нужно, но не нужно и делать их менее рабочими, чем они есть. Полный squash — это та же самая потеря точности bisect. А при rebase без squash будут цепочки конфликтов.
Относительно хаоса: а зачем вы используете историю, что оно вас волнует? Я вижу основные три применения: annotate, bisect при проблемах и создание списка изменений. Для bisect чем больше коммитов, тем лучше (если они, конечно, достаточно рабочие). Для annotate тоже. Для списка изменений git вполне позволяет вам пройтись только по «первым родителям», которыми будут слияния веток в master, а не слияния master в ветки, так что это только вопрос «насколько адекватны описания слияний».
Как я уже говорил в обсуждении ThreeFlow (начало здесь) просто разрешите merge, и никогда не делайте rebase для больших ветвей, за исключением редактирования истории (в смысле
rebase --interactive
, но без собственноrebase
; у mercurial на это есть histedit, для git’а пришлось написать длинный alias, который определяет, с каким аргументами нужно вызватьrebase --interactive
, чтобы ничего никуда не переносить и, к тому же, не уничтожить случайно слияния). «Периодический rebase» с лёгкостью незаметно переведёт пачку коммитов в ещё менее рабочее состояние, чем они были до этого, что отрицательно скажется на точность bisect, если в ветке найдутся ошибки.Не понимаю, к чему этот комментарий. Если какой‐то *asm не способен выдавать «чистый бинарник», то зачем он вообще нужен?
На работе у меня Windows (7, WSL нету), там не ELF’ы и objcopy есть разве что в cygwin (у меня тоже установлен). И вряд ли всё так просто: нужно разместить безусловный переход по строго определённому адресу (вектора прерываний), а сама программа должна быть по нулевому адресу. И ещё к аргументам нужно добавить, как минимум,
-march=i386 -static -Os
. И нужно понять как записывать и считывать регистры специального назначения. Разобраться можно, но зачем?Помимо этого написание программы на ассемблере позволило использовать «память» в режиме «только чтение», обошедшись без стека и без собственно реализации записи в память — самой памяти в системе никогда не было, была имитация на FPGA, которую тоже нужно написать.
А ещё в природе есть такая вещь, как i386 в корпусе PQFP. У нас под него писали на ассемблере, потому что nasm может сразу выдать Intel hex, содержащий только нашу программу, а возиться для получения аналогичного результата на C никому не хотелось.
Здесь не только «кому как удобнее», есть ещё и объективные показатели. У разных разработчиков разные приоритеты этих показателей, а в разных проектах разные вероятности различного рода конфликтов, но «правильный» ответ под конкретную ситуацию найти можно. Возможно, наши споры помогут кому‐то это сделать.
По поводу добавления изменения в X: я иногда оставляю изменения с неправильной концепцией в ветке просто чтобы показать reviewer’у, что «я проверил эту альтернативу (другую зависимость, другой подход к созданию новой функциональности, …), и она не работает». Пояснения либо в описании изменения, либо в комментариях PR, но не в комментариях кода, если только нет оснований полагать, что кто‐то не должен пытаться использовать эту альтернативу опять. Тут чисто вопрос какие формы коммуникации в команде приемлемы — где провальные решения предполагается документировать и предполагается ли их документировать вообще; ну и вопрос, насколько причёсанная история нужна, тоже.
rerere у меня включён. Но я ни разу не видел, чтобы он сработал против «цепочки конфликтов», и не знаю, с чего бы он вообще должен бы сработать на ней: никогда нет никаких «recorded resolutions» для первого rebase (а цепочка конфликтов, тем не менее, есть), их никогда и не будет, если в начале цепочки конфликтов после следующего rebase в конфликтующий код вносятся изменения (что, скорее всего, так).
А «почему не использовать»: не везде разрешено. Кроме того, конкретно в Neovim для меня изменение означало, что я всегда могу использовать merge для больших веток, независимо от того, есть ли там мешающие конфликты или merge требуется для других целей (например, потому что иначе не пройдёт проверка clint.py).
git ri
я и так всегда использую до последнего во всех проектах (пока у меня нет причин хотеть быть основанным на последнем master).Исправления, затем rebase+fixup? Чем это поможет? Вот люди переименовали в master функцию foo в функцию bar, я её использовал в коммите X, а потом в коммите Y решил, что здесь больше подойдёт функция baz. Если нет конфликтов после rebase и нет проваленных тестов (а их нет, т.к. переименованная функция более не используется, а использовалось в новом коде, который в master отсутствует и конфликтов не добавляет), то «исправления, затем rebase+fixup» не поможет, нет причин делать исправления. Поможет, если я буду запускать тесты после каждого коммита из rebase, но это именно то, что я имею ввиду под «не очень».
И, самое главное: зачем нужна «настоящая история изменений»: попробуйте делать bisect с точностью до конкретного коммита конкретной feature ветки, а не с точностью до коммитов слияний. Если вы пропустили такую проблему при rebase, то у вас куча коммитов в результате не скомпилируется, а более всего подверженные проблеме длинные ветки так же чаще всего добавляют проблем.
Поэтому никогда никаких rebase, пока я могу их не делать. И
git ri
, поскольку авторы git обожают сваливать в одну кучу слабо связанную (семантически) функциональность, ещё иногда её даже не позволяя использовать отдельно. К тому же, даже если я хочу именно изменить историю и перенести ветку, гораздо проще сначала только изменить историю, потом только перенести ветку: так легче исправлять свои ошибки, и легче их вообще увидеть (у меня тут конфликт, потому что я промахнулся с тем, куда делать squash/fixup, или потому что в master что‐то поменяли?).https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#pull-requests-prs
Мой отличается только тем, что я вместо
sh
написалdash
(у Gentoo в качестве sh стоит bash, а мне нужно проверять такие вещи на чём‐то поближе к POSIX shell).Если там конфликты в том месте, которое вы активно (т.е. в нескольких коммитах) редактировали, то вы имеете хорошие шансы получить цепочку конфликтов при rebase и делать кучу бесполезных действий для их решения. И даже если конфликтов как бы нет, есть шансы сделать изменения некорректными и не заметить: к примеру, если функция была удалена в файле, который вы не меняли, а вы её у себя используете. Заметить при тестах и исправить ситуацию одним изменением легко, исправить по всей ветке — не очень. Поэтому я в своё время уговорил команду Neovim, что для больших PR можно (и нужно) делать merge, а не rebase. А у себя (и в wiki Neovim) имею команду
git ri
, которая как быrebase --interactive
, только ничего никуда не переносит, лишь даёт отредактировать историю либо с начала ветки, либо с последнего merge.