Чем опасен rebase, или как получилось, что 2*3=5

    Однажды старший программист Антон искал причину очередного бага в очень важном проекте компании:
    git bisect start
    git bisect bad
    git bisect good
    …
    

    В компании использовали rebase, история коммитов была линейной, и поиск по ней доставлял Антону одно удовольствие.
    — Ага, нашел. Ну конечно: в коде написано «2*3=5», ещё бы оно работало с этим бредом! Какой @#$%^ это написал?


    Антон: — Эй, Василий! Ты о чем думал, когда «2*3=5» писал?
    Вася: — Да не было такого. Я «2+3=5» написал, точно помню.
    Антон: — Это ты в сообщении к коммиту «2+3» написал, а в коде «2*3», вот смотри.


    Вася посмотрел на свой коммит, и не верил своим глазам: действительно, в коде «2*3=5». В глазах у Васи потемнело…
    Антон: — Эх, нельзя так безответственно, Василий, это неприемлемо.
    Васю пришлось уволить…

    В это время в параллельной реальности..

    Антон ищет причину очередного бага в очень важном проекте. В компании используют merge, а не rebase, история коммитов нелинейна, поэтому Антон хмурит брови и периодически матерится, глядя на паутину слитых веток. Но git bisect умеет работать с нелинейной историей и его она ничуть не смущает.
    — Ага, нашел. В коде «2*3=5», ещё бы оно работало. Так, это появилось, когда слили 2 ветки. В одной Вася складывает «2+3=5», всё верно написал, у нас и по ТЗ результат операции 5 должен быть. А в другой Петя умножает «2*2=4». Ага, а при слиянии получилось «2*3=5», понятно.

    Антон: — Эй, Пётр! Ты зачем сложение на произведение заменил?
    Петя: — Ну, мне показалось это более наглядным.
    Антон: — Откати ка обратно, у нас из-за этого баг вылез.
    Петя: — ОК.


    Мораль: rebase меняет контекст, в котором были написаны коммиты, и теряет информацию о слияниях веток, которая может оказаться полезной для определения причины ошибки. Помните об этом.

    Пример проекта на github.

    Upd.
    Если захотите воспроизвести, обратите внимание, что в проекте специально используется формат, несколько отличающийся от «2+2=4 (в столбик)», чтобы и merge и rebase прошли без конфликтов.
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 145

      +2
      Благодарю за интересную сказку на вечер.
        +6
        А злодей сказал бы «спасибо за указание на новый действенный способ внутрикорпоративной интриги».
        +34
        У нас в команде простое правило — ребейзи у себя локально сколько влезет, но если коммит уже попадал в общий репозиторий — то его нельзя ребейзить (и push --force делает только тимлид в экстремальных ситуациях).

        Поэтому обычно и большая часть истории линейная, и для удобства ревью можно коммиты клеить, но когда идёт слияние веток разных разработчиков — то это мерж. Поэтому таких историй нет и вообще видно реально сделанные коммиты, а не некое совместное творчество коммитера и ребейзера, и восстановить реально существовавшую точку в истории всегда можно.

        Любой инструмент нужно применять к месту и со здравым смыслом, а фанатики ребейза — они как любые фанатики. (Ц) Кэп.
          0
          Согласен. Автор рассмотрел только два крайних случая — либо глобальный ребейз в проекте компании, либо глобальный мердж. Вариант хорошей организации проекта не рассмотрен. Например в центральные репозитории force push запрещен, а локально до пуша хоть ребейзи, хоть интерактивно ребейзи, хоть амендь коммиты…
            +1
            Force push тут вообще ни при чем (то, что он неприемлем, по-моему очевидно). Пример был создан как раз при локальном rebase, это стандартный workflow.
              +1
              Ок. Тогда согласен. Хотя на моей памяти таких случаев не было. Чаще проблемы от неудачного разруливания конфликтов.
                +1
                При локальном ребейзе обычно автор ребейзит свои патчи. С реальным кодом, такие засады бывают редко, обычно все же возникают конфликты, которые пользователь должен разрулить руками. Частично эта проблема ловится на ревью, частично ее ловят тесты.

                PS: на моей памяти подобная штука происходила при накладывании OpenVZ патча, когда там sysctl-ли неуправляемо переезжали в другие подсистемы.
              +1
              Объясните мне хабралогику, пожалуйста.
              Когда я написал то же самое в комментариях к другой статье
              habrahabr.ru/post/179045/#comment_6213807
              Вся ветка сплошь заминусована.
                +2
                Логики нет никакой. В комментарии выше идёт посыл «ребейзи у себя локально сколько влезет, и таких историй не будет», хотя в статье как раз и показан пример, когда локальный rebase теряет важный контекст, и может ввести в заблуждение.
                К слову, та ваша ветка как раз и побудила меня составить этот пример для наглядности.
                +2
                Как уже указали, ваш комментарий не имеет ничего общего со статьёй. ;)
                В статье как раз показан пример вполне себе локального ребейза.
                +35 к этому комменту наглядно показывает, как внимательно хабраюзеры читают статьи и комментарии к ним ;)
                  0
                  Совершенно верно! Я как-то на один из подобных постов отвечал, что народ путает терминологию, а именно: опубликованные vs. публичные ветки или репозитории. Вот в первых как раз git rebase ... противопоказан.
                  0
                  а можно же после rebase делать merge --no-ff и все будет красивенько и удобненько
                    0
                    В таком случае всё равно изменится контекст и будет выглядеть, как будто Вася написал «2*3=5», хотя он этого не писал.
                    +12
                    А почему Вася после ребейза не проверил свой код? Имхо, уволен справедливо.
                      +4
                      А при беглом просмотре Вася бы и не заметил ошибки.
                        0
                        Т.е. данный кусочек кода не был покрыт тестами, хотя проект очень важен для компании?
                          +7
                          Мы же не в идеальном мире живем, в реальности в проекте не 8 строчек, в ветке не 1 коммит, а покрытие кода тестами не 100-процентное. И при слиянии (как через merge, так и через rebase) ошибку можно проглядеть, тем более, если слияние без конфликтов (как в примере).
                          Только при merge в истории сохранится информация, чем руководствовался автор при написании кода коммита, и в какой момент возникла ошибка (при слиянии, а не при написании кода). А при rebase — нет. А не зная причин ошибки, исправить её может быть труднее.
                            0
                            Согласен с теми, кто написал, что былина интересная, как раз то чтение, которые приятно читать на Хабре под конец рабочего для, +.

                            Выводы из конкретного примера однако неоднозначные. Почему объектом критики выбран rebase?

                            Почему бы не «наехать» на:

                            — Алгоритм текствого diff'а/patch'а конкретного в git
                            — Алгоритм текствого diff'а/patch'а вообще

                            Алгоритм текстового diff'а — эвристика, а уж применение его как patch — эвристика в квадрате. Стоит удивляться и восхищаться, что при этом метод rebase был реализован *для специальных целей* и на практике работает весьма неплохо.

                            Учить «пионеров», не нюхавших CVSа, не юзать rebase направо и налево конечно стоит, но использовать для этого недостатки алгоритма diff — «не очень красиво» (хотя еще раз, былина получилась интересная). Для пущего эффекта, статью можно было бы озаглавить «Как я похакал diff» или вообще по-ализаровски: «В git найдена критическая уязвимость» ;-).
                              +1
                              Да ладно, суть примера не в том, как diff работает, а в том, что rebase контекст меняет.
                              Ну т.е. другой алгоритм diff'а безусловно мог бы показать конфликт в конкретно этом примере, но лишь потому, что я пытался ужать его в несколько строк. В реальном проекте изменения Пети и Васи могут быть вообще в разных файлах, так что алгоритм diff'а может быть каким угодно, но смена контекста всё равно может привести к похожим последствиям.

                              Кстати, немного отвлекаясь от темы, в git-diff можно использовать разные алгоритмы:
                              --diff-algorithm={patience|minimal|histogram|myers}
                                Choose a diff algorithm. The variants are as follows:
                                default, myers
                                  The basic greedy diff algorithm. Currently, this is the default.
                                minimal
                                  Spend extra time to make sure the smallest possible diff is produced.
                                patience
                                  Use "patience diff" algorithm when generating patches.
                                histogram
                                  This algorithm extends the patience algorithm to "support low-occurrence common elements".
                              

                              Кроме того, есть опции --word-diff и прочие.
                            +7
                            Давайте уволим ещё старшего QA (за непокрытие) и менеджера проекта (за накосячившего QA) =)

                            Как сказали выше — «спасибо за сказку». Сказка не касалась таких (безусловно важных) тем, как контроль качества и управления разработкой бизснес-критикал проектов. Так что я думаю тема достаточно неплохо раскрыта. Простим же автору недостаточное раскрытие прочих важных, но не обозначеных в статье тем?
                              +2
                              Программисты бывает двух типов — которые ещё не делают юнит-тесты и которые уже делают юнит-тесты.
                                +1
                                Проект 1М+ строк кода, потом пришли к покрытию тестами. За сколько, как Вы думаете, покруют на 100%?
                                P.S. Да, кстати, важно не забывать что Code Coverage = 100% не означает 100% покрытия тестовых случаев.
                                  +1
                                  Конечно, все ситуации покрыть малореально. А ведь ещё есть сроки и прочее, что ещё сильнее ограничивает время на написание тестов.
                                  Я как раз на это намекаю, что тесты часто дописываются когда работа в полном разгаре, а не в самом начале.

                                  У меня лично много проектов, которые я начинаю, а потом они идут в мусорку по ненадобности. Было бы грустно тратить время на юнит-тесты для таких, я бы тогда вообще ничего не успевал бы.
                                  А вот когда проект пошёл удачно, то тогда уже начинаются тесты, фреймворки для тестирования, тестовые фиды, prod/qa/dev и прочие специи по вкусу и по задачам.
                                  При текущей конкуренции на рынке это достаточно адекватный вариант разработки новых идей.
                                    0
                                    Я всегда начинаю проекты с тестов, но пишу минималку для проверки тех сценариев, что сразу в голову приходят. Это быстро. Остальные тесты пишет QA.
                                      0
                                      Это очень классно когда есть QA, много заинтересованных людей в компании и достаточно времени. А когда у тебя стартап из тебя одного или маленькая команда в два с половиной человека, то в одном лице может быть и разработчик и QA и менеджер. В этом случае приоритеты, к сожалению, идут не в пользу юнит-тестов.
                                        0
                                        Если писать в стиле TDD или похожем то времени на сам тест мало уходит, гораздо больше уходит на обдумывание всех случаев. Зато коду можно доверять. Вы ведь не хотите чтобы в стартапе у вас кому то из пользователей ненароком один мильен засчитался?
                                +4
                                Тесты не панацея.
                            +3
                            Ради интереса сделал:
                            создал файл, в master написал 2+2=4 (в столбик)
                            потом создал ветку исправил 2*3=5 (в столбик)
                            в master исправил 2*2=4 (в столбик)
                            и всё прекрасно слилось воедино. git ругнулся на то что есть конфликт, но kdiff3 его прекрасно разрулил без участия человека.

                            Rebase и Merge дали один и тот же результат. Кстати, вброшу ка я:
                            rebase и merge в 95% дают один и тот же результат, если конечно во время ребэйза чего-нибудь кардинально не менять.

                            Вообще и merge, и rebase опасны тем, что это объединение двух историй, а значит вероятны конфликты, неправильно принятые решения и т.д. Тут уже всё зависит от человека, а не от VCS.
                              +2
                              Я специально не писал «2+2=4 (в столбик)», чтобы и merge и rebase прошли без конфликтов. См. репозиторий.
                              И да, rebase и merge дают идентичный результат, только с разной историей.
                                +1
                                Я кстати, немного поспешил с ответом. Посмотрел репозиторий и историю.
                                Да в этом случае, как описали вы и показали на гитхабе, результат будет неправильным.
                              0
                              Если посмотреть на изменения Васи при варианте с ребейзом, видно, что он поменял 2 на 3, и 4 на 5. А произведение не трогал, и дальше по истории можно увидеть, что сумму на произведение поменял Петя. Какие вопросы к Василию?
                                0
                                Петя изменил 2+2=4 на 2*2=4. Корректно? Пожалуй, да.
                                А Вася якобы изменил 2*2=4 на 2*3=5. Корректно?
                                  0
                                  А Антон, который смержил 2*3=5? Корректно? Почему еще не уволен?
                                    +5
                                    Вот видите, в варианте с merge четко видно причину ошибки: слияние.
                                    А в варианте с rebase создается ложное впечатление, что был написан некорректный код.
                                      +1
                                      Согласен. Рациональное зерно в этом есть.
                                      Профит только в том, что Васе не придется оправдываться. Ведь баг будет как в первом, так и во втором случае.
                                      Но когда все будут мержить branch в origin/branch, хотел бы я посмотреть как Антон будет морщиться при поиске бага.
                                        +4
                                        Он не только морщится, он ещё и «периодически матерится, глядя на паутину слитых веток». :)
                                        В обоих подходах есть свои плюсы и минусы. Важно о них знать, особенно о минусах того, который используешь.
                                          +1
                                          Что бы не материться при виде путины скрытых меток, нужно использовать именованные ветки.
                                          А т.к. их нет в GIT, то всем нужно обязательно в комментариях писать имя задачи/ветки.
                                +12
                                Подобная ситуация справедлива для любого патча применяемого не для той ревизии из которой он получен. Например, мы сделали патч для ревизии 10, а применяем для ревизии 20. Допустим патч успешно применился, но код может оказаться неработоспособным.
                                  –1
                                  А как это у вас автоматически мержится при ребэйзе?
                                  Только что проверил, будет конфликт, что собственно ожидаемо.

                                  Applying: 2+3=5
                                  Falling back to patching base and 3-way merge…
                                  Failed to merge in the changes.
                                  Patch failed at 0001 2+3=5

                                  И тут уж явно никак не закомитишь не правильно, собственно на чем вся статья и основана.

                                  Что бы быть уверенным что мы говорим об одном и том же вот короткий скрипт, который воссоздает ваш вариант и воспроизводит конфликт при ребэйзе:

                                  git init
                                  touch test.txt
                                  
                                  echo -e "2\n+\n2\n=\n4" > test.txt
                                  git add test.txt
                                  git commit -m "2+2=4"
                                  
                                  git checkout -b my
                                  echo -e "2\n+\n3\n=\n5" > test.txt
                                  git add test.txt
                                  git commit -m "2+3=5"
                                  
                                  git checkout master
                                  echo -e "2\n*\n2\n=\n4" > test.txt
                                  git add test.txt
                                  git commit -m "2*2=4"
                                  
                                  git checkout my
                                  git rebase master
                                  
                                    0
                                    См. ответ выше. Обновлю пожалуй статью, чтобы акцентировать внимание на том, что формат записи не «2+2=4 (в столбик)».
                                      0
                                      Я запутался. Должно быть в столбик или в строку? Потому что все скрины у вас в столбик. И если в столбик, то будет конфликт.
                                        0
                                        У меня вот так:
                                        image
                                        Конфликтов не было, я специально проверял, чтобы не дезинформировать ненароком.
                                        Попробуйте сами:
                                        git clone https://github.com/rabovik/RebaseVSMergeExample.git
                                        cd RebaseVSMergeExample
                                        git checkout -b my ab640a2
                                        git rebase cae31030
                                        

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

                                          У вас есть комит с описанием «2+3=5», но это же неверное описание, вы должны описать что делает патч, а не состояние кода в момент комита, таким образом описание должно быть «заменили 2 на 3 и 4 на 5». Вот теперь все встает сразу на свои места.

                                          Иначе в таком случае ЛЮБАЯ git операция подходит под статью. Возьмем git cherrypick — снова не верно, rebase — неверно, merge — неверно. И все от неправильного описания патча и его трактовки.
                                            0
                                            Ниже уже ответили, но я пожалуй добавлю для полной ясности.
                                            1) Rebase используется так же, как у вас в скрипте, возможно вас смутила запись git rebase cae31030, — так это потому, что в репозитории я rebase уже делал, и мастера уже нет; если повторять с нуля, то будет git rebase master.
                                            2) Любой rebase с мастером + мердж в мастер — это и есть перенос патчей в мастер.
                                            3) Rebase работает верно, только при rebase происходит потеря контекста. Изначально коммит это патч+контекст, при rebase же остаётся только патч, а контекст меняется.
                                            4) Какие должны быть сообщения коммитов — вопрос дискуссионный, статья не про это. Отмечу только, что если написать, как предполагаете вы, то в репозитории не останется даже намека на то, какие причины побудили Васю написать этот код.
                                            5) Не любая операция искажает историю. Rebase и cherrypick — да, контекст теряют. Merge — сохраняет историю неизменной.

                                            В остатке: если хотим иметь в репозитории набор патчей — используем rebase, если важна правдивая история — используем merge.
                                              0
                                              1) можете написать, что не так в скрипте в комменте первого уровня? Почему он приводит к конфликту, которого не было у вас? Напишите, если не сложно, свой вариант скрипта, который покажет безконфликтный rebase
                                                0
                                                сорри, поспешил.
                                                нашёл ниже по треду
                                      –3
                                        +1
                                        А при чем тут запушенные данные?
                                        +5
                                        В статье нет ни слова про rebase запушенных данных.
                                        Описан стандартный юзкейс при пуше своего коммита.
                                        0
                                        Назревает необходимость в системе контроля версий для систем контроля версий :-)
                                          –1
                                          Исходники git-а лежат в git-е. Думаю это верно для большинства систем контроля версий.
                                            +1
                                            проще: пользуемся mercurial — у них идеологически нет команды rebase
                                            Да и для освоения она легче чем git
                                              –1
                                              Пробовали, ни разу не легче. По гиту есть хотя бы сообщество и опытные товарищи, которые могут что-то объяснить. В меркуриал въехать самостоятельно вообще нереально.
                                                +1
                                                ну это всегда так было — проще всего тот дистрибутив linux которым пользуется ближайший к вам админ, и даже если это gentoo — он с админом будет проще любого debian :)
                                                Я к примеру въехал в mercurial довольно быстро, а вот в гит до сих пор путаюсь в командах.
                                                  –1
                                                  git — сложнее:
                                                  — не логичные команды
                                                  — нет именованных веток
                                                  — нужно указывать ветку при pull или push или дополнительно настраивать, что бы происходило автоматом
                                                    0
                                                    — не логичные команды
                                                    В Hg логики тоже не нашёл, этим он не легче.
                                                    — нет именованных веток
                                                    Чушь, всегда переключался по имени ветки.
                                                    нужно указывать ветку при pull или push или дополнительно настраивать, что бы происходило автоматом
                                                    push да, а при pull какая разница? Легко решается алиасами, которые всё равно должны быть (не писать же всё время все эти длиннющие команды).
                                                      0
                                                      В Hg логики тоже не нашёл, этим он не легче.

                                                      Например:
                                                      git branch -a
                                                      git tag
                                                      
                                                      git branch name
                                                      git tag -a name
                                                      
                                                      
                                                      hg branch name
                                                      hg tag name
                                                      
                                                      hg branches
                                                      hg tags
                                                      


                                                      Чушь, всегда переключался по имени ветки.

                                                      Прочитайте сначала, что такое именованная ветка. И их действительно нет в git'е.
                                                      pqr7.wordpress.com/2010/10/10/a-guide-to-branching-in-mercurial/

                                                      push да, а при pull какая разница? Легко решается алиасами.

                                                      Не легко. У меня никто в команде этого делать не умеет. И мало того, на всяких сходках программистов, никто мне не сказал, как же это сделать. Все ссылались на чтение мана. В Hg это делается с помощью одной команды «hg push».
                                                        0
                                                        Прочитайте сначала, что такое именованная ветка. И их действительно нет в git'е.
                                                        Если вы говорите, что нет почти никому не нужной штуки с несоответсвующим именем, то так и говорите, потому что в русском языке «именованная ветка» — ветка, которая имеет имя, и в гите ветки имена-таки имеют. (P.S. Ссылка нерабочая)
                                                        Не легко. У меня никто в команде этого делать не умеет.
                                                        По памяти:
                                                        alias push='git push origin `__git_ps1`'
                                                        
                                                        Аналогично с pull.

                                                        Гугл подсказывает, что можно даже проще, всего лишь настроить конфиг:
                                                        git config --global push.default current
                                                        
                                                          0
                                                          Если вы говорите, что нет почти никому не нужной штуки с несоответсвующим именем, то так и говорите, потому что в русском языке «именованная ветка» — ветка, которая имеет имя, и в гите ветки имена-таки имеют. (P.S. Ссылка нерабочая)

                                                          Вроде как у всех кому давал — открывается. И эта никому не нужная штука, одна из основных фич из-за которых большие проекты переходят/остаются на Hg.
                                                          Эта одна из самых нужных фич, для тимлидов, которая позволяет легко отслеживать все изменения проекта в истории.
                                                          В Git, например, не сохраняется история, к какой ветке принадлежал commit после merge.
                                                            0
                                                            Это лишь вопрос организации процесса, а не инструмента. Там, где я работал всё было просто: в сообщение коммита и в имя ветки добавлялся номер задачи, по которой идут работы. Отслеживается потом проще простого.
                                                              0
                                                              Слушайте, а как вы с таким подходом вообще пришли к использованию VCS? Менялись бы себе дальше тарболлами и патчами по почте. Отслеживается проще некуда.
                                                                0
                                                                Улучшили рабочий процесс и перешли с SVN на GIT. До этого была неудачная попытка перейти на Mercurial.
                                                                  0
                                                                  Спросите у коллег, которые раньше работали в Мегаплане, на сколько проще работать с Hg, они вам расскажут.
                                                                    0
                                                                    Имея опыт, с DVCS уже пофиг. Покажите мне пример, когда с нуля сами изучили.
                                                                      0
                                                                      Я перешел с SVN на Hg за 2-3 дня.
                                                                      Потом осваивал не меньше полу-месяца Git(что бы полноценно управлять репозиторем и настраивать deploy)
                                                                      Опыт тесной работы как с Git, так и с Hg более года.
                                                                        0
                                                                        И как переходили? По манам или советам и наставлениям гуру? А вообще вы приводите разные задачи, имеющие разную сложность.
                                                                          0
                                                                          Переходил по манам + советом помогал 1 человек, который внедрял в своё время Git в одной крупной it-конторе
                                                              +1
                                                              Сколько уже этой фраз лет отбиваются поклонники Git от простой истины:
                                                              «В Git не хранится история commit'a, а поэтому это сложный в работе интсрумент»

                                                              Результатом этого мы можем взглянуть на множество примеров известных продуктов. Там просто не сливают ветки, что бы можно было нормально работать. Они одни и те же изменения копируют из ветки в ветку и делают commit.
                                                              Ну к примеру PostgreSQL: github.com/postgres/postgres/network
                                                              Или каждый commit подписывают в комментарии, к какой «named branch» он относится, к примеру ядро линукса.

                                                              Я прежде чем составить свое мнение о работе изучил около сотни репозиториев известных больших продуктов. Результат один: история, в какой ветке был создан commit — необходима. В Hg она есть и ничего «эмулировать» там не надо.
                                                                0
                                                                Это всего лишь ваши личные предпочтения по ведению кода.
                                                                  0
                                                                  Что значит мои предпочтения?! Это исследование репозитариев всеми известных больших проектов.
                                                                  Ссылки и направления куда копать, я вам дал — убедитесь сами.
                                                                    0
                                                                    Потому что вы сделали вывод. Или его за вас сделал кто-то другой? Нужна информация о том, что делает коммит, а как это достигается: описанием или ссылкой на ветку — вопрос десятый.
                                                                      0
                                                                      Вы собираете проекты из веток или просто делаете push/pull?
                                                                        0
                                                                        Я не собирал, этим, как полагается, занимаются релиз-инженеры.
                                                            0
                                                            Гугл подсказывает, что можно даже проще, всего лишь настроить конфиг:
                                                            git config --global push.default current

                                                            Да, вы сами ответили положительно на моё утверждение. Без google с git очень тяжело работать.
                                                            И тот же .gin/config не так уж и по настраиваешь по памяти, не потратив времени на освежение памяти из доков по разделам remote и branch
                                                              0
                                                              Без google с git очень тяжело работать.
                                                              Не только с git, а с Hg тоже. Более того, имея Гугл с гитом работать можно, а с Hg нельзя.
                                                                0
                                                                Я больше скажу — с гитом можно работать только имея гугл (или гуру) под рукой (http://stackoverflow.com/questions/tagged/git?sort=votes как бы недвусмысленно подтверждаэ). Хотя казалось бы — почитай манов, и вперёд. Что характерно, этот же подход вполне себе срабатывает в случае mercurial (отчего, собссно, его и не видно в гугле).
                                                                  0
                                                                  Я именно это и сказал.
                                                                  0
                                                                  c Hg не нужен Google.
                                                                  Один раз ознакомившись, ты уже не разучишься, как на велосипеде — вот в чем прелесть.
                                                                  У меня команда, которая больше года работала с GIT и которая в должной мере не могла его осилить при всех попытках, пересела на Hg за 2 дня и начала успешно работать. Спустя неделю, ребята уже каждый под себя TortouseHg заточил с custom visual diff tools.
                                                                    –1
                                                                    Ключевые слова: «больше года работала с GIT». Таки осилили, вы просто предвзяты.
                                                                      0
                                                                      Если не менять workflow, то «работать» можно и десять лет. А «асилел» или нет, на самом деле выясняется, когда workflow приходится править.
                                                                        0
                                                                        И мартышку можно научить делать последовательность комманд.

                                                                        Вот пример, который был недавно. Тестировщик.
                                                                        По бумажке работал с Git. Выливал изменения в основную ветку, после тестирования их в своей ветке, таким образом, что бы тестовые изменения в эту ветку не попали.
                                                                        В Hg он выбросил инструкцию спустя два дня. Хотя до этого, бумажка с последовательностью команд Git у него висела очень долго.

                                                                        Показатель?
                                                                        Если нет, тогда мы совсем по разному с вами глядим на этот мир.
                                                                          0
                                                                          Просто надо было настроить свой рабочий инструмент. Не все это сразу делают. С Hg это и произошло.
                                                                            0
                                                                            Как именно следует настроить git, чтобы выбросить шпаргалку через два дня?
                                                                              0
                                                                              В зависимости от того, что делается. У меня вообще были алиасы из одной буквы: p — git pull, u — git push и пр.
                                                            0
                                                            да, кстати, если не согласны с каким пунктом — отпишитесь. А то как то не понятно, где я заблуждаюсь.
                                                          0
                                                          Есть у них rebase, использовать только не принято. Нет push -f и push --delete, но статья не о том.
                                                            0
                                                            Точнее, push -f не удалит никаких изменений.
                                                              +1
                                                              rebase в Hg можно подключить, но по умолчанию это расширение не подключено.
                                                              0
                                                              у них идеологически нет команды rebase
                                                              ложь. изучите матчасть. Hint: hg help extensions, раздел «disabled extensions»
                                                                0
                                                                да, мне уже заметили комментарием выше, что я погорячился с отсутствием команды rebase. Только это не отменяет того факта, что она практически не используется в mercurial — ну и по умолчанию она выключена как вы сами заметили.
                                                                А изучать матчасть этой команды нет никакого желания (и без нее я вполне обхожусь), но спасибо за предложение.
                                                                  0
                                                                  это не отменяет того факта, что она практически не используется в mercurial
                                                                  а) откуда у вас эта информация?
                                                                  б) если бы это было действительно так, с чего бы класть этот плагин в коробку?
                                                                  изучать матчасть этой команды нет никакого желания
                                                                  не сомневаюсь. но иметь полное представление о возможностях используемого инструмента иногда бывает полезно.
                                                                    0
                                                                    если бы это было действительно так, с чего бы класть этот плагин в коробку?

                                                                    я полагаю — для удобства людям которые ранее использовали git и считают подмену истории в системе контроля версий нечто само собой разумеющимся.
                                                                      +1
                                                                      б) если бы это было действительно так, с чего бы класть этот плагин в коробку?

                                                                      Rebase — это расширение и по умолчанию отключено, а merge находится в ядре.
                                                                  0
                                                                  Команды rebase нет наверное ни в какой другой системе контроля версий. Это подчеркивает, насколько развит git и насколько у него большая community, что в нем реализованы *специальные* возможности для *специальных* целей, которые другим системам и не снились. Конечно же, Капитан подсказывает, что всем подряд использовать специальные возможности ни к чему.
                                                                    0
                                                                    Команды rebase нет наверное ни в какой другой системе контроля версий
                                                                    Есть. Точно есть.
                                                                      0
                                                                      Напишите в какой, я после того, как освоил git, за другими пристально не слежу, но быть в курсе эволюции всей области хочется.

                                                                      Собственно, я по-моему слышал о rebase-плагине для bazaar, но плагин это не совсем то… Когда мне нужен будет rebase для bazaar (что иногда случается), я не побегу искать плагин, а матернусь и с'merge'у. (А merge'ы у bzr особо плохие по сравнению с git'ом, они фактически squash'ат по-умолчанию, докопаться по внутренней истории можно, но нужно давать дополнительные ключи в bzr log -p и т.д.; итог: по практичности далеко до git'а).
                                                                        +1
                                                                        У mercurial это стандартное дополнение (т.е. присутствует сразу после установки, но отключено). Если напишете hg rebase, не включив его, то получите
                                                                        hg: неизвестная команда 'rebase'
                                                                        'rebase' предоставляется следующим расширением:
                                                                        
                                                                            rebase        команда для перемещения наборов ревизий к другому предку
                                                                        
                                                                        наберите "hg help extensions" для справки по включению расширений
                                                                        .
                                                                          0
                                                                          Nice! Не знаете, много ли пользователей hg включают и используют его? С одной стороны, логика не включения — это advanced'нутая фишка, и ее неразумное использование приводит к примерам, как в этой статье. С другой стороны, это advanced'нутая фишка, и требуется много глаз и рук, чтобы сделать ее реально пригодной и удобной в использовании.

                                                                          Я помню как rebase в git был весьма нервотрепным делом. Собственно, и сейчас там есть неочевидные моменты (например, если какой-то патч уже в upstream'е, то может выйти конфликт, после резолюции которого будут нулевые изменения в рабочей копии, которые соответственно нельзя за'add'ить в индекс, а значит нельзя сделать rebase --continue; нужно знать, что в это момент нужно дать rebase --skip).
                                                                            0
                                                                            много ли пользователей hg включают и используют его?
                                                                            Непонятно, какое это имеет значение. Кому надо rebase, тот его ищет и моментально находит. Кому не надо, не ищет и соответственно не находит.
                                                                            требуется много глаз и рук, чтобы сделать ее реально пригодной и удобной в использовании
                                                                            Если «удобной и пригодной» == «один в один как в git, который rebase изобрёл и вообще родина слонов», то нет, не требуется. Ну и да, rebase — детерминированная операция, поэтому простора для творчества тут немного.
                                                                            если какой-то патч уже в upstream'е, то может выйти конфликт
                                                                            В то время, как mercurial уже второй год умеет отслеживать, опубликован ли changeset, пользователи git по-прежнему записывают на бумажке хэши коммитов, которые нельзя трогать, чтобы не сломать историю. Прекрасный пример и гибкости, и развитости, и практичности.
                                                                              0
                                                                              А почему «записывают на бумажке хэши» без пруфлинка? :-E

                                                                              > Если «удобной и пригодной» == «один в один как в git»

                                                                              Нет, это имеющей как можно более простой процесс применения и с возможно меньшим количество corner cases. Ну и en.wikipedia.org/wiki/Principle_of_least_astonishment. git в этом не идеален, конкретный пример я привел — когда должен был бы работать rebase --continue, «почему то» требуется rebase --skip (детали почему простым пользователям не интересны).

                                                                              > Ну и да, rebase — детерминированная операция

                                                                              Статья выше аргументирует, что нет.

                                                                              Спасибо за ссылку на Phases, рад знать, что фичи hg развиваются. Уверен, что тот, кому нужно маркировать коммиты как public/draft/secret его сразу находит и использует. Увы, в mercurial достаточно своих некрасивостей и нурешений принципа least user surprise…
                                                                                0
                                                                                почему «записывают на бумажке хэши» без пруфлинка?
                                                                                какой пруфлинк? То, что git никак не помечает, выпинан ли коммит куда-нибудь или нет — это факт. В итоге пользователь вынужден выяснять, какие коммиты уже опубликованы и запоминать, что менять их нельзя.
                                                                                с возможно меньшим количество corner cases
                                                                                а разве --interactive не добавляет corner cases в rebase?
                                                                                Уверен, что тот, кому нужно маркировать коммиты как public/draft/secret его сразу находит и использует
                                                                                Не тот. Коммиты помечаются как public автоматически при pushе их в другой (точнее, publishing) репозиторий. А вот secret phase действительно является тем, что нужно искать специально.
                                                                                  0
                                                                                  > какой пруфлинк?

                                                                                  Это была ирония на вашу иронию. Просто вы дали три ссылки подряд, какой hg хороший, что можно было подумать, что про «на бумажке» тоже прям из какого-то man git скопировано ;-).

                                                                                  > То, что git никак не помечает, выпинан ли коммит куда-нибудь или нет

                                                                                  Вы явно что-то путаете. Это SVN никак не помечал (и то в 2.0 или около исправили), был ли коммит смержен, например при мерже одной и той же ветки дважды вылезут конфликты. git разумеется ведет историю merge'ей и все работает, как надо.

                                                                                  Это не относится к rebase, потому что rebase работает не на уровне истории основной ветки, а на уровне последовательности отдельных патчей в нашей ветке. Наши коммиты попросту применяются один за другим к *совершенно новой истории upstream'а*, и либо применяется, либо patch «видит», что он уже применен (тогда из нашей ветки этот патч уходит), либо есть конфликт (и пользователь исправляет). Автор этой статьи вот нашел, как подстроить конфликт, который patch git'а не заметил. Кулхацкер. Итог, при rebase'е нечего «записывать», кроме самих патчей, что git делает неплохо, но поскольку patch — штука эвристическая, то ошибиться может.

                                                                                  > а разве --interactive не добавляет corner cases в rebase?

                                                                                  Дай бог многим системам такого пользовательского интерфейса, как в git rebase --interactive. Все в вашем любимом текстовом редакторе, помощь перед глазами, все весьма очевидно — хочешь переставить коммиты — переставь строки в редакторе. Я никогда не пользуюсь git merge --squash — зачем мне помнить об этом corner case'е, если git rebase --interactive позволяет добиться и его эффекта, и многих других.
                                                                                    0
                                                                                    Это SVN никак не помечал (и то в 2.0 или около исправили), был ли коммит смержен
                                                                                    тысяча чертей, merged ≠ pushed же
                                                                                  +2
                                                                                  Сейчас в mercurial пилят changeset obsolescense: хотя эта возможность и предполагается как замена MQ, я в первую очередь вижу в ней возможность полностью безопасного изменения истории (в репозитории остаются все изменения, просто при переписывании mercurial указывает, что данное изменение является obsolete, указывает, что данное изменение является заменой другого (или наоборот, указывает, какое изменение является заменой данного — не узнавал, в метаданных какого изменения всё это сохраняется), а также по‐умолчанию отдаёт только не‐obsolete изменения (дополнительно скрывая уже имеющиеся)).

                                                                                  Есть и дополнение, автоматическим образом разрешающее часть проблем вроде «изменение в вашем репозитории имеет obsolete предка» и д.р. Поищите «mercurial changeset obsolescense». То есть, теперь уже «mercurial changeset evolution».
                                                                                    +1
                                                                                    Такого рода изменения, кстати, хорошо показывают, у кого лучше архитектура. Я лично не знаю ни одного примера добавления возможности в, так сказать, ядро git с самого момента начала его мною использования. В Mercurial же спокойно добавляют largefiles, phases и changeset evolution, да ещё и без проблем с совместимостью.

                                                                                    Не говоря уже о том, что рабочий прототип на Python с использованием довольно неплохого внутреннего API (позволяющего в т.ч. изменять поведение встроенных команд), написать гораздо легче, чем тот же прототип для git на C без специальной поддерки изменения поведения команд со стороны уже имеющегося кода.
                                                                                      +2
                                                                                      Кстати, в случае с mercurial с или без changeset evolution тот, кто делал rebase, мог бы восстановить контекст и объяснить действия Василия (с changeset evolution это мог бы дополнительно сделать любой, кто сделал pull до rebase; правда требуется либо настройка сервера, чтобы он не считал находящиеся на нём изменения публичными, либо принудительное выставление фаз администратором на сервере и rebase его же силами). Без changeset evolution rebase делает резервные копии удаляемых изменений в .hg/strip-backup, с — просто оставляет их в репозитории (никакого автоматического gc!). Git же оставляет эти резервные копии на милость своего gc.
                                                                            0
                                                                            Ах, да, и еще, под «rebase в git» и «нет ни в какой другой системе», я понимаю так же и rebase --interactive, т.е. не просто перекинуть «свой» блок коммитов на (новый) верх «чужой ветки», а вообще легко и удобно переписывать историю.
                                                                              +2
                                                                              И это есть. Другое дело, что в mercurial такое действие предлагается проделать двумя командами: есть просто rebase и histedit, который может перетасовать/убрать изменения как rebase -i, но не перенести их в другую ветку.
                                                                      0
                                                                      еще можно делать git merge --squash, получается что все одним коммитом и в истории красота
                                                                        +2
                                                                        Спасибо автору за хороший пример. Хочу еще раз отметить, что ошибка возникает и в том и другом случае, просто в случае с rebase сложнее понять историю и контекст ее внесения.

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

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

                                                                        У нас в проекте сейчас используется стратегия rebase (+squash), что позволяет держать историю коммитов красивой, компактной и почти линейной. Проект не очень большой, и ошибки такого рода у нас возникают очень редко (если вообще возникают), благодаря изолированности изменений (как правило разные разработчики редко правят одни и те же файлы) и тестам. Ну а если вдруг возникают — то у нас это не повод кого-то увольнять, а повод покрыть этот код тестом и исправить ошибку. Причина появления ошибки вторична.

                                                                        Выбор, конечно, должен быть осознанным. Но ведь как чертовски хорошо, что Git нам дает право на этот выбор!

                                                                        Ваш КО.
                                                                          –1
                                                                          К сожалению(к счастью?) пример не корректный. Выше я описал почему.
                                                                            +1
                                                                            Прочитал выше — не понимаю, что конкретно не корректно. Я специально проверил прежде чем писать комментарий. Все получилось как у автора, конфликта при rebase не было, а ошибка в итоге появилась. Пробовал именно такой сценарий, который используеся у нас (и не только, он довольно стандартен). Опишу подробнее по шагам, чтобы прояснить:

                                                                            1. Есть master в котором есть файл с таким содержимым:

                                                                            сумма
                                                                            2
                                                                            и
                                                                            2
                                                                            равна
                                                                            4

                                                                            2. Есть 2 разработчика, каждый создает свой бранч (feature1, feature2)
                                                                            3. В feature1 вносится изменение: слово «сумма» меняется на «произведение». Коммитит.
                                                                            4. feature1 мержится в мастер (не важно через pull request или нет)
                                                                            5. В feature2, другой разработчик меняет «2» и «4» на «3» и «5» соответсвенно. (У него по-прежнему «сумма», а не «произведение», потому код верный). Коммитит.
                                                                            6. В feature2 делается git rebase master. Тут rebase проходит автоматически, конфликта НЕ возникает, в коде появляется ошибка, как описал автор.
                                                                            7. feature2 мержится в мастер. В результате ошибка оказывается в мастере.

                                                                            Еще раз хочу отметить, что при merge ошибка точно также возникнет. Но как справедливо заметил автор, по истории git-а в случае merge будет легче разобраться как и почему так получилось. Вроде об этом и статья.
                                                                              –1
                                                                              Ну по сути ребейз здесь приянут за уши. Все что вы делеаете это переносите патч в другую ветку. Сооственно без какой либо проверки, и да он проходит. Я еще не встречал что бы кто то так пользовался ребэйзом, но так тоже можно делать. Если делать по нормальному, пример скрипта выше, то этой проблемы не будет, так как будет конфликт.

                                                                              Если коротко то сейчас это выглядит так:
                                                                              1. есть код в котором последнее состояние: 2*2=4
                                                                              2. есть патч который заменяет 2 и 4 на 3 и 5
                                                                              3. если такой патч применить, он сооствественно пройдет без конфликтов, и результат будет 2*3=5

                                                                              И это не потому что ребэйз плохой, это потому что им изначально не верно воспользовались + неверное описание комитов.
                                                                                0
                                                                                В вашем примере скрипта делается абсолютно то же самое, только формат записи не такой, как у меня. Посмотрите внимательней.
                                                                                  0
                                                                                  Почему не такой? Все тоже самое в столбик, только нету слов сумма и произведение, вот добавил и их, ничего не изменилось:
                                                                                  Обновленный скрипт
                                                                                  git init
                                                                                  touch test.txt
                                                                                  
                                                                                  echo -e "сумма\n2\n+\n2\n=\n4" > test.txt
                                                                                  git add test.txt
                                                                                  git commit -m "2+2=4"
                                                                                  
                                                                                  git checkout -b my
                                                                                  echo -e "сумма\n2\n+\n3\n=\n5" > test.txt
                                                                                  git add test.txt
                                                                                  git commit -m "2+3=5"
                                                                                  
                                                                                  git checkout master
                                                                                  echo -e "произведение\n2\n*\n2\n=\n4" > test.txt
                                                                                  git add test.txt
                                                                                  git commit -m "2*2=4"
                                                                                  
                                                                                  git checkout my
                                                                                  git rebase master
                                                                                  

                                                                                    0
                                                                                    «сумма\n2\n+\n2\n=\n4» != «сумма\n2\nи\n2\n=\n4»
                                                                                    Я специально подбирал формат записи такой, чтоб конфликтов не было.
                                                                                      0
                                                                                      Не поленился, подправил ваш скрипт, и запустил. Конфликтов нет, всё как в статье.
                                                                                      Исправленный скрипт
                                                                                      git init
                                                                                      touch test.txt
                                                                                      
                                                                                      echo -e "сумма\n2\nи\n2\n=\n4" > test.txt
                                                                                      git add test.txt
                                                                                      git commit -m "2+2=4"
                                                                                      
                                                                                      git checkout -b my
                                                                                      echo -e "сумма\n2\nи\n3\n=\n5" > test.txt
                                                                                      git add test.txt
                                                                                      git commit -m "2+3=5"
                                                                                      
                                                                                      git checkout master
                                                                                      echo -e "произведение\n2\nи\n2\n=\n4" > test.txt
                                                                                      git add test.txt
                                                                                      git commit -m "2*2=4"
                                                                                      
                                                                                      git checkout my
                                                                                      git rebase master
                                                                                      

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

                                                                                        Как вы видите, всего один символ и у нас выкидывает конфликт.
                                                                                        Но мораль rebase vs merge ясна, спасибо за терпеливость и помощь с форматом! :)
                                                                                          +1
                                                                                          Я бы не стал утверждать, что вероятность мала. На практике изменения Пети и Васи будут разделены не 1 символом, а десятками строк, а скорее и вообще в разных файлах будут. И конфликта скорее всего также не будет.
                                                                                          У меня прям сейчас открыт репозиторий, в котором однозначно при rebase вместо merge была бы масса «битых» ревизий.
                                                                                          Некрасивая история при merge — это конечно аргумент. Только возникает вопрос на подумать. Что мы хотим от истории: достоверности и информативности или красоты?
                                                                                          Кстати, cherry-pick коммитов при merge — совсем не сложное дело, если коммиты сгруппированы в отдельные законченные понятные ветки: берешь все коммиты ветки и переносишь. А с rebase надо ещё разобраться, с какого коммита нужная функциональность начинается, и на каком заканчивается.
                                                                                            0
                                                                                            Имел ввиду, перенос патчей на полностью новое дерево, ни как не связанное с текущим репозиторием. Вероятность такого события где то равна проблеме с ребэйзом.

                                                                                            > А с rebase надо ещё разобраться, с какого коммита нужная функциональность начинается, и на каком заканчивается.
                                                                                            Обычно в комитах есть номера тикетов, к чему относится та или иная фича/баг, поиск не вызывает особых проблем. Кстати что происходит, когда замерженную фичу надо обновить по каким либо причинам?
                                                                                              0
                                                                                              Открывается ветка с тем же именем, выполняются коммиты, ветка вливается в master (или куда принято). Всё то же самое, что и при rebase, только коммиты останутся сгруппированы в отдельной небольшой ветке (фича целиком окажется в 2 ветках: основной и дополнительной).
                                                                                              Кстати, на сколько я понимаю, выборку коммитов, созданных в конкретной ветке, удобнее всего делать в Mercurial: там в коммите сохраняется имя ветки. Возможно пользователи этой DVCS расскажут подробнее.
                                                                                                0
                                                                                                Если вам надо просто отменить слияние, то вы просто откатываете (revert, ни в коем случае не прочие манипуляции с историей) изменение, в котором слияние было произведено (если, конечно, первый родитель правильный: если делать слияние feature -> master, а не наоборот с последующим fast-forward merge. Документация предостерегает, что при повторном слиянии надо сначала откатить изменение с предыдущим откатом изменений и только затем делать повторное слияние).

                                                                                                С Mercurial вы действительно можете узнать, какой ветке принадлежало изменение. А можете и не узнать, если вместо веток использовались закладки (с некоторыми оговорками — то же, что и ветки в Git). Или отдельные каталоги вместо веток. Или программист поленился задать имя ветки (одна ветка с двумя головами — нормальная ситуация, иногда удобно). В общем, зависит от степени разгильдяйства программистов и мер защиты от оного. Как правило, сделать выборку действительно легче.

                                                                                                Для Git где‐то вроде лежит сложный скрипт на perl, который делает то же самое, с некоторой вероятностью даже давая верный результат. При использовании модели git flow при отсутствии отклонений от неё особых проблем с определением ветки не возникает.
                                                                                                  0
                                                                                                  Спасибо.
                                                                                                  Вообще, отмена слияний в git дело не хитрое, главное понять принцип. Вот кстати, хорошая статья об этом, может кому пригодится.
                                                                                                  С Mercurial вы действительно можете узнать, какой ветке принадлежало изменение. А можете и не узнать, если вместо веток использовались закладки (с некоторыми оговорками — то же, что и ветки в Git). Или отдельные каталоги вместо веток.

                                                                                                  Хм. Есть всё-таки что-то пугающее в этом зоопарке видов веток, — он всегда меня останавливал, когда я думал на досуге изучить Mercurial.
                                                                                                  При использовании модели git flow при отсутствии отклонений от неё особых проблем с определением ветки не возникает.

                                                                                                  Да, простой поиск по commit message выдаст все merge-коммиты нужной ветки. Я просто предполагал, что в Mercurial это может быть изящнее.
                                                                                                  Например, при задаче: в репозиторий Foo сделать cherry-pick всех коммитов ветки feature из репозитория Bar. В git нужно будет отобрать нужные последовательности коммитов, и для каждой сделать cherry-pick. А в Mercurial?
                                                                                                    +1
                                                                                                    Например, при задаче: в репозиторий Foo сделать cherry-pick всех коммитов ветки feature из репозитория Bar. В git нужно будет отобрать нужные последовательности коммитов, и для каждой сделать cherry-pick. А в Mercurial?
                                                                                                    И в git, и в mercurial можно скормить команде cherry-pick (git) или transplant (mercurial, находится в одном из стандартных расширений) диапазон. В mercurial вместо диапазона можно написать что‐нибудь посложнее. hg transplant -b {branch name} или hg rebase --keep --source {branch name} пересадит ветку. То же самое может сделать hg transplant 'branch(branch name)', но я не знаю, как всё это работает с уже применёнными изменениями. hg transplant отказывается пересаживать родителя текущего изменения, git cherry-pick не смущается, даже если его попросить пересадить HEAD. hg rebase -r {revisions}, кстати, тоже работает, только отказывается если ревизии не связаны.

                                                                                                    Несколько более сложный пример: взять все ревизии из ветки foo, вносившие изменение в файл bar: hg transplant 'branch(foo) and file(bar)'.
                                                                                                      0
                                                                                                      Хорошие примеры, спасибо!
                                                                                                        0
                                                                                                        * В первом примере с rebase не --source, а --base. В отличие от --source, делает то же, что и git rebase.
                                                                                                          +1
                                                                                                          hg graft же (в ядре, начиная с Mercurial v2.0)
                                                                                                            0
                                                                                                            Можно и так. Только transplant — хорошее, запоминающееся имя (т.к. заимствованные слова на его базе всё время на слуху), а graft я как несколько раз видел, так и не запомнил. Судя по словарю является медицинским и садоводческим термином. И с двумя разговорными вариантами, не имеющими к цели команды отношения, — взятка/взяточничество и (брит.) работа. Кальк и заимствований на основе graft я ни разу не слышал, само слово без контекста «есть такая команда в Mercurial» — тоже.
                                                                                            +1
                                                                                            забавно.
                                                                                            Вот такой
                                                                                            git init
                                                                                            
                                                                                            echo -e "2\n+\n2\n=\n4" > test.txt
                                                                                            git add test.txt
                                                                                            git commit -m "2+2=4"
                                                                                            
                                                                                            git checkout -b my
                                                                                            echo -e "2\n+\n3\n=\n5" > test.txt
                                                                                            git add test.txt
                                                                                            git commit -m "2+3=5"
                                                                                            
                                                                                            git checkout master
                                                                                            echo -e "2\n*\n2\n=\n4" > test.txt
                                                                                            git add test.txt
                                                                                            git commit -m "2*2=4"
                                                                                            
                                                                                            git checkout my
                                                                                            git rebase master
                                                                                            


                                                                                            скрипт приводит к конфликту, а вот такой

                                                                                            git init
                                                                                            
                                                                                            echo -e "+\n2\n2\n=\n4" > test.txt
                                                                                            git add test.txt
                                                                                            git commit -m "2+2=4"
                                                                                            
                                                                                            git checkout -b my
                                                                                            echo -e "+\n2\n3\n=\n5" > test.txt
                                                                                            git add test.txt
                                                                                            git commit -m "2+3=5"
                                                                                            
                                                                                            git checkout master
                                                                                            echo -e "*\n2\n2\n=\n4" > test.txt
                                                                                            git add test.txt
                                                                                            git commit -m "2*2=4"
                                                                                            
                                                                                            git checkout my
                                                                                            git rebase master
                                                                                            


                                                                                            нет. Подозреваю, что что-то нечисто с правилами автомерджа. Я всегда косо смотрел на его принципиальную осуществимость. Строчки строчками, а без контекста всё равно никак.
                                                                                              0
                                                                                              Всё верно. При префиксной нотации конфликта нет, я просто записал её словами.

                                                                                              На мой взгляд, никаких проблем с правилами мерджа нет.
                                                                                              В первом случае перед гитом стоит задача «найди строку „2“ между „+“ и „=“ и замени её на „3“», и не может её выполнить, т.к. нужные строки выглядят как «2,*,2,=,4» (вместо ожидаемого "+" стоит "*").
                                                                                              А во втором — «найди строку „2“ между „2“ и „=“ и замени её на „3“», и успешно её решает, т.к. строки выглядят как "*,2,2,=,4".
                                                                                              «4» на «5» меняется в обоих случаях без конфликта.
                                                                                                +1
                                                                                                честно говоря, не вижу никакого оправдания такой дискриминации польской нотации (или такого фаворитизма инфиксной).
                                                                                                Не сочтите за пеар, написал вот тут свои выводы о.
                                                                                                  0
                                                                                                  ну т.е. технически вы правы — проблем с правилами мерджа нет, они едины. Однако то, что они выполняют сематически эквивалентную замену в одном случае и не выполняют в другом — общая и вобщем нерешаемая проблема, которая отлично проиллюстрирована вашим примером.
                                                                                                    0
                                                                                                    Вообще, можно написать стратегию слияний, игнорирующую различные строки вокруг изменяемой, чтобы конфликт выдавался только если одна и та же строка была изменена в обеих ветках. Тогда конфликта не будет в обоих случаях.
                                                                                                    Также как можно написать и стратегию, чтобы конфликты вылезали чаще, например всегда, когда изменен один и тот же файл.
                                                                                                    По моей субъективной оценке, обе эти крайности окажут скорее негативное влияние на эффективность разработки среднестатистического проекта, нежели позитивное. Нужен компромисс, например тот, что есть сейчас.
                                                                                            0
                                                                                            А вот и результирующая картинка дерева во время ребэйза, где видно и формат записи, и то что конфликт, и то что конфликт именно на тех местах где и должен быть:

                                                                                            0
                                                                                            На мой взгляд, вы торопитесь с выводами, говоря что тут rebase притянут за уши, и что мы им не правильно пользуемся. Описанный мной сценарий довольно популярен, и является рекомендованным, например, при разработке Ruby on Rails.

                                                                                            Если представить, что оба разработчика из моего примера не являются core members и не могут пушить в мастер, а только шлют пулл реквесты и при этом соблюдают рельсовый contribution guide, то именно так в жизни это и будет выглядеть. Шаги 4 и 7 будут выполнены через пулл реквесты.

                                                                                            Посмотрите, пожалуйста, внимательнее. Тут совсем не «Все что вы делаете это переносите патч в другую ветку». Тут классическая история, когда во время разработки feature2, мастер (естественно) ушел вперед. Поэтому чтобы влить feature2 назад в master, мы делаем сначала rebase, тем самым записывая изменения произведенные в feature2 поверх уже нового мастера. После этого шлем pull request (ну или мержим feature2 в мастер сами).
                                                                                              0
                                                                                              Это как раз пример того, что патч уже устарел. И если будет ревью, то в патче должы будут отказать и отправить назад на доработку.
                                                                                                0
                                                                                                Что значит «как раз»? Этот пример и был изначально. «Патч» устарел, именно поэтому и делается rebase. После этого (если тесты проходят), о какой еще доработке идет речь? Да, возможно, будет ревью, но такая ошибка легко может быть не замечена при ревью и попадет в мастер.
                                                                                      0
                                                                                      Очень интересный пример. Не думал о такой возможности. Спасибо! :-)

                                                                                      Only users with full accounts can post comments. Log in, please.