Pull to refresh

Comments 91

Очень предвзятый взгляд на --no-ff, не помню случая чтобы он мешал бисектить и находить коммит который поломал бы релиз… вобщем очень спорная статья…
Местами аргументация автора мне тоже не очень ясна, но что можно иметь против лаконичной и прямолинейной публичной истории?
А что именно в ней должно привлекать? Если мержи сделаны с помощью --no-ff вы в любой момент можете открыть gitk и увидеть что вот — эта фича началась вот тут, закончилась вот тут, не читая описание к каждому коммиту.

Что касается лаконичности, то если лаконичность это синоним «давайте уместим фичу в три гигантских коммита», то я определенно против. Когда я делаю ревью кода, я люблю смотреть маленькие, аккуратные диффы, а не на простыню на десятки экранов.

вот и я за --no-ff история выглядит красиво и наглядно и нет кучи непонятных ветвлений непонятно где начинающихся и непонятно куда уходящих.
Так, насколько я понимаю, люди вообще против ветвлений. Они хотят историю прямую как стрела.
Что касается лаконичности, то если лаконичность это синоним «давайте уместим фичу в три гигантских коммита», то я определенно против.

Для меня лаконичность это синоним скорее «давайте не будем хранить в истории основных веток коммиты с исправлением „helo“ на „hello“.
я наоборот когда замечаю опечатку в процессе правки бага или ее отдельным коммитом пправлю или в рамках бранча dev_cleanup так же отдельным коммитом.
Может мы про разные опечатки? Я про ситуацию типа:
— что-то написал, закоммитил и запушил (по хуку на пуш ушло на дев-сервер)
— посмотрел на дев-сервере, заметил опечатку (не суть, синтаксическая ошибка или опечатка в строке)
— исправил, закоммитил и запушил (по хуку на пуш ушло на дев-сервер)
— посмотрел — всё ок
— смержил в продакшен ветку, закоммитил, запушил (по хуку ушло на продакшен сервер)

И вот в продакшен ветке будет два коммита с разницей в пару минут, причём второй коммит — исправление одного символа. Нелаконично.
а… ну да если косяк в рамках бранча я его сквошу
если найдена случайно опечатка из чего то тревнего то я не правлю «заодно» а выношу отдельным коммитом. чтобы мух от котлет отделять.
Я вот как раз мотивирую всех делать вот такие мелкие фиксы в отдельных коммитах.
Потому что иногда бывает, что в коммит содержит какое-то важное и нетривиальное изменение на пять строк. Ну и плюс человек, чтобы не плодить коммиты в нем же сделал какое-то «мелкое и неважное изменение» — типа убрал пробелы перед концами строк в половине строк файла.

В результате в этом важном и нетривиальном диффе сам черт ногу сломит. И, если это важное изменение не заработает, то при откате коммита получим еще и откат кучи мелочей.

Коммит должен быть маленьким, по возможности атомарным и в нем должно быть то, и только то, о чем написано в комментарии этого коммита. Это очень упрощает жизнь.
Это-то да. Но вот если написал эти пять строк, закоммитил и обнаружил в ней ошибку, просто опечатку. Пускай из-за неё на билд-сервере проект не собирается. То есть коммит составляет логическое целое с предыдущим.
Представим опенсорсный проект. Реализовано 10 фич, все они слиты в master. В каждой фиче было по 10 промежуточных коммитов. Открываем gitk или github и лицезреем паутину из 100 коммитов.
Не лучше ли было бы увидеть линейную историю из 10-20 коммитов?
И нет, я не предлагаю фичи в 10 килострок умещать в один коммит, все должно быть разумно.
хотите пример приведу
github.com/MidnightCommander/mc/network
если полистать влево, то видно как бранчи были влиты с --no-ff в мастер.
где то от 20 марта и далее посмотрите на коммиты…
Если делать ребейз перед слиянием фич в мастер, а потом merge с --no-ff, то никакой паутины не будет.

На самом деле я двумя руками за правку истории перед сливанием и публикацией. Правда я считаю что маленькие коммиты и --no-ff это добро. Часто, я в процессе rebase -i, наоборот разбиваю коммиты на несколько мелких.
спасибо, давно хотелось почитать поподробнее на русском!
Как-то нелогично, лучше ведь узнать в каком микрокоммите произошёл фейл, чем узнать что он просто произошёл. Да и если уж так заморачиваться с тем, чтоб иметь возможность собрать любую ревизию, то есть два пути: коммитить всё в транк, потом сливать с master, либо ставить теги на стабильные версии кода.
Промежуточные рабочие микрокоммиты не обязаны даже компилироваться, не говоря уже о какой-то функциональности.
Затем в один прекрасный день вы обнаруживаете критичный баг в продакшене и вам требуется отследить момент, когда он появился. Вы запускаете bisect, но постоянно попадаете на промежуточные коммиты. Вы сдаетесь и ищете руками.

Может, просто, перейти на Mercurial?
Вы точно знаете какой коммит относится к какой ветке.
Если разработка идет фича-ветка, то таких проблем — просто не будет.

Я серьёзно, не холивара ради. Если ошибаюсь в этом мнении, то буду рад услышать — почему?
Вопрос ведь не в том из какой подветки коммит, а в том как быстро найти сам коммит.
Я так понимаю, вопрос в том, как вообще найти feature, которая все сломала.
Т.к. промежуточный commit не дает представления о том, что в данном месте происходит.
Ну и статья посвящена тому, что в git это сделать не совсем уж тривиально.
Зачем искать фичу, которая всё сломала? Имхо, нужно искать как раз коммит. Там есть commit message, поясняющий изменение; там есть автор, которого можно спросить.
Кстати, да. Когда микрокоммиты потóм начинают подчищать, то теряется изложенное (в комментарии к коммиту) представление о том, чего хотел автор.

Пример из жизни: если четыре коммита из изложенного по адресу https://github.com/CloudMade/Leaflet/pull/586 запроса на слияние будут слиты в один, то может быть не понятен ряд его нюансов, тем более что каждый из двух последних коммитов является ответом на конкретную реплику в обсуждении, по адресу https://github.com/CloudMade/Leaflet/issues/582 расположенном.
Используем на основном проекте GIT.
Автор сделал merge в master ветку.
Через 4 часа обнаружилось, что один из модулей вернулся к доисторическому состоянию.
Даже он не смог объяснить, что за факап произошел.
Сидели и восстанавливали целый день реп и выполненную большую задачу(несколько задач).

Так что, вот жизненный use-case, когда зная автора проблеме не поможет.

p.s.
commitы мы конечно же нашли. Но вычленить их из различных фич мы не смогли, ибо авторы периодически делали pull из masterа и дерево было похоже на лабиринт.
Что мешало откатить этот merge commit? Или вообще всю ветку срезетить на предыдущее состояние?

А вообще, кривые руки (несанкционированный merge ветки в мастер, «дерево было похоже на лабиринт») на любом проекте с любыми инструментами могут привести к печальным последствиям. ;)
Ничего не мешало.
Просто не получилось. Откатили и все пошло наперекосяк.

А что значит срезетить всю ветку на предыдущее состояние?

Дерево в любой момент у нас похоже на лабиринт. У вас разве нет, вы все время делаете rebase?

К тому же, я привел этот пример про автора, которого можно спросить.

В свое время, была похожая ситуация с другим проектом, который велся на Mercurial. Там потратили на порядок меньше времени что бы найти и исключить ветку-фичу которая привела к серьёзной регрессии.
Что очень важно, необходимо вырезать именно фичу, т.к. багованная, она никому, не нужна в релизе.
«срезетить всю ветку на предыдущее состояние»:
1. Найти злостчастный merge commit.
2. Сделать git reset --hard <hash^> — резет ветки на последнее «хорошее» состояние.
3. Переприменить все полезные коммиты, сделанные после вредного. За 4 часа вряд ли что-то плохое могло случиться.
4. git push --force
У нас в проекте была такая ситуация. Вот таким образом и решили проблему, довольно быстро.

У нас дерево тоже далеко от идеала, но не подмёрдживая из мастера в feature branches, удаётся сохранять довольно понятную структуру. Честности ради, у нас просто мало кто пользуется feature branches, так бы обязательно бардак устроили ;)
В том посте точно такой же холивар разгорелся насчёт разного подхода к бранчам.
Вообще команды полезные. Позволяют многое автоматизировать. Но мне кажется, что для новичка они могут быть даже вредны, т.к., абстрагируясь некоторым образом от гитовской терминологии, не позволяют понять функционирование гита. И тогда, когда случается непредвиденная ситуация, люди впадают в панику.

Говорю это не понаслышке. У нас в компании большинство людей пользуются гит интеграцией с IDE, которая тоже многое позволяет делать, не думая. При это большинство этих людей с гитом на «вы». Поэтому когда случается что-то из ряда вон, то они зовут на помощь ;)
Я с вами совершенно согласен. Новичкам может навредить а вот ветеранам экономит время. Этот вопрос уже поднимался на Hacker News и даже в описании репозитория этого git-legit приведена цитата:

They haven't re-created the git CLI tool in a GUI, they've created something different. They've created a tool that makes Git more accessible. Little things like auto-stashing when you switch branches will confuse git veterans, but it will make Git much easier to grok for newcomers because of the assumptions it makes about your Git workflow.
Как видно цитата говорит об обратном. Мол новичкам так проще, и а ветеранов может запутать.
Но я думаю то что написал выше над цитатой — тоесть считаю что лучше учить гит как есть а те кто шарит могут и упростить себе всё.
Да. Я согласен с вами, но не с цитатой. Ветеранов ничем не запутаешь ;)
ИМХО, git создавался с вполне конкретными целями — для разработки ядра Linux. На мой взгляд, это достаточно специфическая задача, и заточка git под нее отразилась на удобство работы с ним в более широком круге задач. Когда распределенная по земному шару команда разработчиков клепает патчи к ядру — это одно. Когда разрабатывается новая версия Photoshop — это немного другое. На мой взгляд, отсутствие хорошей поддержки feature branches как в mercurial — это скорее минус.
Отсутствие хорошей поддержки feature branches? В Гите? Поясните мысль, пожалуйста. Бранчи считаются одной из самых сильных сторон Гита, поэтому боюсь, не вполне понял вашу мысль.
Feature branching — это такая техника, при которой мы делаем бранч для разработки сложной функциональности, которую больше дня пилить, и время от времени мерджим в нее транк чтобы работать с актуальным кодом и потом было обратно мерджиться проще. В гите коммиты не привязаны к веткам (тоесть ветка — это метка ее «последнего» коммита). Соответственно после того как мы нашу feature branch смерджим обратно в транк, при просмотре истории не будет информации о том, был ли какой-то changeset этой ветки разработан в рамках этой ветки или же был получени из транка в рамках актуализации этой ветки.
Если вы не сделаете rebase, то ветка (именно физическая ветка графа истории) никуда не денется и будет отлична видна в графе. Да и указатель на последний коммит этой ветки можно оставить, в виде бранча или в виде тега.

Подход Mercurial в этом смысле мне нравится куда меньше. Его heavyweight branches, записывающие информацию о ветке в каждый коммит, убивают идею быстрых и лёгких feature branches. Именно поэтому для feature branches в Mercurial часто используют букмарки или просто неименованные ветки. А это и есть аналог гитовых бранчей.

Преимущество у «тяжёлых» веток тоже есть, не спорю. Например, поиск бранча, в котором был сделан коммит, о чём вы говорили. Лично мне, впрочем, такая функциональность редко нужна.
Так что я бы не говорил об «отсутствии хорошей поддержки feature branches». Это просто другой подход. И тот факт, что в меркуриале изобретают велосипеды, чтобы достичь той же функциональности, говорит о преимуществах этого подхода.
Я не говорил, что информация о ветке теряется. Я говорил, что в случае актуализации feature branch путем мерджа в нее транка впоследствии теряется инормация о том, откуда взялся конкретный коммит — из транка или из ветки.
Для feature бранчей удобней merge --rebase. Тогда все остается простым и понятным (новые коммиты сверху).
Во-первых, rebase возможен только в тривиальных случаях. Если бранч делался две недели и идет последовательное изменение общего кода в транке и в бранче, то фиг там rebase получится. Во-вторых, хорошо, разделили мы последовательность коммитов на «до» и «после». Как это потом в истории смотреть? Вручную метки ставить? :)
Почему? Делается тот же merge, просто без сохранения истории. Все там получится, с любой сложностью.
Потому что если мы поменяли общий код, затем смерджили из транка изменения этого же общего кода, закоммитили результат мерджа, опять поменяли общий код, опять смерджили из транка изменения этого же кода — то тут важна последовательность когда мы этот код меняли а когда его меняли в транк. И последовательность изменений ветка-транк-ветка-транк нифига не тождественно равна последовательности изменений транк-транк-ветка-ветка, которая захочет получиться после rebase
Я несколько запутался в Вашем объяснении :( Если мы делаем full rebase, то мы имеем один коммит в нашей ветке, который выглядит как наши изменения примененные в мастере и так после после каждого reabase. Таким образом мы всегда создаём иллюзию всего лишь одного коммита. Т.е. как будто мы просто взяли патч и применили его к master. Какие тут могут быть проблемы? Если будут конфликты, тогда решаем их обычным механизмом. Т… е. этот процесс полностью идентичен merge
Сложно объяснить на пальцах :(. Тут нужно писать последовательность коммитов, а это долго. Вообщем если в бранче и транке много раз меняют одно и то же — то rebase даст нам «резульирующее» изменение, которое не будет иметь ничего общего с тем, как на самом деле происходила разработка. А это как бы потеря истории, что негативно скажется на возможность ее изучть через несколько лет.
Потеря истории вторичной ветки, не master
Да. И, как показывает практика, это плохо. История нужна не когда все хорошо, а когда приходит пушной зверек. И нет никакого желания воевать на два фронта — с пушным зверьком и с тем, что часть истории потеряна.
Не знаю зачем обязательно знать откуда коммит. На мой взгляд, вполне достаточно того что логически связанные коммиты идут последовательно. Если сильно надо, можно найти голову и хвост посмотрев на описание/автора коммитов.

В общем, идея git в том что в правильно написанной истории знать откуда коммит не надо. Я согласен, что если же все перемешано промежуточными merge то в этой каше без знания «что-куда» не разобраться, но кашу можно легко избежать.

Как уже выше заметили, разница между merge и merge --rebase только в получающейся истории, конфликты разрешать приходится те же самые.
Кстати, подмёрдживать изменения из транка в feature branch не рекомендуется. Именно потому, что это путает историю. Вот тут Junio Hamano говорит об этом: kentnguyen.com/development/visualized-git-practices-for-team/#comment-423841808
У него, кажется, был ещё пост на эту тему, но я не смог сходу найти его.
Это именно то, о чем я говорю — слабая поддержка feature branch :)
К слову, на чем вы сейчас остановились из подобных систем? И почему?
Увы, все еще выбираю :(. Git популярнее, в mercurial ветки лучше. А в продакше используется subversion. И я пока не знаю на что ее менять.
UFO just landed and posted this here
UFO just landed and posted this here
Не совсем ©. Тоесть «тупо», конечно, ставится. Но при попытке поставить на чистой Windows 7 64-бит с ActivePython 2.7.чтототам получим:

> pip install hg-git
...
building 'dulwich._objects' extension
error: Unable to find vcvarsall.bat


Я честно пытался в течении часа это побороть. И из Visual Studio 2008 shell запускал, и пути к этому батнику в разные места подкладывал, и гуглил… Гугл выдает примерно следующее:
"- WTF, у меня под Windows ничего не собирается.
— Ваши проблемы, у меня под Linux все собирается."
UFO just landed and posted this here
Ну вы меня совсем обижаете :). Написал же — все установлено и пытался «подсунуть» разными способами. Не видит. Тоесть конечно можно убить много времени, разобрать их код, понять как и что они ищут и соорудить им ситуацию когда все будет работать — но как-то пока не хочется :).

Да, виндопроблемы. А также макпроблемы, убунтупроблемы, <вставьтеназваниеоси>проблемы. Я, в целом, рад что у автора под его дистрибутивом все собирается и работает. Но у меня тут и винда, и макось, и линуксы разные — и subversion подо всем этим работает.
UFO just landed and posted this here
Питон у всех разработчиков установлен с помощью дистрибутива ActiveState. Вряд ли они все будут его пересобирать :).

VS2008 пробовал устанавливать в разных вариантах, начиная от Express и заканчивая Enterprise. Не работает ©.

BTW, то что написано в статье по ссылке — бред несколько расходится с реальностью — установленная Visual Studio 2008 ничего не прописывает в систему, поэтому вряд ли просто инсталляция поможет делу. Чтобы сборочный скрипт знал где лежит vcvars.bat нужно либо запускать Visual Studio CMD Shell, либо что-то где-о прописывать.
UFO just landed and posted this here
Тру стори, все сделано. Минимальное время я потратил — не заработало. Если приму решение пробовать мигрировать на mercurial — я, конечно, все это разберу и все починю. Но пока не готов :). Так что наличие hg-svn и hg-git рассматриваю скорее как умозрительное — это где-то собирается, где-то не собирается :).
«Windows 7 64-бит»? Возможно, он хочет компилятор, способный генерировать 64-битные бинарники? В Express Edition такой просто отсутствует, а в других редакциях, возможно, по умолчанию не поставился. Тут — wiki.cython.org/64BitCythonExtensionsOnWindows — рекомендуют ставить SDK и указывать специальной переменной окружения, чтобы distutils использовал прописанные в PATH бинарники, а не лез в реестр за папками студии.
Нет. Он как-то совсем не популярен O_O. Да и плюсов по сравнению с git / hg я у него не вижу. По факту — все то же самое, но менее популярное.
Не популярен в какой сфере? В плане репозиториев для Ubuntu он очень даже популярен)
В целом — количество разработчиков и компаний которые его используют, интеграция с Issue Tracker'ами, интеграция с IDE, с системами автобилда и прочее.
«
— Доктор, мне больно когда я так делаю!
— Ну не делайте так!
»
:-)
Специально разделил комментарии, чтобы не смешивать темы, т.к. не подумал, что именно проблемы при синхронизации ветки с транком могут считаться наибольшим неудобством в Гите.
Просто не надо так делать, и всё. Предлагаю не просто так, а потому что не очень понимаю, зачем так делать (по крайней мере, на постоянной основе).
Это стандартная практика при разработке фичей с большим объемом кода. Если не мерджить время от времени в себя транк, то может случится рассинхронизация, и мердж бранча обратно в транк станет невозможным. Это практика, от этого никуда не деться.
Для этого необходимо делать периодический rebase feature-ветки на upstream. Это позволяет поддерживать кодовую базу feature-ветки в актуальном состоянии.
Обсуждалось уже. rebase хорошо работает если нет последовательных изменений одного и того же в ветке и в транке. Если есть — то rebase сделает «коммулятивные» изменения, которые при изучении истории через полгода будут абсолютно нечитаемы — после rebase десяток мелких изменений в транке и в бранче одного и того же (а такое на практике, увы, бывает довольно часто) превратится в оно огромное изменение в транке и в одно огромное изменение в бранче. Что как бы не есть гут.
Не холивара ради, а токмо разобраться что я делал не так. Начинал с hg (пару лет назад, не помню версию, переходил с svn если что), и натыкался на наприятные моменты, как то: девелоплю себе в /mycalc и веб-сервер смотрит туда же, нужна новая ветка — приходится или делать именованную (значит публичной) либо же клонировать папку в /mycalc-feature, что предполагает изменения настроек веб-сервера. Я не шибко разбирался в DVCS, но всё это показалось чересчур странным либо же чуждым веб-разработке. В git всё стало ок (кроме синтаксиса, конечно, но это другое).

Второе, уже холиварное конечно: git имеет все комманды сразу (мультитул), hg доставляется экстеншнами (из коробки — молоток с гвоздями). Разницы по скорости эти подходы не показывают, а вот проблему несовместимости доставляют. Я не уверен есть ли у товарища нужный экстеншн, чтобы доставить его нужно копаться в системных папках, то же на любом сервере, постоянный головняк. И если смысл заключается в «альтернативных» экстеншнах, то это еще более повышает порог вхождения — какой там экстеншн лучше Attic или Shelve, тут или разбираться дольше придется, или махнуть рукой и использовать «работает как-то ну и ладно».
Любой экстеншн включается в hgrc прямо в .hg репозитория.
Либо в hgrc системы, что может быть ещё удобней для серверов.
Естественно. Просто речь шла о том, чтобы не редактировать system-wide конфигурацию.
UFO just landed and posted this here
UFO just landed and posted this here
Если Вас эта тема не волнует, видимо Вы не видели действительно херовой истории. Я ее видел и в CVS, и в git, и копаться в ней тоже приходилось, как-то оно не очень…
UFO just landed and posted this here
История — это важный элемент инфраструктуры разработки.
Так, например, станку на заводе уделяется внимание, сопоставимое с вниманием к изделию.
UFO just landed and posted this here
Не будет станка — не будет изделия требуемого качества и в требуемые сроки.
С соответствующим эффектом по оплате.
UFO just landed and posted this here
История — это часть документации проекта. Некачественная документация — себестоимость проекта растёт, эффективность разработки и другие связанные показатели — падают.
Я думал что хоть что-то понимаю в Git… до этого момента
SCM делает акценты на изменения. здесь удобнее работать не с хронологической историей коммитов, а со стеком патчей. например www.procode.org/stgit/
Sign up to leave a comment.

Articles