Как стать автором
Обновить

Комментарии 365

Коммит — это патч. Все. Он перечисляет некоторые изменения в некоторых файлах в формате «единого diff-а». [...] История Git — это очень длинная цепочка инструкций для пересоздания кодовой базы с нуля, шаг за шагом. Представь это как стопку патчей, [...] В общем, да, но также они буквально являются SHA-1-хэшами патча, включая заголовки.

Эм, но… нет.

The major difference between Git and any other VCS (Subversion and friends included) is the way Git thinks about its data. Conceptually, most other systems store information as a list of file-based changes. [...] Git doesn’t think of or store its data this way. Instead, Git thinks of its data more like a set of snapshots of a miniature filesystem. Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot.


(http://git-scm.com/book/en/v2/Getting-Started-Git-Basics)

Иными словами, каждый коммит в гите — это дерево блобов с полным содержимым файлов, а не изменений.
Это только в «представлении». В паках гита хранятся диффы.
Вот только это не исторические диффы, а просто дельта-компрессия блобов.

stackoverflow.com/a/8198276/1105881
Причём что интересно, дельта-компрессия может быть даже не от конкретной предыдущей версии данного файла, а от чего-угодно, что покажется гиту похожим на новую версию файла. К примеру в первой ревизии у нас есть файл 1.txt с содержимым «Вася» и файл 2.txt с содержимым «Петя». Теперь мы меняем содержимое файла 1.txt на что-то типа «Пета» — так вот в гите это может сохраниться как «файл 1.txt второй ревизии — это файл 2.txt из первой ревизии с 4-ым байтом 'а' вместо 'я' ».
Да, я именно это и имел в виду. Только файлы адресуются не по ревизиям, а напрямую по хэшам.
Дополнение: именно так git и определяет, что в комите файл был скопирован или переименовался и даже показывает процент совпадения, что невероятно удобно.
И невероятно НЕудобно, когда промахивается, а явно, в отличие от мерка, переименованный/перемещенный файл указать нельзя.
Увы. вы, похоже, совершенно неправильно понимаете гит и как он работает. Каждый коммит — это определенное состояние рабочей директории. Все дифы (патчи) которые возникают — всегда результат сравнения разных состояний рабочих директорий будь то merge, rebase или просто diff.. И они даже не кешируются, а каждый раз высчитываются. Именно поэтому в гите не рекомендуется хранить больших файлов — даже при малом изменении будет храниться новая полная копия файла. Другое дело, что хранение рабочих директорий устроено таким образом, что дифы считаются феерически быстро.

Вы уверены, что хотите этому учить читателя?
Позвольте не согласиться с вашим высказыванием, как с валидной критикой данного поста.

С технической точки зрения, вы, скорее всего, правы насчёт природы коммитов — я не влезал в тонкости реализации.

Однако, семантика использования (за исключением rebase) больше всего напоминает набор патчей.

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

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

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

Я опираюсь на утверждения из Git Book, и это не техническая точка зрения, а концептуальная.

Однако, семантика использования (за исключением rebase) больше всего напоминает набор патчей.

Вот это «за исключением» все и портит.
Ну тут можно спорить, но как модель — оно работает хорошо. А когда человек достаточно освоился, он может отбросить эту модель, и держать в голове больше деталей реализации (если оно ему надо).
Я не очень люблю сначала учить неправильной модели, а потом, когда возникают проблемы, переучивать.
Вы очень категоричны :)
Никогда не занимались рефакторингом? Или вы всегда и сразу строите безупречную и полную модель бизнесс процессов? Является ли предыдущая модель неправильной?

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

когда возникают проблемы, переучивать

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

Опять же, если почитать man gittutorial — вы не встретите там ни слова даже про хэши — там да и в самих cli утилитах они, в основном, упоминаются как «commit», что как бы намекает на то, где предметная область, с которой предлагается оперерировать, а где детали исполнения. Пользователю не нужно знать про тонкости реализации до тех пор, пока ему действительно не нужно про них знать :)

Могу я вас попросить поделиться практикой введения людей в git (или введения вас в git :))? Вы отправляете читать документацию? На какой срок? Какие контрольные вопросы потом задаёте или тесты проводите? Через какой промежуток времени, вы понимаете, что человек готов работать с кодовой базой без вашего надзора?
Никогда не занимались рефакторингом? Или вы всегда и сразу строите безупречную и полную модель бизнесс процессов?

Занимался. Но обычно модель бизнес-процесса развивается эволюционно, а не революционно.

или введения вас в git

git-scm.com/book/en

И две недели на гитхабе со своим проектом.

размазать достаточно Git-а по твоему лицу
нет, спасибо :)
пушнуть на лицо
… Когда они впервые скачивают код, они могут привязать его к директории под названием master (потому что это мастер-копия). Затем, когда они приступают к работе над своим драйвером, они могут все это полностью скопировать в директорию под названием ужасный-драйвер-broadcom. Чтобы сгенерировать патч, им нужно просто получить разницу между этими двумя директориями.

ах, видимо, поэтому один из вопросов от меркуриальщиков: «как узнать в какой ветке были такие-то изменения?»
НЛО прилетело и опубликовало эту надпись здесь
Господи, когда же в мейнстриме появится что-то более простое и понятное чем Git. Пока все статьи которые я вижу из серии «Git это просто» больше напоминают сессии аутотренинга в стиле «все хорошо, все нормально».

Я через силу заставил себя базовый основы Git выучить, но в целом Git вызывает примерно такое же отвращение, как vi после Sublime.
Git настолько восхитителен, когда его понимаешь, что не представляю, что может быть лучше.
Если вы не умеете его готовить, то это не означает, что он не вкусный.
Мне в начале его освоения как раз помогло описание его внутреннего устройства. После чего стало понятно, что не может быть ничего лучше VCS с такой прекрасной архитектурой и идеями, которые в неё заложены.
НЛО прилетело и опубликовало эту надпись здесь
Знаю, что есть, но не возникает желания или необходимости мигрировать. Зачем, если все отлично работает?
И то, что именно git стал на сегодняшний день мэйнстримом, только подтверждает, что большинство придерживается того же мнения.
Ну так и wordpress стал мэйнстримом, Миллоны мух не могут ошибаться.
То что исходный код вордпресса ужасен не отменяет того факта, что с точки зрения пользователя, это превосходный очень удобный движок. Именно поэтому он и стал популярным. Так что аналогия с мухами неверная.
Я что-то не припомню, чтобы мухи ошибались.
Wordpress на момент появления был лучшим движком. Чему удивляться.
Хотя, если честно, я его всегда недолюбливал.
Все претензии к нему от того, что новостной движок пытаются использовать для разработки сайтов и магазинов. Просто не надо этого делать и он будет вполне сносен.
А какие опенсорсные движки сейчас лучше? Просто интересно.
Лучшим по каким критериям? Возможности PHP4 в нём если и использовались, то весьма ограниченно, а ему тогда года 3 уже было.
Лучшим по тем критериям, что ничего лучше в опенсорсе на тот момент не было.
«Миллионы мух» не интересуются, насколько там все прекрасно архитектурно или какие фичи PHP там используются. Раз движок стал так популярен, то разумно предположить, что были для этого причины? Раз считаете, что все так было на тот момент плохо в движке — сделали бы в то время что-то лучше и выложили бы в опенсорс, делов то.
Лучшим по тем критериям, что ничего лучше в опенсорсе на тот момент не было.

Лучше по каким критериям? :)

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

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

Wordpress зашёл в 2003, это был расцвет эпохи блогов и тогда, он действительно был приемлем в технологическом плане.
Он предложил простую установку и расширяемость.
Wordpress стали выбирать из-за обилия плагинов и тем.
Появился wordpress.com…
Теперь уже есть армия wordpress-разработчиков тем и плагинов. Так что wordpress — это в какой-то мере технология-стандарт.

Та же ситуация с GIT: удачный заход из мира разработки Linux (где ей было самое место) через авторитет Линуса (вспоминаем эксперимент Милгрема), потом github, фактически самая крупная социалочка для OpenSource-разработчиков. Потом codeplex отказывается от HG, потом git-используется по дефолту в кучи мест.
Теперь даже если кто-то напишет что-то лучше и удобнее, чем git, оно не станет популярным без очень сильного PR.
Совершенно верно, о чем, собственно и разговор.
Пока не возникнут новые задачи, которые не решает Git и пока кто-то не предложит новое решение, Git будет оставаться мэйнстримом.
Должно быть не просто то же самое, но немного удобнее (что вообще спорная категория), а на порядок лучшее. Или лучше в чем-то конкретном (ниша). Тогда сообщество это быстро раскрутит.
НЛО прилетело и опубликовало эту надпись здесь
Сколько лет пользуюсь и не знаю, что есть какие-то проблемы с переименованием или копированием. С чем именно у вас тут сложности?
Если у вас такие вопросы, вы не понимаете гит. Гит отслеживает не файлы, а изменения в них. И это круто, потому что когда ты спрашиваешь «откуда-куда скопирован файл», то скорее всего инетерсен не сам файл, а «откуда взялся здесь этот кусок кода?», и гит даёт ответ на этот вопрос (см. man git-log, флаг -S).

Как только понимаешь, что важен сам код, а не файлы, в которых он содержится, проблемы исчезают. За всё многолетнее использование гита никогда не было проблем с переименованием-копированием файлов. Такой вопрос, как у вас, возник только в самом начале знакомства с гитом, года 4 назад, но как только я разобрался с тем, что делает гит, вопрос исчез и больше никогда меня не беспокоил. Даже более того, поменялось отношение к коду, так что гит сделал меня лучним программистом.

Да, а «переименование/копирование» — это состояние файлов, и это не так важно, как кажется. Впрочем, гит вычисляет эти категории изменений на лету по «похожести» файлов.

См. githowto.com/changes_not_files
НЛО прилетело и опубликовало эту надпись здесь
Я кстати, так понял, что Линус имел слабое представление о subversion, в его понимании subversion = CVS, но это очень сильно не так. CVS действительно была ужасной системой.
Кстати, кто-то может всё-таки понятно объяснить, чем это так плох subversion, что на него столько гонева?

p.s я абсолютно точно уверен, что мне нужна именно нераспределённая vsc. В моём случае, распределённость — явный минус
Лично я для себя вижу только одно: в Subversion нет локальных коммитов. Может, их уже добавили, но раньше их не было.
У SVN нет поддержки на github и bitbucket, так что для open source проектов он не очень походит. Там как раз нужно форкать репозиторий.
А в остальном svn очень годная штука с низким порогом вхождения.

На мой взгляд интересная заметка автора библиотеки SObjectizer о SVN, нелюбви к нему и степени владения инструментом тех, кто его не любит: http://eao197.blogspot.ru/2015/09/progflame-svn.html
Неудобная (или сложно найти мануал по удобной) работа с ветками — это основное для меня.
Распределенность же есть не просит.
Можете просто ее не использовать. По опыту работы 90% пользуются одним центральным репозиторием.
Но на самом деле, это удобно — у вас один репозиторий, у клиента — свой и вы можете обмениваться правками работая каждый со своей логикой и своим процессом. Мне лично очень нравится эта гибкость.
SVN была ужасной системой. Медленной, с плохой работой веток,… (tree-конфликты как вспомню, так вздрогну).
Пока не переехали на Git было очень много сложностей с командной работой над большим проектом с длинными параллельными разработками.
Как я понимаю, ветки в SVN изначально совсем для другого — не для параллельной разработки. А скорее, чтобы хранить несколько версий одного продукта для разных пользователей, скажем.
А разработка в SVN хорошо идет, если все всё время работают с одним репозиторием (в одной ветке). Это требует вначале некоторой организации кода, чтобы реально можно было пробовать разные вещи не мешая друг другу, и не мешая основному проекту — на уровне кода, не через SVN. Но зато потом это работает железно, 0 проблем.

Видимо Git пытается взять на себя поддержку параллельной разработки, и от этого на него такая нагрузка. Ведь параллельная разработка — это никогда не бывает слишком просто. В принципе это и не может быть просто, вряд ли здесь есть универсальное решение.
Не в организации кода дело, просто при разработке в одной ветке (независимо от системы) эта ветка становится продакшен веткой, коммиты в неё могут попадать только после приемочного тестирования.
Насчет SVN — очень похоже на то.
Пока мы работали с одной веткой — все было довольно неплохо. Но когда стали вести параллельный процесс (несколько пользователей пилят сразу несколько фич), то сведение превратилось в сущий ад.
Процесс в git у нас сейчас такой же — несколько параллельных веток, которые регулярно сводятся. Но благодаря ребэйсу (ежедневному и обязательному) и правильной организации задач все годаздо проще.
Вы меня не слушали. Да, снепшоты он делает, и делает он это для отслеживания *изменений*, хотя лучше здесь сказать *содержимого*? Ведь данные он хранит в блобах (не связанных напрямую с именем оригинальных файлов, если быть педантом — имена хранятся рядом, в деревьях). И сжимает блобы, как было уже указано выше, дельта-компрессией. И всё это сделано, чтобы следить за изменением содержимого. Блин, ну не было у меня никогда проблем с переименованием файлов в гите, не было. И если файл при переименовании изменился больше, чем на 50%, то действительно ли это старый файл? Ну какая мне разница, что файл был переименован, если он настолько изменён, что по сути это другой файл? Ещё раз: мне не важно где какой файл как называется, мне важно, оттуда какой кусок купола взялся. И гит решает эту проблему идеологическую. А блобы там и деревья — это деталь реализации, и она меня редко волнует. А учитывая популярность гита, я не один такой. Так что может пора просто изменить точку зрения на нашу программисткую реальность, и понять, что мы создаём не файлы, а текст, код, содержимое?
НЛО прилетело и опубликовало эту надпись здесь
Вы сейчас какие-то небылицы рассказываете. Чтоб были понятно — у меня 15 лет стажа после универа, лет 5 на гите, писал профессионально на перле, пхп, питоне, теперь на скале пишу. Команды были от 2-3, до 15 человек, сейчас пишем большой командой суровый энтерпрайз: скала, хадуп, бигдата, все дела. С описанными проблемами не сталкивался никогда. Или просто за проблемы их не считал.
НЛО прилетело и опубликовало эту надпись здесь
Что в нем восхитительного?
Отсутствие веток (только именованные головы) и такая милая штука как отсоединенные коммиты?
Или только автоматическое определение переименованных/перемещенных файлов?
Или merge, который сливает два снапшота вместо двух графов диффов?
Почему же нет веток? У меня есть.
У меня по процессу 4 постоянных ветки и я в любой момент могу делать сколько угодно новых — под конкретные фичи. И все это элементарно и беспроблемно таскается из ветки в ветку, меняется местами и сводится. Я в любой момент могу решить, что войдет в апдейт, что отложить, что выложить частично, например. Не представляю, что может быть гибче.
Мерджи я по процессу совсем исключил. Они слишком мусорят историю. Все делаю ребэйсом. Даже пулл — с опцией ребэйса. Так же удобно собирать коммиты (если случилось, что по одной задаче их получилось несколько) в один интерактивным ребэйсом.
А что из какой ветки пришло сохраняется при слиянии функционала после ребэйса уже мерджем с --no-ff.
История всегда идеальна и прозрачна.
Я вас разочарую — у вас нет веток. У вас есть именованные головы и связи между коммитами. «Ветка» в гите — раскраска от коммита в прошлое по связям.
Ветки, привычные по живой природе и другим системам контроля версий, совершенно другие: растут не от крайнего листочка в прошлое, а от родительской ветки в будущее.

> И все это элементарно и беспроблемно таскается из ветки в ветку, меняется местами и сводится. Я в любой момент могу решить, что войдет в апдейт, что отложить, что выложить частично, например. Не представляю, что может быть гибче.
Я вас снова разочарую: в мерке все это делается еще проще и надежнее ;) Потому что с нормальными именованными ветками, без дурацких отсоединенных коммитов, куда более интеллектуальным слиянием, возможностью руками указать на перемещение-переименование

> Мерджи я по процессу совсем исключил. Они слишком мусорят историю. Все делаю ребэйсом.
То бишь предпочитаете фальсифицировать историю. Это вполне возможно и в других системах контроля версий. Проблема только в том, что при ребейзе мерж никуда не пропадает по факту, но из истории вычеркивается. Это делает расследование и исправление проблем особенно увлекательным. Также очень приятно что без специальных ключей гит элегантно сотрет лишнюю по его мнению информацию о принадлежности коммита к ветке (я в курсе, что такой информации у гита на самом деле нет, я про то как это выглядит для пользователя).
Я умею его готовить и даже есть.
Но гит именно что невкусный.
А что именно вам в нем не нравится? Конкретные примеры?
Коммит отсоединенный.
Слияние без учета истории сливаемых веток.
Переименование-перемещение только если как сам гит соизволит принять вердикт… который может меняться на лету вместе с настройками.
Отсутствие именованных веток.
Ну а что? По сути это мини-github в кармане. Кроме распределенного репозитария получаем распределенный трекер ошибок, базу знаний и т.д. и т.п. Fossil — это лично мой выбор, как человека до сих пор сидящего на git. Он чуток проще git, можно таскать на флешке без надобности настройки окружения. Один минус — большие бинарные файлы не для него, но я пишу только код. Для маленькой комманды нет ничего лучше.
Git оставим для больших проектов с кучей народа. А свои личные проекты я буду держать на этом маленьком гиганте.
Попробуйте Mercurial с помощью TortoiseHg. Он интуитивно кажется гораздо понятнее.
а чем это будет отличаться от tortoisegit или tortoisesvn?
если пользоваться черепахой, то конечно, гит покажется недружелюбным. Git идеален а консоли — только так понимаешь, как именно он работает, и почему это правильно.
Родной GitGui тоже очень хорош.
По моему, все недовольство git'ом вызвано как раз использованием GUI-оболочек.
Оболочки еще больше запутывают и без того «странноватый» синтаксис git'а. А понимание логики работы приходит только когда работаешь с git'ом напрямую через консоль.
Ну в винде (если я не в шелле msys2) мне удобнее использовать GitGui. Ну а нравится он или нет — дело вкуса. Мне и так хорошо и так.
Лично мое первое впечатление от git было: «version destroy system»
А все потому что впервые столкнулся с отсоединенным коммитом.
Коммит, конечно, нашелся, но осадочек неприятный остался.
Логику работы понял так: «и чего только люди ни придумают лишь бы именованных веток не делать».
В первый раз отсоединенный коммит (особенно, когда его не ожидаешь) — это страшно )
Но это от непонимания что к чему.
На самом деле, ничего страшного в нем нет.
Страшного ничего нет — жить без веток и с отсоединенными коммитами можно.
Вот только как часть дизайна системы контроля версий и то, и другое — фейл, эпик фейл.
Не должна система контроля версий автоматически утрачивать такую важную часть метаданных, как ветка, в которую сделан коммит.
И уж тем более ничего подобного не должно автоматически происходить с самими коммитами.
Не должна система контроля версий автоматически утрачивать такую важную часть метаданных, как ветка, в которую сделан коммит.

а что есть такое важное в тех метаданных (кроме самого названия) ветки меркуриала? (без иронии и сарказма)
я так и не понимаю пока, что это даёт…

взять тот же репозиторий самого Git'а:
развесист он до ужаса, однако, найти кто, когда в ходе какого набора коммитов сделано изменение — вообще не проблема…
и самое главное — узнать почему: это описано в КАЖДОМ коммите
и хотя это мера административная… весьма нужная… но в произвольном проекте всё равно зависит от разработчика
и уж если разраб не пишет ПОЧЕМУ он сделал эти изменения, а ты потом вынужден догадываться (по имени той ветки, в которой он это делал), то это не столько проблема ЛЮБОЙ SCM (даже SVN), сколько «разрабу по башке надавать», чтобы не писал коммиты вида «Исправлена ошибка»
или есть ещё что-то, что я не вижу?
И граф коммитов тоже в консоли смотрите?
У меня вот очень большой проект, чтобы проследить от кого пришло изменение мне порой приходится стреляться даже с SourceTree. Как вы это всё в консольке делаете?
Да, я знаю, что у git есть log с кучей параметров.
Мне интересные конкретные действия, которые делает человек, который отрицает GUI для Git для того, чтобы найти от кого пришло изменение. Ну там, открывает 10 терминалов, долго уныло скроллит, пишет grep или как?
Ну да. git log --grep, git blame и т.д.
10 терминалов не нужно. Достаточно одного.
соответственно, с десяток тыкнутых клавиш вместо пары кликов мышкой) тут действительно нечего спорить, кому как удобнее. На небольших проектах с небольшим числом разработчиков gui вполне достаточно (а зачастую в силу более низкой планки входа — и удобнее). Консоль представляет больше возможностей, там где они действительно нужны. Этот вечный спор консольщиков и визуалов напоминает ситуацию с АКПП. Первое время автоматы считались моветоном, 'не по пацански' ;) а ведь ничего, сейчас половина машин, если не больше, уже без педали сцепления. И ничего, 'пацаны' нормально ездят.
tig? — https://github.com/jonas/tig
Граф, каюсь, смотрю в gitk — запускаю из консоли.
В нем мне действительно удобнее смотреть историю.
Хотя проблем с git log тоже нет. Особенно, когда работаешь не на своей машине, а по ssh.
Из доп.средств еще пользуюсь kdiff3 для разбора конфликтов, тоже как-то привык к нему.
Не знаю, уверен что профессионалы Git, конечно, правы. Но так как по сути и Git, и SVN, и все такое — делают ОЧЕНЬ ПРОСТЫЕ ВЕЩИ, то совершенно ожидаемо, что я, как пользователь, ожидаю от них, что бы они делали это ПРОСТО.

Ну как бы система выполняет 3-5 команд всего. Неужели так было трудно сделать, чтобы эти 3-5 команд выполнялись легко, без того, что нужно год работать под Git чтобы во всем разобраться? Ясно, что в конце концов человек во всем способен разобраться.

Merge под Git — это просто катастрофа. Всегда приходится использовать посторонние программы, но дело не в этом. Не дай бог случайно сделать что-нибудь не то, какую-то ошибку. Потом откатить назад все очень сложно.
Как-то в SVN я этого не замечал. Так что я жалею, что весь мир перешел на Git.

Недавно мы начали работать с суб-репозиториями. Это вообще ужасно. Собрать головной проект по всем референтным ссылкам на суб-репозитории, которые независимо обновляются… Ну правда, это как использовать vi вместо Microsoft Word.
Ну. vim настолько же лучше Sublime, насколько vim лучше блокнота.
Git сложный и вся его прелесть внутри, в этих tree-hash, в этих индексах, в этих immutable цепочках комитов. Он настолько сложен и прекрасен внутри, что когда он выходит наружу через console, а еще хуже через UI, он становится совсем непонятным. Почему надо сначала делать git add, а потом git commit. Почему есть git push и есть git commit, эти многие вопросы, которые появляются когда люди переходят с svn или других систем. На самом git гораздо сложнее внутри, чем svn, зато эта сложность оправдана. Он позволяет делать такие алгоритмы, которые невозможны в других vcs. В git действительно, очень сложно потерять, его действительно очень сложно сломать без возможности восстановить (чего не скажешь о svn), git делает потрясающие merge. Сравнивать его с mercurial не стану, долго им не пользовался, но git действительно очень интересно устроен. Мне кажется, каждый программист должен изучить сначала его изнутри, тогда многое на верхнем уровне станет понятнее. На самом деле git команды изначально были не самым лучшим образом устроены, поэтому появилось множество утилит и «упрощений» типа github client, но они меняются со временем и становятся только лучше.
Так может, он бы и жил своей внутренней жизнью, вообще не выходя наружу? Мы бы радовались его красоте, а пользовались для жизни чем-нибудь другим?

Вот например, прекрасная ситуация: сделал git push, а потом, перед git commit проверил обновления и увидел, что код существенно изменен. Казалось бы, что проще? Возьми последнюю версию, сделай merge.
Но после обновления выходит, что уже есть 3 версии: локальная, та которая push и обновленный репозиторий. Сидишь, думаешь, с чем сливать. Ладно, проще иногда сделать commit с конфликтами, просто чтобы не связываться с этим, а потом еще раз вычистить все конфликты и снова сделать commit. Но тогда кто-то другой может успеть взять версию с конфликтами из репозитория…
Но после обновления выходит, что уже есть 3 версии: локальная, та которая push и обновленный репозиторий. Сидишь, думаешь, с чем сливать.

эээ… ТРИ версии? откуда?
в простейшем случае в одной «ветке» проекта есть две версии кода:
ваша локальная и та, что на удалённом «центральном» сервере, и всё.

и зачем перед git commit делать обновления? ну, хорошо, git fetch можно делать в любое время, но каким образом это мешает коммитить? или вы следуете парадигмам SVN: коммитите только в последнюю версию с сервера?

может порядок сначала навести в головах или workflow?

если готовы конструктивно обсуждать, я тоже готов, а отвечать на нытьё «я там что-то сделал, не понял что, а оно сломалось, вот оно говно» не хочется :)))
эээ… ТРИ версии? откуда?

1. локальная ветка
2. удаленная ветка
3. рабочая директория с результатом мержа
ну, давайте упростим себе задачу:
1. начнём с того, что мёрджить стОит только закоммиченные изменения (хотя можно и с «грязной» WC, если изменённые файлы не трогаются мёрджем; но зачем себе яму рыть?)
2. таким образом мы имеем две версии: локальная и удалённая… мёрджить их — не проблема. даже в случае ошибок, всегда можно повторить мёрдж…
3. пушить на сервер можно только закоммиченные изменения, поэтому вопрос «у меня тут незакоммиченный результат мёрджа, не знаю что пушить» — как-то абсурден, мне кажется? а закоммиченный мёрдж превращается в локальную версию… и опять у нас ДВЕ версии: локальная и удалённая…

поэтому я не понимаю тут проблемы ТРЁХ версий…
1. Иногда можно и забыть — человеческий фактор и всё такое, но не суть.
2. В момент мержа или сразу после него у нам три версии по любому — локальная в репозитории до мержа, удаленная в репозитории до мержа и результат мержа (закомиченный или нет тут не особо важно), что хорошо видно по всяким *diff3
Сделать commit не получается просто так. Если удаленная версия изменилась, то, как я понимаю, Git заставляет её взять начала. Дальше возможны два варианта. Если его автоматический merge сработал, то в Tortoise возникает такая смешная картинка, которая меня приводит в некий ступор: одна стрелочка вверх, одна вниз. Ну то есть можно после этого сделать push, не вполне понятно в какую версию. Но через несколько pulls все восстанавливается, кажется.
А вот если не повезло, и возникли конфликты в слиянии… Тут все совсем плохо. Локально версия становится с этими безумными <<<<<<, >>>>>>>>; версия staged без них. При этом откатить авто-commit, кажется, невозможно (может, я не знаю как просто?).
Надо дальше читать про git?
У вас что‐то с workflow. Если бы вы делали коммит находясь исключительно на своей закладке‐ветке, то таких проблем бы не возникло на стадии фиксации. Конфликты, конечно, никуда не делись бы, но они возникли бы позже: при merge или rebase.

Ну и если вам не нравятся <<</>>>, то используйте другой mergetool (см. git help mergetool и git help config, во втором искать mergetool).

PS: вернуть репозиторий из абсолютно любого состояния возможно всегда: я, к примеру, иногда вынужден делать git branch -f branch origin/branch. Но не всегда это легко. git reflog вам поможет.
Извините, я неправильно написал. Надо было «сделать push не получается просто так»…
Просто я работаю с несколькими системами одновременно, и все эти понятия слегка смешались у меня в голове.
Но это была моя ошибка, извините.

По сути я описал проблему верно, только ошибся в словах.
Коммит можно делать всегда и из любых положений, он не требует обновлений с сервера, потому что это сугубо локальная операция. Только git push может потребовать git pull если удалённая ветка обновилась.
Это была моя ошибка, извините. Я выше (и ниже) объяснил.
Если удаленная версия изменилась, то, как я понимаю, Git заставляет её взять начала.

в этом и проблема, что Вы неверно понимаете
в отличие от SVN, используя Git, вы можете вообще не обращать внимание на то, как обновляется «центральный» сервер (боюсь Вам говорить, что удалённых репозиториев может быть не один), коммитите себе и коммитите в свою ветку…
а брать pull'ом удалённые репозитории — не самый лучший способ

судя по всему, вы коммитите сразу в master, и ещё делаете git pull ПЕРЕД коммитом…
в общем, вы трогаетесь сразу с третьей передачи, и удивляетесь, что она глохнет… иногда только газу когда сильнее даёте, до отсечки, тогда иногда трогается, но сцепление горит…

сходите в автошколу, что ли… на пару занятий…
Да нет, я кажется плохо объяснил. Во-первых я обычный пользователь, и уж конечно никто мне в master работать не даст. Моя область профессионализма, ну извините, лежит не в IT; в своей области я хороший профессионал. А с Git мне просто приходится иметь дело.

Commit, разумеется, сделать легко. И никакой pull перед commit я не делаю (хотя, возможно, стоило бы). Проблемы начинаются, когда делаешь push и понимаешь, что версия уже изменилась. И тут начинается автоматический merge + все последующие проблемы.

Скажем, конкретный вопрос: а) можно ли откатить авто-merge? б) можно ли откатить commit? Просто легче делать merge между локальной копией, и удаленной. А не между stage-версией (которая неизвестно где находится), и удаленной.
Под stage-версией я имею ввиду ту, которой уже сделали commit но еще не смогли сделать push.
Откатить автослияние должно быть можно обычным git reset. Но я предпочитаю просто работать с ветками‐закладками, которые трогаю только я, потому с такой ситуацией практически не сталкиваюсь. Но, насколько я помню, автослияние только при pull, а с push такого быть не должно. Если после push идёт автослияние, то вам поможет только push -f {remote} {old-commit-hash}:{branch-name}, если я правильно понимаю (точнее, вам точно нужен push -f, но не уверен, что он примет {old-commit-hash}: если нет, то придётся использовать ещё и branch -f {branch-name} {old-commit-hash}, предварительно слиняв с ветки или тот же reset (что проще: линять с ветки не нужно)).

Фиксацию обычно откатывают через reset. Помните, что под «откатом» в git имеется ввиду исключительно перемещение закладок: само изменение никуда не денется, просто на него после отката перестанут ссылаться, а через некоторое время оно будет удалено сборщиком мусора. Поэтому в особо сложных случаях можно «откатывать» через branch -f {branch-name} {commit-hash}, восстанавливая изменения в рабочем каталоге через checkout {removed-commit-hash} -- '*'. Предварительно сделав checkout --detach и в конце не забыв checkout {branch-name}.

И ещё одно: stage версия — это незафиксированное состояние, с которым до фиксации (commit) можно работать только локально, ни в коем случае не состояние, имеющиеся в любом из изменений.
точнее, вам точно нужен push -f

Предварительно сделав checkout --detach

оу! оу! оу! полегче!
*и после этого ещё ругаются на Git...*
не лечите по фотографии, а то ща насоветуете…
Это единственный способ откатить слияние, если оно с какой‐то радости произошло именно при push, а не локально, как должно. Я недостаточно знаю git, чтобы сказать, что слияние на сервере при push в принципе невозможно.
Лечите, лечите. Может я наконец разберусь. Поверьте, я уже прочитал книжку по Git, и работаю с ним пару лет, и то до сих пор не разобрался в некоторых базовых вопросах. Это уже даже не смешно.

На работе, если у меня что-то не получается, то просто приходит человек и исправляет. Но я все равно не понимаю до конца. Причем, мне кажется, даже он не всегда понимает как именно надо исправить, просто делает несколько разных попыток и в конце все работает.
У нас последняя история — начали работать с submodules, это вообще финиш. Приходится каждый раз ВРУЧНУЮ проверять все ссылки на submodules каждый раз, прежде чем делать pull главной версии. А этих submodules уже больше десятка. Но про это я даже не спрашиваю, мне бы с вещами попроще разобраться.
В mercurial свой аналог (subrepos) пометили как «feature of last resort» («использовать в крайнем случае»). Наверное, не зря.
Наверное. К сожалению, это не мне решать. Возможно это облегчает координацию между группами в чем-то, когда на проекте более тысячи человек.
В git'е их тоже не стоит использовать, пока не прижмёт. Всё-таки фича тяжелая для повседневного использования и требует хорошо продуманного workflow.
Я что-то понял, но мне хотелось бы прояснить. Сначала определимся с терминологией.

Версия А — моя локальная версия. НЕКОТОРЫЕ файлы из которой я хочу отправить в репозиторий, а с другими продолжаю работать.
Будем считать, что когда я начал работать с локальной версией, она была синхронизована с репозиторием в день 1.

Я делаю commit этим файлам, и у меня появляется:
Версия Б — это удаленная версия день 1 + мои правки, все это все еще у меня на компьютере.
При этом версия А тоже продолжает оставаться на моем компьютере, так как я сделал commit не всем файлам.

Следующий этап — я делаю push, и понимаю, что удаленная версия изменилась. То есть сразу push не проходит. Назовем удаленная версия день 2, это версия В.
Значит я делаю pull этой версии В, и этот pull портит мне версию А. Но я могу зато сделать merge. При этом версия Б остается неизменной, мой merge на нее не влияет, к сожалению.

Ок, я делаю merge В с А (хотя хотел бы Б с А), потом делаю еще один commit и надеюсь, что теперь Б соединилась с В.
После этого я делаю push и вроде все должно быть нормально.

Однако, поскольку эта процедура портит мне локальную версию А, то и merge A c В может не вполне адекватно отражать то, что я хочу сделать merge Б c В.

Где физически находится версия Б? Могу ли я работать с ней напрямую, после commit но до push? Могу ли я работать с Б так, чтобы моя локальная версия А оставалась нетронутой?

Извините, если запутано получилось.
да уж… весьма запутано
Вы визуализируете себе дерево коммитов?
gitk --all ?
git log --all --oneline --graph --decorate на «худой конец»?
Ну здесь хотя бы нету слияния при push, так что про push -f лучше забыть. Версия Б находится локально в виде изменения и изменить её нельзя никак, но можно создать версию Г, что‐то сделав (rebase, к примеру) из Б и обычно этот вариант считают изменённой версией Б (знание о том, что версия Б не изменилась и никуда не делась пригодиться, если вы где‐то накосячили — Б можно добыть из reflog). Я предлагаю следующее:
  1. git stash — фиксирую версию А в специальном изменении, которое никуда не push’ится. Достаётся с помощью git stash apply, при этом происходит аналог rebase. Это лучше вообще делать до pull, если вы хотите нормально работать с Б.
  2. Теперь делаете pull, указывая что делать с Б (слияние, rebase).
  3. И теперь достаёте сохранённый А, происходит rebase A поверх слияния Б+В (которое я ранее назвал Г для случая «rebase»).
Делать push можно в любой момент после 2.
Звучит очень хорошо. ОК, про А мы можем забыть. Делаем ей stash, действительно, и все. Вместо pull сначала fetch, чтобы осмотреться.

По поводу 2: вы не знаете, как в Tortoise выбрать слияние или rebase? И в чем разница?
И другой вопрос — как в Tortoise откатить слияние, если оно слишком запуталось (то есть вернуть чистую версию Б?)

Я как-то уже привык работать через Tortoise, не хочется учить terminal git только для пары вещей.

Спасибо!
Про tortoise меня не спрашивайте, я использую либо терминал, либо Vim с моим дополнением aurum (которое попутно стирает часть различий между git и mercurial). Но слияние/rebase только через терминал.
#some changes in working
git add.
git commit
git fetch
git merge --no-commit origin/…
#control merge
git push
Думаю, что очень нескоро. Github, bower и прочие тулы, где git идёт по-умолчанию, фактически, монополизировали git.
Да-да. У меня у прабабки, когда была жива компьютеры вызывали отвращение, поэтому она до упора пользовалась печатной машинкой. Это про vim против sublime. Про git Вам и так много ответили.
Некоторые и сейчас предпочитают печатные машинки ) Да и качество первых экранов и самих компьютеров могло вызывать.
Заголовок спойлера
image
Californication
Всё бы хорошо было в sublime, если бы там текстовый редактор доработали. А так — когда мне нужен блокнот на стероидах — я предпочитаю IDE.
Вроде как Google собирается раскрыть свою систему контроля версий, основанную на mercurial.
Да, есть много хейтеров гита, даже я таким был, и боготворил меркуриал… Но до тех пор, пока не начал работать в команде из более чем 3х человек.
Меркуриал прекрасен, быстр, прост и удобен.
Но в гите понимаешь все прелести cherry-pick, rebase, ветвления, множество апстримов (они есть в меркуриале, но либо скрыты в недрах, либо реализованы костылями)… Около полутора лет назад плотно подсел на git, но до сих пор не понимаю как он работает. Очень часто ломаю ветки пытаясь сделать rebase на master, иногда возникают вопросы как сделать инвертированный cherry-pick (особенно для отката более чем одной ревизии), не всегда ясно почему это дерьмо не хочет «пушить» в мастер с одной машины, но успешно «пушит» с другой, но я его люблю, потому что… Да не знаю почему… Наверное потому что он прекраснее меркуриала, с ним можно поиграться, поискать проблем на пятую точку и сломать все нахрен =)
Если с каждой возникающей проблемой один раз разобраться и запомнить, то Вы начнёте боготворить гит.
Если разобраться предварительно, то и проблем не будет возникать.
Если использовать меркуриал, то и разбираться не придется — оно просто сразу работает так, как надо.
Не работает оно как надо, основной костыль mercurial — это бранчи, в git они работают просто и понятно, в mercurial это что-то другое. Еще mercurial не давал никаких инструментов по созданию «чистой» историю, а не сложнейшего графа комитов — не было rebase стратегии (ситуация может поменялась за 3 года, так что буду рад услышать что-то новое)
Про бранчи — с точностью до наоборот.
Главный костыль гита — обозвать именованную голову веткой, а отсоединенный коммит — нормой. «Свобода — это рабство, незнание — сила».
И меркуриал вы не знаете — 3 года назад все перечисленное вами уже было.
А может мне кто нибудь пояснить необходимость rebase? Чисто для красоты дерева коммитов что ли?!
Под hg есть плагин, видимо, повторяющий функционал из git, но не могу понять, зачем бы мне захотелось переносить изменения вместо слияния?
Есть замечательная презентация от Mark Jason Dominus: perl.plover.com/classes/git-rebase-wtf/samples/slide001.html
Она многое объясняет.

Применений много. Например, вы накоммитили в локальную ветку кучу коммитов, включая коммиты виды «сделал фичу а», «сделал фичу б», «ой, забыл запятую в фиче a», «починил фичу б», «фича б поломала фичу а, починил её», «отрефакторил фичу б». Никому не интересно в истории видеть все ваши метания с запятыми, фиксами и правкой пробелов. Ребейз позволяет такую историю ужать до «сделал фичу а», «сделал фичу б» и отдать ветку в мир с двумя аккурантыми коммитами.

Другой пример: у вас ветка следит за мастером. Если постоянно вытягивать и мержить мастер в вашу фичеветку, в истории получается «колосок» из мержей, что 1) некрасиво, 2) после пуша только путает историю, т.к. никому неинтересно, когда и как вы подтягивали мастер, 3) добавляет лишний хаос, 4) эти мержи не несут смысловой нагрузки к вашей разработке, итд. Альтернатива: вытягивать master отдельно, а потом фичеветку ребейзить на него. Тогда, когда вы отдадите свою ветку в мир, он будет базироваться на актуальном мастере, история будет ровная, гладкая и шековистая^W^W.

Есть ещё несколько примеров, когда ребейз полезен, в том числе для исравления всяких ошибок и факапов. Я привёл самые частые случаю использования. Рекомендую всё же посмотреть презентацию Mark-а.
Всё это, само собой, имеет для вас смысл, если вы заботитесь о чистоте истории так же, как о чистоте кода. Если вам всё равно, и вы считаете, что чистая история никому не нужно, то ребейз не для вас.
Да, точно. Поймал себя на мысли, что не вижу ценности в «чистой истории».
Очищенная история — это не история, а попытка выдать желаемое за действительное.
Чисто для красоты дерева коммитов что ли?!


Применений много.


Для красоты.
Подписываюсь под каждым словом.
Вытягивать ветку за которой следит текущая можно через pull --rebase, еще проще это прописать в конфиг и делать автоматом при каждом пуле.
НЛО прилетело и опубликовало эту надпись здесь
В релиз пойдёт снэпшот.
У меня длительные проекты и я через какое-то время уперся в то, что история стала просто нереально мусорной — мерджи копились и все это стало напоминать бесконечную пирамиду.
Ну и сам вопрос мерджей — когда сливаются две правки в одну — не очень приятен при больших изменениях.
Гораздо лучше из ситуации «делали две большие фичи параллельно и вот они сливаются в одну кучу» сделать ситуацию «вот сделана одна большая фича, вот за ней сделана другая большая фича» — так история получается линейной и фактически двухуровневой (вместо разрастающейся годами пирамиды). Если при этом ребэйсить правки друг-друга ежедневно, то о проблеме с конфликтами можно забыть окончательно. Гораздо легче разрешить конфликты как только они появились, чем делать это при финальном сведении правок. Поэтому у нас прописан в конфиге pull с опцией rebase — разработчик что-то делает в ветке, если при этом кто-то уже залил в эту ветку какой-то другой функционал, то этот разработчик должен свои правки локально перенести на актуальное состояние ветки — если при этом возникнут конфликты, то он их тут же, по свежей памяти разрешит, а когда он закончит работу над фичей и соберется запушить ее в основную ветку, то она идеально встанет в историю — без конфликтов, поскольку он постоянно актуализировал (ребэйсил) свою работу.
Еще раз повторюсь — для меня это наиболее приемлемый вариант ведения истории по большим долгосрочным проектам с командной разработкой.

Так же у ребэйса есть интерактивный режим — с возможностью объединять и переставлять коммиты — это очень удобно для финального рефакторинга правок.
Ок, понял. На всякий случай уточню: в git ведь не обязательно для актуализации с мастером (при длительной разработке) делать ребэйсы? Просто можно время от времени смерживать актуальные изменения?
На всякий случай уточню: в git ведь не обязательно для актуализации с мастером (при длительной разработке) делать ребэйсы?

не обязательно
Просто можно время от времени смерживать актуальные изменения?

можно

вы вольны выбирать ту схему работы с коммитами, которая вам удобна )))
хочешь кучу merge'ей и видеть реально, кто, что, откуда и когда? — пажалте
не нравится — делайте rebase, и получи «полусинтетическую» «красивую» историю, в том виде, в котором с ней потом удобней работать
дело хозяйское, и SCM Git тому не препятствие ))
Сколько не пытался юзать меркуриал, долго плевался и возвращался на гит. Зачем там дублирование хешей номерами коммитов, для застарелых свнщиков? А ветки там тоже такую боль приносят, чтобы привычнее после свна было? Не знаю, может мой мозг съеден гитом, но мекруриал мне кажется каким-то поломанным и недоделанным подобием гита.
Еще как съеден ;)
В мерке нет отсоединенных коммитов.
В мерке мержатся не два снапшота, а две истории коммитов.
В мерке после мержа двух веток коммиты сохраняют свою изначальную привязку к веткам.
Так что ветки мерка никакой боли не приносят, если воспринимать их именно как ветки, а не именованные головы с предысторией.
Вот чувствую там что-то прекрасное, но не могу никак понять, что именно и зачем?
Что дает отсутствие отсоединенных коммитов?
Чем хороша привязка коммита к ветке? У меня в git программист запушил в release то, что должно было быть в hotfix (или поменялись приоритеты и что-то из релиза нужно выложить срочно) — я просто перекинул коммит из ветки в ветку. Это равнозначно тому, что задача изначально и была бы сделана в нужной ветке. Зачем мне чтобы коммиты были привязаны навсегда к своей ветке? Или я неправильно понимаю и это работает как-то по другому?
Если работать только с мерджами разве не будет история похожа на карту метро? Или всегда все в мерке делается идеально? Или тоже ребэйсится для улучшения истории?
Чем мержить две истории лучше, чем мерждить два снапшота? Чем мердж двух историй отличается от ребэйса?
Мердж он и есть мердж — две ветки сводятся в одну. Мне кажется это вообще в истории неправильное действие и я пользуюсь ребэйсом.
Ветки у меня и в git есть — но я их контролирую самостоятельно, а не на уровне движка. Но не пойму, в чем именно профит?
Отсоединенные коммиты — чем плохи? Если я выкачиваю из gerrit что-то чего у меня в истории нет, конечно будет отсоединенный коммит. Ну и пусть будет (это ведь так — не к чему ему привязываться), в чем проблема? А если мне он нужен будет в истории, я его перекину cherri-pick'ом и запушу в одну из веток. Это ведь так и должно быть. Что здесь страшного? Как это решается в мерке? Видимо за счет физических веток выкачивается всегда вся история?
А как быть с тем, что мои ветки — это мои ветки. И у каждого программиста так. В git я сам решаю какую локальную ветку в какую удаленную закинуть, сколько веток иметь в какой момент времени и это очень удобно и очень гибко. Это главное в git.
Git мне чем-то напоминает регулярные выражения. Когда понимаешь, как он работает, ты можешь делать все, что угодно очень легко и изящно.

Вопросы искренние, затронули интересную тему — хочется понять. Есть ощущение, что мерк навязывает тот процесс, который я выстроил в git, но только уже на уровне системы. Это должно быть здорово, но это ведь должно и ограничивать? Не будет той гибкости за которую я так люблю git. Или я неправ?
Про мерк слышал много хорошего, но ведь у меня в git все то же самое, разве нет?
НЛО прилетело и опубликовало эту надпись здесь
Git мне чем-то напоминает регулярные выражения. Когда понимаешь, как он работает, ты можешь делать все, что угодно очень легко и изящно.

хорошо сказано! ))
Только хрен кто поймёт, что и как ты сделал. Результат есть, а процесс, как говорится, write-only.
что означает «вы не понимаете регулярок» :))))))))
мдааа… вот уж не предполагал, что и среди DVCS могут быть холивары!
Если вы пытаетесь решить проблему регулярками, то проблем у вас уже две ;)
Комбинаторные парсеры не пробовали?
не, не пробовал
честно говоря, от Вас первый раз про такое слышу ))) почитаю

но у меня и нет проблем ни с регулярками, ни с Git'ом ))))
А мне Git напоминает стеклянную банку кетчупа с узким горлом, к которой прилагается специальная ложечка и книжка в 200 страниц о том, как правильно его выковыривать.

В то время как можно его просто выдавливать. Ок, процесс выдавливания, возможно, не столь эстетичен, и что-то даже теряется по дороге. Но как-то зато быстро и вкусно.
хм… вообще-то в Git как раз в полный рост TMTOWTDI
даже закоммитить нет единственного способа:
git add --update && git commit vs git commit --all

З.Ы. а вот «потерять по дороге» в Git непросто, да )) и в этом-то и смак
Способ по‐прежнему единственный — git commit. Просто как и с git checkout -b налицо прямое нарушение принципа разделения обязанностей: git commit --all с какой‐то радости что‐то делает с индексом (для чего есть тот же git add), git checkout -b с какой‐то радости создаёт новую закладку (для чего есть git branch).

Вы ещё можете вспомнить про команды более низкого уровня (вроде git commit-tree), но «спуск на уровень ниже» ≠ «нахождению другого способа что‐то сделать». В некоторой степени пару git add && git commit можно рассматривать как что‐то на уровень ниже git commit --all. Или, скорее, второе как alias первого.
я (честно!) не знаю, что ответить на такие претензии (как по мне, так формальные) к SCM, суть которой всё же несколько в другом, нежели синтаксис её команд
да, я заметил, что Git — не для всех, а так судя по таким холиварам — вообще для гикнутых гиков…
очевидно — непрост. вероятно — сложен. но бесконечно мощен и прекрасен )))
и тут меня не переубедить ))
НЛО прилетело и опубликовало эту надпись здесь
это проблема функционала? или всё же архитектуры?
каким образом меня, как пользователя, касается внутренняя красота кода Git (хотя я отправлял пару патчей)?

*а зачем Вам Git в shared library?

НЛО прилетело и опубликовало эту надпись здесь
ну, то есть «очень хочется Git, но невозможно»?
может, посмотреть на другие DVCS? вот пресловутый Hg можно так использовать?
У mercurial довольно стабильный внутренний API, но официально, если вам нужно куда‐то встроить mercurial, поднимайте command server и общайтесь с ним, передавая команды типа commit (т.е. то же, что и через командную строку). hg … — тоже официальный внешний API, как и command server (преимущества command server — нужен один fork+exec и одна инициализация Python). А внутренний только для дополнений, остальное на свой страх и риск.

А сложение репозитория не на диск к наличию shared library вообще никаким боком не относится. В libgit2 такое сделали, но это не потому, что они shared library, а потому что у них архитектура не такая кривая. С обычным git такое тоже можно было бы учудить, создав механизм а‐ля модули в zsh (т.е. подгружаемые библиотеки, при том API позволяет сделать множество интересных вещей: я, к примеру, делал возможность использовать Python непосредственно в процессе оболочки, а кто‐то добавил через модули переменные, ограниченные одной функцией (обычно локальные переменные доступны для вызываемых функций, zsh/param/private добавляет локальные переменные, недоступные для вызываемых функций)).
Про «мощен» я уже не раз говорил: mercurial позволяет запихать в себя всё, что угодно, только пишите дополнения, архитектура позволяет, а хорошие идеи авторы примут. В git вам что дали, с тем вы и сидите. Все дополнения — мелкая косметика. Зато есть куча адептов, кричащих о его мощи.

У mercurial есть мощь: evolve, ветки, закладки, фазы, возможности в протоколе, позволяющие, к примеру, потребовать от пользователя включить largefiles до клонирования (git — аналог работает на gitattributes, отказ происходит после clone) или полностью проигнорировать фазы (для старых клиентов). И всё это развивается со временем. Бесконечностью пахнет только здесь, где вы вставляете в ядро такой сложный концепт, как obscolescence markers (этот тот самый evolve)… с помощью дополнения. Дополнения, устанавливаемого любым пользователем, а не отдельной веткой с новой функциональностью и с необходимостью пользователю иметь квалификацию и время на сборку и установку с решением сопутствующих проблем.

У git есть своя мощь, но нет ни инфраструктуры для её наращивания, ни развития. Фактически, единственное, что мне совершенно не хватает в mercurial — удобное редактирование истории — станет ущербным в сравнении с mercurial после evolve в релизе с поддержкой его bitbucket’ом. Может libgit2 здесь что‐то когда‐нибудь исправит (насколько я помню, там, как минимум, есть возможность полностью заменить принцип хранения данных (т.е., к примеру, поместить всё в базу данных)). Но я бы не надеялся на libgit2 в upstream.
ну, кому что ))
у Hg, как видим, тоже есть куча адептов ))) и каждый по-своему прав )) и слава Б )))
> а вот «потерять по дороге» в Git непросто, да
Правда? Отсоединенный коммит получить не просто, а очень просто. Да, с помощью командной строки, рефлога и какой-то матери все можно вернуть до сборки мусора, но осадочек остается.

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

Отсоединенный коммит получить не просто, а очень просто.

ну и что? Вы его ПОТЕРЯЛИ при этом? совсем? навсегда?

Да, с помощью командной строки, рефлога и какой-то матери все можно вернуть до сборки мусора

ну, видите же,. — можно! ))) для меня это — ключевое слово.
удалённый файл в NTFS/FAT32 восстановить же можно? можно! только спецтулзами… только в FAT32 они могут похериться «сами просто так», а отличие от NTFS…

а как часто у вас сборщик мусора вызывается?
а то я вот активно делаю рибейсы, а вот сборщик раз в 3 месяца, дай Б, вижу

как по мне, так в итоге все «недостатки» Git'а сводятся к его непониманию ))) а я его понимаю — и тут, извините, я на коне )))

З.Ы. мне это напоминает чем-то жён, которые не хотят ездить на машине с «ручкой», а только на автомате:
«там всё так сложно, надо одновременно сцепление и газ… чуть не так — заглохнет»… и т.п. по мне — так «дело вкуса»… благо — альтернативы есть )))
НЛО прилетело и опубликовало эту надпись здесь
Напоминаю, что сборщик мусора всегда ограничивается только старыми изменениями. Насколько старыми задаётся в настройках, но по‐умолчанию это две недели (см. gc.pruneExpire в git help config).
:)

Напоминаю, что по умолчанию рефлоги хранятся и не трогаются сборщиком мусора аж 90 дней.


С трудом представляю себе ситуацию, когда программист пишет код, коммитит его в виде отсоединенного коммита — и забывает про него на 3 месяца, после чего жалуется что гит плохой :)

Ну и как часто вы получали отсоединённый коммит? Лично я — чуть чаще чем никогда.
Новичку такое сделать просто. Прогнали git bisect и начали исправлять проблему, не сделав git bisect reset. Решили поработать в «ветке» origin/master вместо master. Решили посмотреть «как оно там в изменении deadbeef» и забыли сделать checkout обратно в ветку. Решили поработать в «ветке» pulls/42/head. Я такого уже почти никогда не допускаю, но «прострелить себе ногу» вполне можно.

(Кстати, в powerline я вполне себе делаю отсоединённое изменение намеренно. Сливать их с develop вполне можно, ссылаясь как HEAD@{1}, а создавать имена для веток не всегда охота: получается что‐то вроде временных веток для простых (т.е. не требующих прогона тестов) изменений вроде изменений в документации.)
Новичок станет делать git bisect? Если человек уже узнал про git bisect и начал его использовать, то вряд ли он «новичок». А за git checkout origin/master без понимания процесса нужно бить по рукам. Ну и в случае git checkout который приводит к detached head гит выдаёт здоровенный текстовый баннер с подробным описанием, что вы сейчас в «detached HEAD», что нужно сделать «git checkout -b branch» чтобы сохранить изменения и т.д., и т.п. Так что тут ещё и нужно не уметь читать, чтобы так лопухнуться.
Новичок в git и новичок в DVCS — две большие разницы.
А помимо консоли есть еще и GUI.
Вдобавок в том же мерке анонимная ветка сама по себе абсолютно нормальна, и совершенно непонятно, с какого перепугу гит считает ее мусором.
А почему нет? Помимо того, что есть mercurial, в котором тоже есть bisect, ещё существует вариант, когда человек приходит в issue tracker, говорит о своей проблеме, а его просят сделать bisect. Чтобы его сделать не нужно читать умных книг про git, нужны просто минимальные навыки поиска в Google или прочтение части git help bisect (кстати, слово «detached» здесь нигде не упоминается). Кстати, git checkout -b branch во многих случаях не является правильным способом решить проблему: в случае того же bisect вы вполне можете хотеть зафиксировать изменение в какой‐то существующей ветке‐закладке. И почти наверняка хотите иметь какую‐то закладку в качестве родителя, а не изменение где‐то посередине. И проще всего первое делать через stash→checkout→stash apply (второе, впрочем, через checkout -b→rebase). Впрочем, это неважно, т.к. вместо большого предупреждения при commit вы получите просто [detached HEAD {hash}] msg… на первой строке из трёх.

И да, хороший интерфейс не тот, который выплёвывает вам в лицо длинные предупреждения. А тот, где предупреждения не требуются. А про предупреждение, кстати, можно отвлечься на что‐то и забыть.
Не хвататься за оголенные провода несложно.
Понять, почему на обычном рабочем месте изоляция на проводах отсутствует, гораздо сложнее.
Еще сложнее понять тех, кто продает все это как достоинства инструмента.
Поскольку никто не объяснил, то мне кажется я понял сам. Не уверен, что правильно, и конечно, слегка провакационно (может хоть так спровоцирую на разъяснение), но по крайней мере в моей вселенной все с таким объяснением встает на свои места:
Мерк — попытка не разобравшись с логикой Git сделать все так, как было в Svn — чтобы ветки были железобетонные, чтобы add добавлял в репозиторий, а не в коммит,… Я через это проходил при миграции, и мне кажется это неправильно. Git лучше, чем Svn, а динамические ветки лучше предопределенных — гораздо продуктивнее научиться пользоваться новым инструментом вместо того, чтобы продолжать мыслить старой парадигмой.
Чем ветки мерка «старее» веток гита? Чем они хуже? Я начал использовать svn гораздо позже гита и мерка, его идеология надо мной не довлела, я изучал обе современные системы параллельно, ничего не зная про устаревшую. Подход мерка мне кажется разумнее: лучше хранить больше информации о коммите, чем меньше — игнорировать проще чем, строить догадки.
Если вы не знали, при старте обоих проектов (Git и mercurial) исходные данные были для обоих одинаковыми. Для исходников Linux был выбран Git по вполне понятным причинам. Соответственно и для других подобный авторитет оказался решающим.
НЛО прилетело и опубликовало эту надпись здесь
Спасибо за информацию.
Ну значит был неправ, но только в плане «не разобравшись с логикой Git». Тем более верно мое ощущение и предположение что логика Svn в мерке присутствует (поскольку на момент разработки обоих версий Svn был мэйнстримом), в отличие от Git, который реализует совсем другую концепцию.
А то, что Git при этом стал более популярным только говорит в его пользу.
У меня ощущение дежа-вю с ситуацией mootools + jQuery. Mootools был очень приятным внутри, с классами и архитектурой, но jQuery был проще, гибче и имел очень удобный механизм поиска элементов на странице (такая же удобная система веток и в Git — работа с ветками очень легкая, гибкая и простая) и за счет этого стал популярнее. До сих пор с ужасом вспоминаю процесс миграции проектов в mootols на jQuery. Лучше сразу делать правильный выбор.
Да, скорее всего, мерк внутри красивее — об этом много слышу, но по складывающейся ситуации этого явно недостаточно и вряд ли ситуация уже изменится.
Тем не менее хорошо, что он есть, поскольку конкуренция в любой среде — это хорошо.
А то, что Git при этом стал более популярным только говорит в его пользу.

Если бы святой Торвальс поддержал HG, то ситуация была бы иной.
Git — работа с ветками очень легкая, гибкая и простая

О лёгкости работы в git написано уже 100500 статей.
А вот Джобс считал, что хорошему интерфейсу мануалы не нужны. В моей практике, чтобы научить человека hg, достаточно поставить UI и показать как оно работает. Чтобы научить человека git-у, нужно «понять» гит в консоли.
Поймите, если бы Git был столь ужасен, как вы пишите, никакой святой Торвальдс не смог бы сделать его популярным, тем более, при наличии такого великолепного конкурента.
А я и не говорю, что git ужасный. Ему просто не повезло из тула для написания линуксов стать индустриальным стандартом.
НЛО прилетело и опубликовало эту надпись здесь
Я бы согласился с тем, что «логика svn присутствует», потому как после svn начать использовать мерк очень просто. То есть, базовые действия не вызывают затруднений, и даже распределённая структура не вызывает.

Один адепт мерка буквально говорил, что svn — говно. Я просил объяснить, чем же он отличается от мерка, в его понимании, кроме того, что кроме перед update в мерке он вводит pull, а после commit — push. Не смог он ничего объяснить — воркфлоу был идентичный, распределённая структура не использовалась, ветки в мерке не использовались (до них в то время ещё было как до луны); да если бы они и использовались, это было бы сделано по модели svn. Наезды были в духе «потому что». А, ещё он однажды заблочил базу коллизий svnа, создав в рабочей копии файлы от другой учётной записи, так что у svnа не было прав с ними что-то делать, и он от греха заблокировался. Я вот утверждаю, что в этой ситуации «сам дурак», а svn всё правильно сделал.

Чего нельзя сказать про гит. Гит кажется невменяемым после любой другой vcs. Пока не почитаешь документацию (и не поломаешь голову) — не осилишь.
Так я его и так почти боготворю!
> он перерос VCS, которую использовал, поэтому Линус решил написать новую, т.к. он программист, а именно этим мы и занимаемся.
А я думал, что это потому, что их VCS отказала линуксоидам в когда-то выданной бесплатной лицензии за то, что ребята попытались её хакнуть…
пруф будет?
НЛО прилетело и опубликовало эту надпись здесь
Пруф дали, пока шёл до планшета
Историю надо знать ;)
теперь знаю
не могу понять как это работает
git-scm.com/docs/git-request-pull
знает кто? я всегда думал что нельзя делать пул-реквесты напрямую из дефолтной консоли
НЛО прилетело и опубликовало эту надпись здесь
Попробуйте другой пример, должно сработать:
git clone https://github.com/torvalds/linux
:)
Статья интересна но написана сложно, в комментах много споров на тему 2 + 2 = 4? Вы уверены?
Все что нужно для GIT это прочитать книгу -> Pro Git book или скачать PDF вариант.
Спасибо за перевод.
Для тех, кто хочет разобраться, как работает git, но лучше соображает с картинками, есть замечательная «Наглядная справка по git»: marklodato.github.io/visual-git-guide/index-en.html
Я не знаю как они работают, но пользователи Mercurial рассказывали мне, что это такая боль в заднице, что никто на самом деле их больше не использует.

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

image

Даже джуниоров без проблем обучаем работе с ветками. Никто в команде ни разу не сталкивался ни с какими проблемами, кроме конфликтов. Быть может, всё дело в волшебном TortoiseHG, который работает так как ты этого ожидаешь с первого раза даже без чтения документации. Я уж не говорю про статьи на хабре на 20 (!!!) страниц.

К нам в команду часто приходят фанаты и адепты ГИТа и очень неохотно переучиваются на мерк. Я вижу как людей это злит и бесит. Но никто ещё, ни один человек не смог объяснить мне чем гит лучше? Какие функции есть в гите, которых нет в мерке? В мерке есть всё, но реализовано гораздо проще. ГИТ — это первая изобретённая Dcvs. Но не идеальная, как первый блин. Мерк — это, можно сказать, форк от гита в котором реализовали всё тоже самое, но значительно проще.

К моему сожалению, эта не удобная система стала более популярна но явно не благодаря своей простоте. Возможно дело в эко-системе? Популярный Линус и ещё более популярный GitHub сделали своё дело, но не сам гит.

Понимаю, что сейчас минусов нахватаю за не популярную точку зрения :(
Аналогично сложно объяснить чем Мерк принципиально лучше Гита.
Привычка.
Если не считать эко-систему и GitHub, то сам по себе git ничем не лучше мерка, потому что в мерке есть весь тот же самый функционал, но проще.
НЛО прилетело и опубликовало эту надпись здесь
Есть информация в каждом коммите, из какой ветки он пришел. В команде из 10+ человек бывает очень полезно.
НЛО прилетело и опубликовало эту надпись здесь
В гите таки нет. Коммит хранит ссылку на родительские коммиты и все. «Ветка» гита — ссылка на коммит и не более того.
но коммит-то + все его родители — это и есть сама «ветка изменений» (а нам ведь онА важна), и она видна, и доступна
а как она называлась — до этого дело, видимо, только меркуриаловцам…
Нет, коммит+все его родители — это не ветка изменений. Пример: я только что-то сделал ветку от другой ветки — сейчас у меня в ветке ноль коммитов, гит же считает, что моя ветка все коммиты до первого. Гит не знает ответвлялся я от коммита в ветке дев или мастер — для него дев и мастер когда указывают на один коммит абсолютно равнозначны.
это так, да…
только в чём тут проблема?
Гит не хранит истории работы с ветками. Для кого-то это проблема, которую надо решать другими способами (например, заставлять разработчиков писать название ветки в коммите и бить по рукам за то не указывают, или указывают неверно), для кого-то неудобство, кому-то всё равно, а кому-то может даже эта информация мешать будет.
полагаю, все претензии рода, подобного обсуждаемому, к SCM — сублимация претензий к разрабам, не следующим гайдам «Как писать хорошие сообщения коммитов»

за сообщения коммитов ваще драть надо ))))
Это скорее претензии разрабов: у SCM есть информация о том, в какой ветке я делаю коммит, но она в коммит не пишет, потому меня ПМ заставляет руками писать.
ну, раз уж, используя Git, нужно имя ветки в сообщении коммита, чтобы не писать руками, можно/нужно использовать prepare-commit-msg hook

а как выглядят сообщения коммитов у вас? *интересно
Хуки — штука хорошая, но для данного случая, пожалуй, оверкилл.
ну, лучше, конечно, сетовать на SCM, что она не хранит имена веток и ручками каждый раз писать, да )))
Зачем сетовать? Можно взять SCM, которая для такой простейшей вещи хуков не требует.
В случае гита гайд толще, а сообщения многословнее, потому что приходится дублировать в сообщении коммита информацию, которая уже есть в имени ветки.
видимо, вам хватает ли вам одной лишь имени ветки, чтобы узнать что, зачем да почему…
я же предпочитаю (как рекомендуют, а в разработке самого Git — требуют), знать это из сообщения коммита
и когда надо по быстрому глянуть, мне такой лог
Заголовок спойлера
git log --graph --oneline
*   c43413e Merged: fixed: #644: Ошибка при рассылке e-mail.
|\  
| * e25152f fixed: #644: Ошибка при рассылке e-mail.
| * edbbd74 issue #644: improve: tests: add TMailSender.InitService[Params] tests
| * 2befdc3 fixed: tests: fake SMTP-server: possible "stream is closed" error
| * 266c11c refactoring: tests: fake SMTP-server: add a space
| * 8d1b795 refactoring: tests: fake SMTP-server: log incoming request BEFORE its processing
| * ebcb002 issue #644: refactoring: tests: fake SMTP-server: add tests
| * 30157bf issue #644: refactoring: tests: fake SMTP-server: rename authenticator classes
| * 6dbd039 issue #644: refactoring: tests: fake SMTP-server: lib/auth: introduce SMTP module
|/  
* c096916 fixed: #472: Ошибка при установке АС.
*   c5d7dee Merged: issue #644: improve: tests: добавить тестовыe SMTP-серверы с LOGIN-аутентификацией
|\  
| * b2b96c7 issue #644: improve: tests: добавить тестовыe SMTP-серверы с LOGIN-аутентификацией
| * 6909136 issue #644: fixed: tests: тестовый SMTP-server PLAIN не работает, если параметр задавать позже
| * cb12e39 issue #644: refactoring: tests: fake SMTP-server
| * 4cafc56 issue #644: fixed: tests: тестовый SMTP-сервер с PLAIN аутентификацией "пускает" с пустыми логином и паролем
| * 905d7d6 issue #644: improve: tests: fake SMTP-servers: добавить ключ запуска --extend-with-shutdown
| * d96eef1 issue #644: improve: tests: fake SMTP-servers: добавить ключ запуска --debug
| * c96652f issue #644: improve: introduce EUnknownMessageSenderException
| * fdc3693 issue #644: tests: fake SMTP-server: уточнить текст ошибки при неверном методе аутентификации
| * af2375e issue #644: refactoring: tests: fake SMTP-server: rename classes (remove "T" prefix)
| * 577ed4b issue #644: improve: tests: avoid processor load
| * a45a153 issue #644: refactoring: tests: fake SMTP-server: add module SMTP
|/  
* 8baa7d6 refactoring: tests: avoid compiler warning
* 87913f6 issues #624, #625, #637: rake: add "prepare:accompanies:mail:..." tasks
*   4a44395 Merged: fixed: #643: Пропала компенсация из списка.
|\  
| * 02065f2 fixed: #643: Пропала компенсация из списка.
| * 7be70bd issues #607, #643: improve: добавить скрипт для анонимизации БД
|/  
*   206e9d3 Merged: refactoring: update lib/CF, lib/Common
|\  
| * aa2035b refactoring: update lib/CF, lib/Common
| * 7c90634 fixed: TUpdater зависает, если при вызове .Start происходит исключение
| * b55d639 refactoring: убрать директивы условной компиляции Indep и AladdinSupport
| * ba54807 refactoring: убрать директиву условной компиляции ASK_GROUP_SAVE
|/  
* 188a580 refactoring: tests: use const keyword for string parameters
* bb51653 fixed: tests: `TTestTimeoutsSetup` is shown as `imeouts`

оно же, но полное:
git log --graph --decorate
Скрытый текст
*   commit c43413eb9199a3797157d821a366f051e8703758 (HEAD -> devel, tag: v3.0.157, origin/branch-v3.0)
|\  Merge: c096916 e25152f
| | Author: ***Developer***
| | Date:   Thu Oct 22 11:19:45 2015 +0300
| | 
| |     Merged: fixed: #644: Ошибка при рассылке e-mail.
| |   
| * commit e25152f57a18d25dff44d06858bc46ceb0c77ac0
| | Author: ***Developer***
| | Date:   Thu Oct 22 11:19:23 2015 +0300
| | 
| |     fixed: #644: Ошибка при рассылке e-mail.
| |     
| |     При рассылке e-mail используется тип авторизации AutoSelect, что значит,
| |     что авторизация БУДЕТ выполняться, если сервер её поддерживает, даже
| |     если логин/пароль не заданы.
| |     До сих пор это работало. Пока не появился клиент с сервером, который
| |     поддерживает и авторизацию, и анонимную рассылку, и этот сервер постоянно
| |     запрашивает имя пользователя (которое не задано, т.к. пользователь
| |     знает, что сервер может рассылать и анонимно)
| |     (см. 6909136 (issue #644: fixed: tests: тестовый SMTP-server PLAIN не
| |     работает, если параметр задавать позже, 2015-10-19)).
| |     
| |     Доработаем АС так, что он при будет пытаться авторизоваться на
| |     SMTP-сервере (с типом AutoSelect), только если задан логин.
| |     
| |     З.Ы. А в тестах нужно доработать SMTP-серверы так, чтобы они
| |     обрабатывали аутентификацию одной сессии за раз, и могли поддерживать и
| |     анонимную рассылку тоже (по флагу).
| |   
| * commit edbbd74f03550a6a47560ecc59a1c848cab817f5
| | Author: ***Developer***
| | Date:   Wed Oct 21 18:46:59 2015 +0300
| | 
| |     issue #644: improve: tests: add TMailSender.InitService[Params] tests
| |   
| * commit 2befdc3a7325bc71dfd10b3760ce58952bdd3b3b
| | Author: ***Developer***
| | Date:   Wed Oct 21 17:51:34 2015 +0300
| | 
| |     fixed: tests: fake SMTP-server: possible "stream is closed" error
| |     
| |     Обычно выход из цикла обработки входящих команд происходит по команде,
| |     но может и по закрытию потока. Однако, в этом случае запись в поток
| |     вызовет ошибку, чего нам не надо.
| |     
| |     Будем проверять поток на закрытие перед попыткой в него писать.
| |   
| * commit 266c11c41563022386bd2a78a3ef8d5c48196604
| | Author: ***Developer***
| | Date:   Wed Oct 21 17:50:13 2015 +0300
| | 
| |     refactoring: tests: fake SMTP-server: add a space
| |   
| * commit 8d1b795c5aece2d463e97c26963d801a1a4420d7
| | Author: ***Developer***
| | Date:   Wed Oct 21 17:49:12 2015 +0300
| | 
| |     refactoring: tests: fake SMTP-server: log incoming request BEFORE its processing
| |   
| * commit ebcb00245337614cca4ad2a38b88102c42a4f7d5
| | Author: ***Developer***
| | Date:   Tue Oct 20 14:49:47 2015 +0300
| | 
| |     issue #644: refactoring: tests: fake SMTP-server: add tests
| |     
| |     Add missing tests.
| |   
| * commit 30157bf5a02e4da8a3939353e5de225ee77171dd
| | Author: ***Developer***
| | Date:   Tue Oct 20 14:37:42 2015 +0300
| | 
| |     issue #644: refactoring: tests: fake SMTP-server: rename authenticator classes
| |     
| |     Remove "T"-prefix.
| |   
| * commit 6dbd039f033f80d7dda5e8b14a77affb5b973802
|/  Author: ***Developer***
|   Date:   Tue Oct 20 14:33:00 2015 +0300
|   
|       issue #644: refactoring: tests: fake SMTP-server: lib/auth: introduce SMTP module
|  
* commit c096916c2fa92ac02a883f6f60e4393d1abaaee3 (tag: v3.0.156)
| Author: ***Developer***
| Date:   Wed Oct 21 14:13:32 2015 +0300
| 
|     fixed: #472: Ошибка при установке ...
|     
|     Решили усложнить пароль для пользователя "..." при установке MS
|     SQL-сервера, т.к. на серверах часто включены политики сложного пароля.
|     
|     Пароль "...." вполне удовлетворяет самым строгим политикам.
|    
*   commit c5d7dee3bbba6538b9d844bb47709889e2ca3021
|\  Merge: 8baa7d6 b2b96c7
| | Author: ***Developer***
| | Date:   Mon Oct 19 15:37:14 2015 +0300
| | 
| |     Merged: issue #644: improve: tests: добавить тестовыe SMTP-серверы с LOGIN-аутентификацией
| |   
| * commit b2b96c7a3ac662fe50ad9787fa6d85fdfc04e110
| | Author: ***Developer***
| | Date:   Mon Oct 19 15:35:59 2015 +0300
| | 
| |     issue #644: improve: tests: добавить тестовыe SMTP-серверы с LOGIN-аутентификацией
| |     
| |     Один из них симулирует поведение сервера, который в ответ на MAIL FROM
| |     выдаёт 334 Password: при попытке анонимной отправки.
| |   
| * commit 69091362a1bba12c8f2f06e18a6a1a2e8b11e270
| | Author: ***Developer***
| | Date:   Mon Oct 19 13:14:06 2015 +0300
| | 
| |     issue #644: fixed: tests: тестовый SMTP-server PLAIN не работает, если параметр задавать позже
| |     
| |     Сервер с PLAIN аутентификацией работает, только если использовать
| |     параметр во время команды
| |       AUTH PLAIN <...>
| |       235 Authentication successful
| |     
| |     но НЕ если захотим использовать схему
| |       AUTH PLAIN
| |       334
| |       <...>
| |       235 Authentication successful
| |     
| |     И хотя наш SMTP-клиент использует первый вариант, исправим это, т.к.
| |     дальше мы добавим LOGIN-аутентификацию, которая работает по похожей
| |     схеме.
| |     Заодно уберём текст "Username:" в ответе 334.
| |   
| * commit cb12e395078cbeee22d5c492d98a5bf90b0fa4eb
| | Author: ***Developer***
| | Date:   Fri Oct 16 17:32:24 2015 +0300
| | 
| |     issue #644: refactoring: tests: fake SMTP-server
| |     
| |     Rename @pass to @password. Initialize @login and @password.
| |   
| * commit 4cafc56b15cdb287e3c6c6869ed0dccdff2caf9e
| | Author: ***Developer***
| | Date:   Fri Oct 16 15:23:40 2015 +0300
| | 
| |     issue #644: fixed: tests: тестовый SMTP-сервер с PLAIN аутентификацией "пускает" с пустыми логином и паролем
| |     
| |     Хотя не должен, должен пускать с непустым логином (и, как и раньше,
| |     паролем, равным логину).
| |   
| * commit 905d7d6103bde4f37ec446f8f5c1f95b49103c5f
| | Author: ***Developer***
| | Date:   Mon Oct 19 12:20:50 2015 +0300
| | 
| |     issue #644: improve: tests: fake SMTP-servers: добавить ключ запуска
| |     --extend-with-shutdown
| |     
| |     В тестах используется команда SHUTDOWN, которая завершает работу сервера
| |     (чтобы не приходилось "прибивать" процессы). Клиент посылает, а сервер
| |     корректно обрабатывает эту команду.
| |     Однако, иногда приходится запускать скрипт smtp-server.rb "вручную", и
| |     тогда не очень нужно, чтобы серверы завершали работу после "прогона"
| |     тестов.
| |     Так что сделаем опцией команду SHUTDOWN.
| |   
| * commit d96eef1a70633e28e249a1011ee686b94b368f79
| | Author: ***Developer***
| | Date:   Fri Oct 16 15:24:59 2015 +0300
| | 
| |     issue #644: improve: tests: fake SMTP-servers: добавить ключ запуска --debug
| |   
| * commit c96652fb687c17744e50ba5d1f60d987717fdc5d
| | Author: ***Developer***
| | Date:   Mon Oct 19 13:56:26 2015 +0300
| | 
| |     issue #644: improve: introduce EUnknownMessageSenderException
| |     
| |     В тестах нужно определять, что ошибка неизвестная, а та же
| |     EAuthSenderException, например, - наследник от EMessageSenderException,
| |     что не даёт уверенности, что возникла не она. Поэтому нужно ввести
| |     специальный тип исключения - EUnknownMessageSenderException.
| |   
| * commit fdc3693263f1768ef62d037850f50f304ded71a6
| | Author: ***Developer***
| | Date:   Fri Oct 16 14:44:44 2015 +0300
| | 
| |     issue #644: tests: fake SMTP-server: уточнить текст ошибки при неверном методе аутентификации
| |     
| |     При неверном методе аутентификации выдаётся ошибка с текстом "Unknown
| |     command", хотя лучше выдавать "Unknown authentication type".
| |   
| * commit af2375ea04e4d51494bb352a40ef77a60e0fe2bf
| | Author: ***Developer***
| | Date:   Mon Oct 19 12:00:18 2015 +0300
| | 
| |     issue #644: refactoring: tests: fake SMTP-server: rename classes (remove "T" prefix)
| |   
| * commit 577ed4b4b173a30ff13e2a97ebc0b3d37f12311e
| | Author: ***Developer***
| | Date:   Mon Oct 19 12:58:57 2015 +0300
| | 
| |     issue #644: improve: tests: avoid processor load
| |     
| |     Sleep in a loop
| |   
| * commit a45a1536176b30801ac2820b2e9403bb3fd8b1af
|/  Author: ***Developer***
|   Date:   Mon Oct 19 11:54:55 2015 +0300
|   
|       issue #644: refactoring: tests: fake SMTP-server: add module SMTP
|  
* commit 8baa7d698231cbb880a2ab5ed54e721ad270268f
| Author: ***Developer***
| Date:   Mon Oct 19 15:30:44 2015 +0300
| 
|     refactoring: tests: avoid compiler warning
|  
* commit 87913f6f4263d02bb3456d6ebeba39d6b6fa1d1f
| Author: ***Developer***
| Date:   Tue Oct 6 12:53:30 2015 +0300
| 
|     issues #624, #625, #637: rake: add "prepare:accompanies:mail:..." tasks
|     
|     Google Mail не позволяет отсылать исполняемые и командные файлы даже в
|     .zip-архивах. Поэтому их нужно переименовывать, добавляя, например, знак
|     подчёркивания суффиксом. Автоматизируем это.
|    
*   commit 4a443957ef3b946a76876335d4fe4ef3de961d69 (tag: v3.0.155)
|\  Merge: 206e9d3 02065f2
| | Author: ***Developer***
| | Date:   Tue Oct 13 15:19:01 2015 +0300
| | 
| |     Merged: fixed: #643: Пропала компенсация из списка.
| |   
| * commit 02065f2756b834507961a57cc68e8d1951e4a9e0
| | Author: ***Developer***
| | Date:   Tue Oct 13 12:52:40 2015 +0300
| | 
| |     fixed: #643: Пропала компенсация из списка.
| |     
| |     Если при добавлении/редактировании компенсации её название совпадёт с
| |     наименованием НАЧИСЛЕНИЯ, и после сообщения об ошибке об этом исправить
| |     название компенсации и сохранить её, то она "пропадёт" из дерева
| |     компенсаций.
| |     Происходит это потому, что при проверке на дубликат названия, получается
| |     и тип этого дубликата (если он есть), и тип компенсации ошибочно
| |     изменяется на этот тип, что сказывается при её сохранении.
| |     
| |     Исправим это, не изменяя тип компенсации при проверке на дубликат.
| |   
| * commit 7be70bd51a2d35280fb64519e3c79f6f62a64497
|/  Author: ***Developer***
|   Date:   Wed Jun 3 11:05:16 2015 +0200
|   
|       issues #607, #643: improve: добавить скрипт для анонимизации БД
|       
|       Некоторые абоненты не хотят давать БД по соображениям конфиденциальности
|       Таким мы можем предложить следующий скрипт, который преобразовывает
|       имена абонетов и групп в имя вида Contractor/Group-<ID>-<номер_телефона>
|       
|       UPDATE c
|       SET ....
|       FROM dbo.b_Co....
|       LEFT JOIN dbo.Vi....
|          ON  t.ID_....
|    
*   commit 206e9d33703cd997d277a5f10e37f122757b976e
|\  Merge: 188a580 aa2035b
| | Author: ***Developer***
| | Date:   Tue Oct 13 15:17:53 2015 +0300
| | 
| |     Merged: refactoring: update lib/CF, lib/Common
| |   
| * commit aa2035b9dadaa86e16c7b687382f0ad629f5c624
| | Author: ***Developer***
| | Date:   Thu Oct 8 15:20:02 2015 +0300
| | 
| |     refactoring: update lib/CF, lib/Common
| |     
| |     Модули CF, Common обновлены: добавлены директивый условной компиляции
| |     URLREADER_USE_PROXY и URLREADER_USE_BASEUNIT.
| |     
| |     И т.к. мы всегда используем XMLHTTPRequest, то флаг не нужен.
| |     
| |     Submodule lib/CF 038eab1..c80a287:
| |       > refactoring: avoid BaseUnit dependency
| |     Submodule lib/Common 580a371..895856f:
| |       > improve: introduce TInternetOpenClient class
| |       > refactoring: removed commented code
| |   
| * commit 7c9063457fc9c5f4d27e490fabcee183359c92cf
| | Author: ***Developer***
| | Date:   Tue Oct 13 13:46:39 2015 +0300
| | 
| |     fixed: TUpdater зависает, если при вызове .Start происходит исключение
| |     
| |     В деструкторе ожидается обнуление FCurrent, однако, если при Start
| |     вызовется исключение, отчего не вызовется FreeOnTerminatе, который
| |     вызывает FreeCurrent, то деструктор "повиснет" в бесконечном цикле.
| |   
...
---cut---




кажется более юзабельным, нежели вот у товарища Joshua
Полагаю, что настолько полный дубликат таск-трекера в репе нужен далеко не всем.
С другой стороны, лог, нечитаемый без ныряния в таск-трекер, также малополезен.
Предпочитаю информацию о таске брать из имени ветки, а назначение конкретного коммита — из его сообщения.
Это просто, надежно и требует от человека меньше механической работы.
SCM разные, а методы — одни ))) и то хорошо ))

просто заявления «Git в сommit message не вставляет сам ID задачи» (ведь в итоге, я прАвильно понял, весь сыр-бор про имя веток сводится к этому?) симулирует утверждение «Git в commit message не умеет автоматически вставлять ID задачи, приходится писать руками, а мне лень, поэтому Mercurial удобнее»

а «не умеет» — это уже неверно ))) благодаря prepare-commit-msg hook'у, как, собственно, у меня и происходит (Вы же не думаете, что я каждый раз при закрытии задачи её ID и summary пишу руками?)

к слову, бывает ли необходимость просмотра истории через полгода, например, и не приходится ли вспоминать по ID задачи (из summary) её суть?
Для меня prepare-commit-msg hook оказался бы совершенно бесполезен: commit message я предпочитаю писать в том же редакторе, что и код, а не запускать git commit (редактор потом запустит git commit -m или git commit -f). Если нужно что‐то вставлять туда автоматически и всегда, то нужно использовать не prepare-, а просто commit-msg.

Но в любом случае даже этот вариант, во‐первых, оставляет простор для ошибок: commit с ненастроенной машины и кто‐то будет ругаться: либо разработчик, которому сервер провалил push, либо тот, кому эти метаданные нужны, а их нет. И дополнительно придётся так или иначе делать запрет «неправильных» сообщений серверными hook’ами или административно. В mercurial, как обычно, всё сразу работает.

И ещё: summary можно вполне запихнуть и в название ветки. В большинстве случаев это название писать всё равно не придётся, для остального есть автодополнение.
ну, это уже детали…
главное, что я, наконец, понял из обсуждения этого поста в чём претензии меркуриаловцев к «неполноценным веткам» Git'а… спасибо
> ну, это уже детали…
Это — самая суть. То, что в мерке структурированно, хранится в одном месте (имя ветки), всегда существует для коммита, в гите — произвольное текстовое дополнение, раскопированное по всем коммитам ветки с помощью гайдов, хуков и ручной работы.
Мерковский transplant (аналог гитового cherry pick) оставляет в новом коммите настоящую ссылку на старый вместо опционального упоминания об оригинале в сообщении коммита.
Претензий к «веткам» гита нет нет никаких, есть претензии к отсутствию настоящих веток в гите, наличию отсоединенных коммитов, отсутствию данных о публичности коммита и т.п.
Все это не означает, что гитом нельзя пользоваться или что он вообще плохой и неправильный. Но свои недостатки у гита есть (я бы сравнил текущее положение гита с положением C++ в 90-е) и бывает очень забавно наблюдать за фанатами, которые пытаются назвать даже их достоинствами.
Нет-нет-нет, речь вообще не про автоматизацию.
Просто если в мерке использовать стратегию «ветка на задачу», то id и название задачи можно отобразить в имени ветки, а в строке описания коммита оставить только то что относится к самому коммиту. В гите так сделать не выйдет, потому что его ветки эфемерны и придется информацию о задаче дублировать в каждом относящемся к ней коммите. А ветка мерка и через год никуда не исчезнет
а можете показать как это выглядит? я что-то плохо себе это представляю (мой мозг тоже съеден Git'ом ;) )…
в смысле как выглядит информация о ветке в Hg + сообщения коммитов
Отличия, видимо, лишь в описании коммита в дополнении к номеру задачи? Если так, то это Вам лишь кажется ) Одно из достоинств нашей команды (она же головная боль) — это отсутствие авторитетов в построении процесса разработки.

Каждое действие должно нести пользу и в этом еще нужно УБЕДИТЬ. Вот например, выше я интересовался преимуществом GitWorkFlow по сравнению с нашим именно потому, что когда то первоначально ввел именно его, а потом не смог найти его преимущества перед схемой ветка = версия.

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

Переход на задачу — в один клик по номеру задачи. А комменты вроде:
«refactoring: убрать директивы условной компиляции Indep и AladdinSupport»

и так очевидны из диффа.
а GitFlow, разве, не «ветка = версия», просто в нём есть ветки и долгоживущие, и короткие?

Переход на задачу — в один клик по номеру задачи.

переход по клику не всегда возможен *тут столкнулись апологеты GUI и консоли )))*
кроме того, задачи в issue tracker'е могут быть долгоживущими, и искать в её комментах когда именно было сделано это изменение (а уж тем более в связи с чем) — тоже ручная работа (кстати, у вас к комментам задачи добавляется связь с коммитом репозитория?)

А комменты вроде:
«refactoring: убрать директивы условной компиляции Indep и AladdinSupport»


и так очевидны из диффа.


а тут вы взяли уж очень простой и очевидный пример. согласитесь, не все изменения настолько очевидны? или Вам привести неочевидный пример? ;)
задачи в issue tracker'е могут быть долгоживущими

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

кстати, у вас к комментам задачи добавляется связь с коммитом репозитория?

В жире есть вкладка — коммиты по задаче. Про это? Коммит связываем просто с задачей, не с комментарием к ней. Может и было бы иногда удобно но в 99% случаев хватает номера задачи.

По условной компиляции: у нас бы завели задачу и сделали бы один коммит по одной задаче. Тогда у другого разработчика не возникло бы вопросов о том, зачем убрали одни атрибуты и добавили другие. Сейчас для этого требуется Ваше пояснение.

Впрочем, действительно, у нас тоже есть ИНОГДА коммиты с задачей и поясняющим текстом. И некоторые коммиты без задач: мердж, stylecop, мелкий рефакторинг для fxcop. Вопрос размера рефакторинга, который можно сделать без задачи — на усмотрение разработчика, до тех пор, пока не будет рецедива )
ага, понятно ))
у нас бы завели задачу и сделали бы один коммит по одной задаче. Тогда у другого разработчика не возникло бы вопросов о том, зачем убрали одни атрибуты и добавили другие. Сейчас для этого требуется Ваше пояснение.

ну, тут, я так понимаю, ещё и следование регламенту, с возможностью отследить «чем занимался», ибо «завести задачу» вряд ли даёт выигрыш в эффективности в сравнении с «написать комментарий в сообщении коммита» и дальнейшим «одним кликом» при просмотре истории…
А комменты вроде:
«refactoring: убрать директивы условной компиляции Indep и AladdinSupport»


и так очевидны из диффа.

а, кстати, не так уж и очевидны ))
само «убирание» директив — да, возможно )) но зачем? )) если и так всё работало…
а затем, что в следующем коммите добавятся новые директивы, которые вызовут ошибку… ибо у компилятора, оказывается, есть ограничение на суммарную длину директив, заданных в командной строке
-DFirstConditionalDefine;SecondConditionalDefine;...

ну, а поскольку я люблю атомарные коммиты, то сначала удаляем ненужные, а затем — добавляем нужные
и объяснить зачем удалять — надо… писать это в багтрекере? сомнительная польза
На мой взгляд это уж очень радикально. Если имя и id задачи включены в имя ветки, а описание коммита в его строку, то до этой информации будет не один, а ноль кликов, что во многих случаях позволяет получить одновременно выразительную и детальную картину изменений, переходы же к другим ресурсам (таск-трекер) оставить для случаев, когда краткой информации недостаточно.
Плюс комментарий к коммиту создает полезную избыточность, позволяя выявлять случаи, когда разработчик заведомо не заливает все необходимое или (что чаще) включает в коммит не относящиеся к его цели правки.
До этого дело есть всем, просто в гите приходится для коммита писать как то, ради чего сделан этот конкретный коммит, так и то, для чего сделана ветка, которая этот коммит содержит. Допустим, коммит содержит некоторый рефакторинг, о чем в сообщении и написано (удалены ненужные методы X и Y, выделен интерфейс Z ради T). Но он является подготовительным для решения бизнес задачи. В результате в гите я вынужден писать для коммита еще и id таски в жире и название самой таски. А в мерке эта информация есть в имени ветки и никуда не исчезнет.
Причем в мерке у тебя есть выбор (можно использовать как букмарки, аналогичные гит-веткам, так и собственно ветки), а гите — нет. Вообще git-way как-то очень уж скуден на метаданные.
Он не просто скуден на метаданные: я как‐то не могу припомнить, чтобы метаданные туда добавляли. У mercurial изначально не было ни закладок, ни фаз, ни evolve. Но их добавили. При чём закладки изначально существовали в виде дополнения (как evolve сейчас).

Это я к тому, что в mercurial метаданные добавляют, причём добавляют их, в том числе, через расширения — архитектура позволяет. В git не добавляют ничего. Это ясно говорит либо о том, что в протоколе взаимодействия и/или формате хранения данных (скорее первое: второе уже меняли и даже, вроде бы, не раз) просто не предусмотрена возможность расширения. Либо о том, что архитектура проекта не позволяет добавить что‐то вроде фаз или веток без тяжелого рефакторинга. Либо о том, что разработчиков нельзя убедить в полезности дополнительных метаданных, а добавить их самому через расширение как в mercurial не позволяет либо протокол, либо архитектура.
Так и представляю себе, как хочет мейнтейнер что-то такое добавить в гит, а Линус ему — да ты парень полон дерьма, и так далее в своём стиле :)
НЛО прилетело и опубликовало эту надпись здесь
Мне кажется, что тут скорее идеологические причины — в гит не добавили даже метку публичности коммита
в гите я вынужден писать для коммита еще и id таски в жире и название самой таски

аа, ну вот же и ответ на мой вопрос

prepare-commit-msg is overkill, говорите?

нее, ну не вопрос, когда под свои нужды можно сменить SCM… )
Понимаю, что сейчас минусов нахватаю за не популярную точку зрения :(
Я предпочитаю не ставить минусы за непопулярную точку зрения.

А вот за написание глупостей — вполне. Git не был первой dvcs (а не dcvs, как вы написали): были sun teamware, bitkeeper, monotone, arch, arx, darcs, dvcs (да, такое творение тоже существовало и расшифровывается, как distributed concurrent versions system).
НЛО прилетело и опубликовало эту надпись здесь
распиливание ханков есть. Называется «Отложить в долгий ящик». Очень удобная штука. Возможно это только в TortoiseHG, а не сам hg — не разбирался.

Octopus merge — есть arrenbrecht.ch/mercurial/pbranch/octopus.htm (сам я такими извращениями никогда не страдал, но этот функционал есть).
НЛО прилетело и опубликовало эту надпись здесь
нет, не оно.

А это что? (никаких плагинов я не ставил, всё из коробки):
image
НЛО прилетело и опубликовало эту надпись здесь
> Но никто ещё, ни один человек не смог объяснить мне чем гит лучше?
У меня большое подозрение, что дело банально в возможности менять историю. Делать вид, будто ты никогда не ошибался, не косячил, вместо пути показывать только результат.

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

Но для хранения истории проекта… это очень болезненное яблоко искушения.
Что делается?
Есть много разных вариантов:
1. «Экспортировать список различий» — создаётся один *.diff показывающий разницу между 1917 и 1926. Можно свою фичу пилить в отдельной ветке, а потом этот патч накатить на основной транк.
2. «Экспортировать часть граффа» — создаёт 10 diff-файлов
3. «Сжать историю» — создаёт 1 коммит выходящий из 1917 (второй башкой).
А зачем вы это написали в ответ на мой комментарий об изменении истории? :)
Потому что №1 и №3 позволяет сделать: чтобы человек мог долго пилить у себя фичу для линукса, а потом спрессовать это в один коммит или diff и отправить ревьюеру. Которого, действительно, твои ошибки и не должны интересовать.

Могу дополнительно рассказать как менять историю, но это слишком скучно и тривиально.
Всё то же самое в гите, скучно и тривиально. И в чём здесь преимущество мерка?
Я ни разу не открыл документацию и ничего не читал. Просто кликнул пару раз и сразу увидел то что мне было надо.
Так я вроде не собирался пилить фич и их отправлять
Я высказал своё мнение о том, почему гит более популярен

Поэтому я и недоумеваю — зачем вы мне объясняете, как делать то в хг то, что я делать не планирую…
НЛО прилетело и опубликовало эту надпись здесь
для Mercurial существует (хоть и не релизнут) плагин


то есть то, что в гит есть из коробки, в мерке мне нужно ставить плагин, который к тому же ещё и в бете?
НЛО прилетело и опубликовало эту надпись здесь
Почитал немного про changeset evolution, выглядит интересно. Как я понял, это как бы ведение истории изменения истории? Можете рассказать по подробнее простыми словами? В двух словах.
НЛО прилетело и опубликовало эту надпись здесь
Ну в гите можно накостылять с ветками, то есть вместо того, чтобы ребейзить одну и ту же ветку, делать git checkout -b feature-v2 feature && git rebase master; git checkout -b feature-v3 feature && git rebase master итд. При желании можно это всё завернуть в красивый плагин (похожее сделали с git-stash) и счастливо пользоваться, но как-то никогда не нужна была такая функциональность. Хотя может быть, если бы была, ей бы и пользовались, хз. Как вы сами, часть пользуетесь hg evolve? Интересен реальный опыт.
НЛО прилетело и опубликовало эту надпись здесь
править историю в хвост и в гриву без оглядки на коллег и чтобы вам за это ничего не было

Кто вам такое сказал? Я постоянно пользуюсь git rebase, каждый день раз по пять, как практически все мои коллеги. При должном опыте, практике и соблюдении элементарных правил безопасности, это совершенно нормально и безопасно. Правила просты: ребейзить только свои локальные ветки, не ребейзить общие ветки (master, develop) без согласования со всей командой, если опубликовал фичеветку ребейзить можно только если над фичей работаешь только ты, если кто-то ещё — согласовывать ребейзы с этим коллегой. Всё, всё просто, никаких проблем. Именно что, с оглядкой на коллег, чтобы ничего за это не было. Мне ли вам объяснять, что гит — это инструмент, со своими опасностями, как фрезерный станок: если сувать руки внутрь, то может оторвать, но если правильно пользоваться — можно это делать совершенно безопасно годами. Тут есть момент, что инструмент для команды коллективный, да. Но при ошибках работы с ним никто не умирает, в отличие от ошибок с коллектиным оружием (если кто-то один накосячит, например, с миномётом, разорвёт весь взвод).
НЛО прилетело и опубликовало эту надпись здесь
Да, я уже понял, что hg evolve это суперкруто. Однако:

не пользуюсь: 1) bitbucket его пока не поддерживает, а искаробочной смотрелки репозитория мне недостаточно 2) недостаточно народу на проектах под mercurial, чтобы разворачивать evolution (там, где народу достаточно, VCS выбирал не я ⇒ Git)
НЛО прилетело и опубликовало эту надпись здесь
Советую приплюсовать gerrit — тогда все правки делаются в одном коммите и не нужно опасаться за rebase.
Меняет концепцию работы, но реально очень полезно, особенно, при появлении в команде джуниоров.
Так история и должна быть правильной.
И не только в ошибках и правильности дело.
Изменение истории — это как рефакторинг в программировании. Пока не видел ни одного программиста, который бы в реально боевой, ежедневной работе над проектом писал бы код не требующий рефакторинга.
Это правильно, что когда все готово, то нужно прибраться и все причесать, чтобы история была реальной историей, а не мусорной кучей.
Вы хотите религиозного спора? Ночь же уже, но давайте попробуем.

Историю должна быть историей. Разграничивать то, что было и чего не было. Если есть желание рассказывать прекрасные красивые сказки — заради бога, но то, что это называется history и log…
Нет, ребята, извините. На самом деле этого не было. На самом деле всё было совсем не так.
Нет, религиозного не хочу. Хочу конструктивного.
Насчет истории — не согласен.
История должна отражать, кто и что сделал. А как он это делал — не должна. Мне не нужно видеть 100500 коммитов по одной задаче из-за того, что тестировщик нашел баг, а потом еще один, и еще один.
Мне нужно, чтобы в историю попадал один коммит, в котором сделаны изменения именно по задаче. Это важно, если, например, придется откатить изменение.
Я хочу сам (как лицо ответственное за разработку и за историю) решать, что мне нужно в истории, а что нет. Если в историю будет попадать все, что делают разработчики это будет помойка, а не история.
А меня мама учила не врать.
Какой уж тут конструктив, когда меня учат обманывать, да ещё так красиво объясняют, почему обманывать — так хорошо и правильно :)
Кстати, мне тоже не совсем понятно, зачем нужна красивая история. Проблемы иногда добавляет а какие решает? Можете привести один-два примера?

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

Поиск автора строки в коде — нет. История изменения файла — нет. Поиск плохого изменения — бисект.
Решает такую проблему — нет мусора в истории.
По каждой задаче есть (в идеале) один коммит. Видно кто его сделал, видно в этом коммите все изменения по задаче.
И что самое удобное — его легко откатить, при необходимости (reverse commit) — он не размазан по истории.

Как раз вместо трех заходов с промежуточными коммитами будет один (вообще это должно делаться разработчиком до попадания в основные ветки, но бывает, что фиксится дополнительно уже после вливания — все сразу не отследить). А разбираться частенько приходится — когда баг всплывает или когда требуется что-то откатить, или дополнительно изменить в связи с решенной ранее задачей.

Непогрешимой веткой (которую нельзя ребэйсить) остается только мастер. Все остальные правятся при финальной подготовке апдейта.

Кроме отсутствия мусора редактирование истории нужно для гибкости.
Это вообще основной инструмент в git для меня.
Подготовили апдейт, но владельцем продукта было решено какую-то функциональность пока отложить. Т.к. по каждой задаче коммит один, то это сделать очень легко — переносим правки из текущего в следующий релиз. История при этом остается аккуратной.
Или подготовили 2-3 апдейта параллельно, нужно их свести в последовательные правки. И т.д.

Поиск автора остается, поиск плохого изменения остается. Все точно так же, но только история красивая и последовательная. А работать с ней, при этом, на порядок проще.
Ок, идею понял. Красота, плюс если нужно откатить, то вот он — один коммит. С другой стороны, объединение коммитов и откат нескольких мне кажется задачей одной сложности. Почему бы тогда не проводить ее именно когда нужно откатить, а не каждый раз? Откатывают то 1 из 100. Получается, остается только красота и магическая «работа с историей»?
Единственная причина, имхо — откатить, как правило, бывает нужно срочно. И, надеюсь, лицо, решившее, что лучше потратить N часов на M% бесполезной работы по объединению ради возможности в (100-M)% случаев откатить «фичу» полностью практически мгновенно, руководствовалось оценкой реальных бизнес-рисков, а не красотой «истории» (история, которую можно изменить задним числом не история, а, в лучшем случае, её представление в каком-то разрезе).
В этой ветке про ребэйс прокомментировано.
История должна отражать, кто и что сделал. А как он это делал — не должна.

История на то и история, что должна отражать всё и не должна исправляться задним числом. Иначе это не история, а что-то другое. Политическое видение истории, например :) В Советском Союзе был распространён процесс решения, что включать в текущую версию истории, а что не включать. И не важно было оно или нет.

А если вы как ответственный за разработку не хотите, чтобы третьи лица (прежде всего те, перед кем вы ответственны) видели, что делают те, за кого вы ответственны, и делаете что-то, чтобы это скрыть, то это называется введением в заблуждение. И если мотивы ваши корыстны, то это даже на статью УК РФ катит. Серьезно. Руководство думает, что у вас в подчинении пускай медленные, но тщательные разработчики, но не в курсе, что вы своих падаванов пинаете устно за каждый «промежуточный» коммит, искажая реальную историю событий.
Такую ерунду написали. Бред просто.
Поработайте над одним проектом 8 лет в agile-режиме — тогда обсудим.
Возможно вам (и всем остальным интересно знать), что вот пароль добавлен в историю, а вот он из нее удален, а вот задача — размазана по 10 коммитам с перебивкой другими коммитами и затесавшимися в задачу правками по оформлению (отрефакторили по ходу дела 50 файлов) и нужно снова срочно повторить ее через год — наверное, вам будет очень удобно выбирать из такой каши конкретные правки по задаче.
Или то, что за такой срок при сохранении всех телодвижений и объединении правок мержами вам покажется, что карта метро по сравнению с историей проекта — песочница по сравнению с карьером. Без структурирования и причесывания истории работать просто нереально. Все равно что написать, что если программист что-то один раз написал в код, то оно должно там оставаться навсегда, и менять его уже нельзя, а изменения нужно делать дополнительным кодом.
Возможно вам (и всем остальным интересно знать), что вот пароль добавлен в историю, а вот он из нее удален


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

Ещё раз — вам интересна не история, а какие-то моментальные снэпшоты на выбранные вами моменты времени и диффы между ними. Вам интересные не события, происходящие с кодовой базой, а конечные результаты цепочек событий.
Справедливости ради замечу, что вот у нас самый крупный непрерывный проект — 5 лет с 30 тыс коммитов. И у нас нет необходимости в красивой истории. Просто нет таких процессов в разработке, где нужно открыть дерево истории глубже чем на пару итераций и рассматривать его.
Хотя, допускаю, что если бы мы захотели красиво распечатать пятилетнее дерево коммитов в виде обоев на стену, то там бы ничего понятного бы не было.
Может вам история совсем не нужна? Поэтому и наплевать, что там будет?
Непрерывный проект — что значит? Как часто в нем правки? Может и 30 тыс. коммитов там от того, что «забыл запятую», «поставил запятую», «запятая оказалась лишней»,…?
На 30 тыс коммитов примерно 11 тыс. задач в багтрекере. Т.е. примерно по 3 коммита на задачу, включая: мерджи, коммиты по тестам, по метрикам кода и stylecop. Много это или мало — смотрите сами.
А по истории трудно сказать. Процессов разработки, в которых мне бы нужно было полазить по графу мерджей больше одной итерации назад — действительно нет.
Типовые вопросы по истории: понять когда и кем была сделана фича по номеру задачи, с какой версии она появилась, история изменения участка кода, список изменений между поставками. Все эти вопросы решаются без графа. Т.е. у меня просто нет необходимости читать описания «забыл запятую». Значит ли это, что мне не нужна история?
Вот так выглядит типовая история
Скрин
image

Меня не пугает, жить не мешает. В том редком случае, когда нужен именно аудит изменений — тот факт что история без правок только помогает разобраться. Такого не бывает. Послушав доводы и изучив за эти пару дней материалы лично мне кажется, что скрипач rebase — не нужен )
Ну это практически плоская )
У нас была на порядок «шире».
Сейчас вот такого плана:
Скрин
image
А до того, как навел порядок в истории было:

так
image

и даже так
image


Мне кажется, сейчас стало лучше )
О да, знакомая картина :-)
У нас было как на второй картинке после octopus merge. Я его сделал чисто попробовать первый и последний раз в жизни.
Как вы такое получаете?! Что мы делаем не так, что у нас такого нет?! )
Может действительно что то в Hg или отсутствии git workflow приводит к тому, что нет таких ситуаций?

Бывает, видел у нас ну 7-8 веток. Но 33!
У нас тоже сейчас такого нет )
Это было время «поиска workflow» — тогда пытались каждую фичу делать в отдельной ветке и затем мерджить. Получалось не очень )
Сейчас git workflow (master | hotfix | release | develop), роль временных веток + код ревью играет gerrit, сама история — плоский мастер с периодическими вливаниями из hotfix / release. develop обычно переносится в release. Все сводится ребэйсом.
У разработчиков локально могут быть любые ветки, но обычно каждый работает над одной фичей в один момент времени.
Да нет, наоборот хорошо, когда вместо слепого холивара обоснованное мнение.
Лог непривычно в виде графа вместо истории по веткам. Удобно?
У меня история — это плоский мастер в который вливаются другие ветки (всегда два уровня — мастер и ветка, которая в него влилась) — видно что в какой ветке было сделано, кем и когда пришло в мастер. т.е. это реально история, а не некоторый процесс.
Никак не могу понять, за что костерят HG-ветки. После гита очень радуют полноценные ветки, с информацией о том, откуда пришел коммит, а так же всю историю слияний по веткам. В GIT'е она частично решается костылём в виде «пишем в комментарий к коммиту название ветки», и само наличие такого костыля означает, что в гите этой возможности пользователям не хватает…

Так же не понял, о каких в комментариях уникальных возможностях git'а говорят в комментариях. Чего нет в том же hg? Ветки, слияния, всякие черрипики есть… Не возникало ситуации в командной работе, что бы этих возможностей не хватало.

Так же не понял, за что в комментариях ругают «черепашек» (TortoiseHg/TortoiseGit). Отличный интерфейс, позволяющий вообще забыть, какие там есть ключи и что там и как происходит в командной строке. Опять же, в интерфейсе есть всё, что необходимо для работы. С ситуацией, когда пришлось бы «спуститься уровнем ниже» (в командную строку) не сталкивался за несколько лет использования ни того, ни другого. А вот с SourceTree периодически в командную строку лазить приходилось, ибо подглючивает местами.
Заранее прошу прощения, я просто не в курсе, но очень уж хотелось бы узнать из первых уст, а что такое «полноценные ветки» и почему/зачем они так нужны (меркуриальщикам; а судя по постам, только им)?
я действительно пока не понимаю «зачем нужно знать из какой ветки пришёл коммит?» в чём их, веток в меркуриале, особенность?
Знать из какой ветки пришёл коммит нужно, чтобы отслеживать откуда пришло изменение. Представьте, что вы работаете в большой компании с десятком команд, и в каждой команде человек по пять сидит. Есть хитрая политика мерджа, которую могут нарушать. И вот вы находите странный код в релизной ветке. Вам нужно проследить то место, где этот код появился и кто его изначально написал. Чтобы обсудить разработчиком этого кода, почему он принял своё решение. Если hg хранит информацию о ветке, то git нет. Потому такой ресёрч в hg провести намного проще, чем в git.
Знать откуда пришло изменение, когда оно было сделано, кем и в связи с какой задачей — это необходимое условие при работе на больших проектах.
Представьте, что вы фиксили багу, а на прод ваш фикс не попал, потому, что его кто-то перетёр. В таком случае найти грешника по истории изменений и покарать.
Когда вы работаете в одной команде и друг-друга знаете, кто чем занимался, такую проблему вы не осознаёте. Здесь действительно нет большой разницы hg или git. (Ну только, чтобы пользоваться hg не придётся читать статьи «hg-это просто», hg работает логично сразу и без консоли.) Однако если вы начинаете работать с проектом, в котором дерево изменений настолько широко, что не влазит в экран, то c git начинаются проблемы поиском откуда что пришло.
Есть хитрая политика мерджа, которую могут нарушать

На мой взгляд, это уже проблема.

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

Информация, кто код написал, в гите есть. А вот зачем мне место, где код появился — я и правда не очень знаю.
Есть хитрая политика мерджа, которую могут нарушать

На мой взгляд, это уже проблема.


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

Информация, кто код написал, в гите есть. А вот зачем мне место, где код появился — я и правда не очень знаю.


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

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

Да, но возможно надо смотреть на способы оптимизации этого процесса.

Чтобы понять зачем эта строчка нужна вам нужно проследить откуда она появилась и просмотреть на весь ченджсет с которым она пришла.

Так, это я прекрасно понимаю, и гит это позволяет.

На больших проектах исследование истории может дать очень много информации

С этим я не спорю. Но вот зачем знать именно ветку, в которой это было — не очень.
Но вот зачем знать именно ветку, в которой это было — не очень

например ветки это задачи в TM. А ещё можно посмотреть все изменения в ветке до её слияния
например ветки это задачи в TM.

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

А ещё можно посмотреть все изменения в ветке до её слияния

Так и в гите можно. Я сейчас специально сделал тривиальный (но жизненный) тест — две ветки, в каждой по изменению, затем слияние (с преднамеренным конфликтом). git blame показывает «правильный» коммит для каждой строчки, а затем (благодаря тому, что коммит хранит ссылку на родителя), можно пройти от этого коммита назад (да и вперед) по истории.

Я не вижу какого-то важного сценария?

(кстати, пока ветка не удалена, узнать, в какой ветке лежит коммит тоже же можно)
Но вот зачем знать именно ветку, в которой это было — не очень.


Если есть какая-то система в именовании веток, которую большинство разработчиков соблюдают, то по имени ветки, в которой был сделан коммит, можно извлечь дополнительную информацию. Ну, банально, что кто-то делал обычные коммиты в релизную ветку. А в гите (при fast-forward) вообще может не быть информации, что ветка создавалась.
А в гите (при fast-forward) вообще может не быть информации, что ветка создавалась.

git merge --no-ff
при fast-forward
Так не делаейте fast-forward, когда вам нужна информация о ветках.
Даже если издать приказ о штрафах в 1000 долларов за каждый мерж без --no-ff, то это не гарантирует ничего. Уменьшает шансы, но не гарантирует.
Серверные хуки зато гарантируют.
Мердж в основную ветку должен делать тот, кто отвечает за процесс.
У нас делается ребэйс с причесыванием (--interactive) и одновременным сведением в актуальный код, а затем уже merge --no-ff
Все очень хорошо видно по истории в результате.

Гарантировать можно и гитолайтом, например.
Да ладно вам, чтобы в гите-то да не удалось обойти серверные куки? :) в гите всё можно…
Это уже злое намерение, оно по другой категории проходит.
Очень часто запреты нарушаются из самых лучших побуждений :)
Побуждения уже не важны. Одно дело — защищаться от случайностей, другое — от намеренных действий.
Вы говорили о злых намерениях, а я о добрых :)

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

т.е. там, где обычно «что, зачем и почему» описывается в commit message (и если не описал — то… СМЕРТЬ ТЕБЕ уже непонятно… ), hg добавляет что-то, что поможет узнать эти самые «что, зачем и почему»?
все перечисленные Вами требования (как уже написал lair, отхватив свою порцию минусов, можно сказать, за меня :) ) — в Git'е выполняются:
и автора изменений, и их время, и набор последовательных коммитов можно узнать, и довольно просто (может, конечно в hg как-то ещё проще — я не знаю, не использую)…
но ответа на терзающий меня вопрос «что такое „полноценные“ ветки?» я пока не получил… может Вы ответите, раз Newbilius пока молчит? какое отличие их, веток, в hg — от Git'овских?

Грубо, в гите ветка — это указатель на коммит, а в мерке — тег коммита.
Ну так это тогда две разные сущности, сделанные для совершенно разных целей и с разной идеологией. Говорить, что одна из них — полноценные ветки, а вторая — нет, это как говорить, что мерседес — настоящая машина, а мазда — нет. Холиварно, не продуктивно и просто неправильно.
Ну, ветка в гите очень простая и целиком вторичная сущность — указатель на коммит. Ветка же в мерке более сложная сущность — коммиты принадлежат ей, информация о ветке неотъемлемая часть коммита. Потому и выходит «полноценная».
Вот с этого момента поподробнее. Вот я мержу две ветки, соответственно создаётся новый мерж-коммит с двумя родителями. Внимание, вопрос: какой ветке будет принадлежать этот мерж коммит? Или в меркуриале всё не так, и мерж коммитов нет? Вроде помню, что были, но могу ошибаться, т.к. давно с ним не работал. Мне и правда интересно, вопрос без сарказма.
В текущую ветку делается «мерж» другой ветки. Соответственно текущая останется текущей.
Но как тогда быть точно уверенным, что код после мержа попал в основную ветку из истории основной ветки, а не из смерженной (или наоборот)? Всё равно в этот момент связть веток с кодом теряется, и без отслеживания по истории такие вещи не понять, как и в гите. Так что получается избыточная сложность, которая не особо облегчает поиск.
Мерж коммит будет в той ветке, на которой вы стояли перед началом операции
Все детерминированнее некуда

Если потом захотите влить это и во вторую ветку — станете на нее и сделаете ещё один мерж-коммит ) если вдруг возникнет такая необходимость
А зачем нужно, чтобы коммиты принадлежали ветке? Никак не могу понять.
В git они тоже принадлежат — пока их в другую не перекинешь. Это же удобнее, разве нет?
В гите ветке непосредственно принадлежит только один коммит и могут быть коммиты веткам вообще не принадлежащие. В мерке все коммиты непосредственно принадлежат одной и только одной ветке.
В гите ветке принадлежит вся ветка коммитов — по цепочке. Если я захочу — они будут принадлежать другой. Это же удобно.
Я понял, что имя ветки приписывается коммиту навсегда в мерке. Я не пойму, зачем это нужно и что конкретно дает?

Пример: я делаю временную ветку под фичу, работаю в ней, затем перекидываю в основную ветку разработки. Зачем мне знать, что коммит был сделан во временной ветке? Или нужно делать сразу в основной? Но это неудобно, если работать над несколькими фичами параллельно.
Объясните.
НЛО прилетело и опубликовало эту надпись здесь
а если делать во вспомогательной, то при мердже в основную имя вспомогательной так и останется в коммите?
НЛО прилетело и опубликовало эту надпись здесь
Ну тогда особой разницы (помимо идеологической) не вижу.
В git действительно, при мердже не сохраняется имя ветки, кроме как в описании (дефолтно подставляется). Что, в принципе, и понятно. Возможно кого-то это действительно напрягает — меня нет.

А что будет в мерке, если удалить ветку после мерджа? В самом мердже ее имя останется?
Что будет если после удаления повторно создать ветку с таким же именем? Будет считаться, что смердженные коммиты пришли из нее?

Много ли в мерке делается веток?
В git ветку можно (и нужно) создавать на каждый чих, и так же легко с ними расставаться.
В мерке ветки не удаляются. Их можно закрыть (пометить неактивными), чтобы не выводились по умолчанию и всё.

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

Интересно, а если мерджить результат мерджа (который тоже может быть результатом мерджа,...), то какая ветка укажется в окончательном мердже?
Ветка будет всегда та текущая, в которой делается коммит, в том числе мерж — та, в которую мержимся.
В гите несколько наборов принципиально разных сущностей с теми же именами, что и в хг, но с иным смыслом
Это для меня было самум неудобным при изучении гита :)

Конкретно:
— Ветки
— команда add
… и что-то третье было, запамятовал :( то ли reset, то ли checkout/update…
А как в расследовании помогает название ветки?
Разве не достаточно знать кто и по какой задаче добавил код?
Какие, например, у вас названия веток?
Названия веток часто и есть названия или номера задач.
Понятно, спасибо.
> А как в расследовании помогает название ветки?

Помогает даже не название, а цвет. В GUI для Hg (SourceTree, например) можно проскользить взглядом вдоль линии одного цвета — охватишь взглядом все коммиты, сделанные в рамках работы над конкретной фичей. В том же SourceTree для Git цвета натурально не несут ни малейшего смысла. Скользя вниз по ветке какого-то цвета будешь спотыкаться об слияния, после чего надо пытаться понять, по какой родительской дуге надо продолжать движение.
В свою очередь, можно тоже ответ из первых уст: каждый ответ любителей гита на вопрос о ветках — «ветки не нужны». Прямо как ортодоксальные фанатики-линуксоиды: если чего-то в линуксе нет, «это не нужно». Почему так?
Что значит «не нужны»? Гит состоит из веток.
я не говорил «не нужны»
*тем более, что Git — это ветки… и быстрые/дешёвые ветки! за них в его исполнении я его и люблю

я просто пока так и понял, в чём разница меркуриаловских веток и гитовских? почему имя ветки так важно меркуриаловцам?
Не знаю, как TortoiseHg, но TortoiseGit был сделан на идеологии TortoiseSvn. В результате в нем все сделано неправильно идеологически. Работать можно, но суть git понять — нет. Очень советую вместо него юзать в винде хотя бы GitBash. А лучше изначально на linux пересесть, хотя бы в виртуалке.
Иначе потом будут возникать постоянно проблемы из разряда «ой, я столько лет с git работаю и ничего не могу в нем понять».
Ситуация с удалённым репом, описанная в разделе «rebase», невозможна. При наличии обновлений в апстриме гит предупредит о non fast-forward push и не даст залить изменения без ключа -f. Если же говорить о полноценном окружении разработки, то тот же gitlab делает ветку master по умолчанию защищённой от форсированных действий (ну, и защита остальных веток, естественно, настраивается).
Что до кривых ребэйзов, осиротевших объектов и прочих поломок, то это проблемы отсутствия интеллектуального ценза. Идите писать на дельфи, обмениваясь кодом по самбе.
НЛО прилетело и опубликовало эту надпись здесь
>> Ситуация с удалённым репом, описанная в разделе «rebase», невозможна
> линус какбэ возражаэ
За шесть лет многое изменилось.

>> При наличии обновлений в апстриме гит предупредит о non fast-forward push и не даст залить изменения без ключа -f
> этого недостаточно. достаточно было бы явно отслеживать публикацию коммита и не давать переписывать опубликованные, но это же
> 1) меркуриал какой-то получится 2) приведёт к уменьшению кол-ва боли и унижений, что совершенно недопустимо
А, я Вас понял. Если я решу набрать в проект конченных дебилов, надо будет задуматься об использовании меркуриала… Хотя, о чём это я? Вы ведь полностью проигнорировали часть моего коммента, где я описывал гитлаб.
Сам по себе гит не подразумевает централизованного хранилища и, соответственно, каких-то общих для всех политик. Поэтому если вы делаете центральный репозиторий на голом гите (по протоколу самого гита, ссх или вебдаву – не важно), вы осознаёте, что работаете на станке без кожуха. И любой долбоёб может засунуть в него руку или арматуру (от этого зависит, плохо будет долбоёбу или станку).
Впрочем, если на проекте отсутствуют анацефалы, подходить к станку с непонятной стороны никто не будет, и можно работать даже в таком виде. Но если вы решили дать доступ к такому репозиторию разработчикам на дельфи или, простигосподи, жабаскрипте, потрудитесь оградить их от внутренних механизмов. Поставьте тот же гитлаб: он даже в дефолтной конфигурации избавит вас от возможности совершить ошибку, закодированную на генетическом уровне.

>> это проблемы отсутствия интеллектуального ценза
> способность запомнить карту минных полей в интерфейсе Git с интеллектом не имеет ничего общего.
Минные поля создают сами пользователи, потом по ним же и ходят.
НЛО прилетело и опубликовало эту надпись здесь
> Это что же конкретно?
Вот конкретно обсуждаемая вещь. Без форсирования затолкнуть свой коммит в апстрим при наличии детей у родителя этого коммита невозможно. По крайней мере, на практике оно именно так.

> никакой гитлаб не помешает сначала сделать ошибку в локальном репозитории
Скажите, а ошибки в коде за Вас тоже hg правит? Может быть, прав был наш интернет-обму…омбудсмен, когда говорил, что программистов можно будет заменить компьютером, который будет писать код?
Вы выдумываете непонятные проблемы и ставите в минус гиту то, что он за Вас эти проблемы не решает. Мне это напоминает ту бабу, что залезла к медведю через забор и просунула руку в клетку. По вашей логике, это не баба дура, это забор был недостаточно велик, и рядом не стояло три охранника.

> нет ли здесь victim blaming?
Абсолютно нет. Это у вас есть мышление потребителя (в самом, что ни на есть, плохом значении данной фразы): «Ваше ПО позволяет что-то сломать. И не важно, что для этого нужно проигнорировать предупреждения, насрать на документацию и делать вещи, в которых не имеешь ни малейшего понятия. Я девочка, я не хочу ничего решать^W^W^W^W^W^Wне хочу читать документацию и учиться работать с инструментом, я хочу, чтобы инструмент работал за меня».
прав был наш интернет-обму…омбудсмен, когда говорил, что программистов можно будет заменить компьютером

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

Не выдёргивайте из контекста, как журналисты. Если естественный для человека порядок мышления непременно приводит к некорректному использованию программы, это — недостаток интерфейса программы, а не человек дурак, потому, что инструкцию не читал. Программы пишутся для человеков, а не человеки для программ. А git именно что неестественнен. Для большого числа рабочих процессов нужно отслеживать, кто когда и в каких условиях (в какую конкретно ветку) внёс данный участок кода, эту потребность git не закрывает. (Ну или не закрывал, потом научился, я не знаю — я не работаю с ним постоянно.)
Я даже не знаю, как реагировать на фразу «естественный для человека порядок мышления». Дайте линк на РФЦ, что ли…
Миллионы людей корректно используют гит, и их «порядок мышления» никоим образом им в этом не мешает. Тот факт, что ваш личный опыт работы с системами контроля версий мешает Вам использовать гит корректно, говорит только о двух вещах:
а) ваш опыт сильно отличался от того, что предлагает гит, и гит Вам неудобен;
б) на первый пункт Вы отреагировали не коррекцией своего опыта путём обучения, а неконструктивной критикой всего нового и непонятного.
НЛО прилетело и опубликовало эту надпись здесь
Какие конкретно изменения в Git за последние 6 лет помогают предупредить/предотвратить перезаписывание уже опубликованных коммитов?

Необходимости указывать опцию --force, по вашему мнению, недостаточно?
Ещё нынче есть --force-with-lease.
Это сарказм или нет?.. реально тяжело понять :)
> Моя версия: «никакие». Ваша, насколько я понимаю — «никакие, и это прекрасно, тупой недоумок».
Не приписывайте мне химер вашего сознания.
Вам уже неоднократно объяснили все аспекты данного вопроса, но Вы упорно игнорируете все аргументы.

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

> трекать признак публикации возможно
Не используйте push -f. Не используйте rebase.
НЛО прилетело и опубликовало эту надпись здесь
А вы не задумывались о том, что мерк, запрещая некоторые варианты поведения, запрещает их и тогда, когда это действие хотят сделать намеренно? Не хочу, чтобы молоток за меня решал, стоит мне бить по гвоздь сбоку или нет. А если кто-то попадает молотком по пальцам — то тоже молоток виноват? Ай-ай-ай, молоток позволил попасть себе по пальцам! Он должен быть с резиновой оправой и с направляющими, чтобы нельзя было бить по не по шляпке гвоздя! А простые молотки вообще запретить!

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

Многие современные git-сервера позволяют намертво запретить git push -f. Этого тоже недостаточно?
НЛО прилетело и опубликовало эту надпись здесь
Если у вас есть необходимость force push, значит, у вас неправильно организована работа.
НЛО прилетело и опубликовало эту надпись здесь
Когда необходим — даем права конкретному человеку, он делает force push, затем отбираем обратно.

(да, мне тоже не нравится)
тогда даём права определённому пользователю (необязательно реальному) это делать :)

в gitolite, например, это можно реализовать так:
просто генерим новый ключ, заносим его как ключ некоего всемогущего пользователя, а когда собираемся делать push --force, делаем это с ключом этого пользователя
По поводу веток хотелось бы уточнить: каждый раз, чтобы подправить одну строчку, необходимо копировать весь проект? Иначе изменения никак не могут высчитаться?

И как быть с ветками, которые должны жить постоянно (вроде beta release, release candidate, trunk), они считаются независимыми проектами? Как проходят мержи между ними?
> По поводу веток хотелось бы уточнить: каждый раз, чтобы подправить одну строчку, необходимо копировать весь проект?
> Иначе изменения никак не могут высчитаться?
Что значит «кажды раз»? Если вы склонировали репозиторий единожды, вам достаточно обновить его до актуального состояния, когда вы в очередной раз решите внести изменения.

> И как быть с ветками, которые должны жить постоянно
> (вроде beta release, release candidate, trunk),
> они считаются независимыми проектами? Как проходят мержи между ними?
Моё мнение: beta release ответвляется от мастера (trunk = master) каждый раз, когда проект подходит к очередному релизу. release candidate – состояние ветки beta release, а не отдельная ветка.
Затем, когда они приступают к работе над своим драйвером, они могут все это полностью скопировать в директорию под названием ужасный-драйвер-broadcom.

Имел ввиду, что перед каждой задачей, нужно ответвляться?

Моё мнение: beta release ответвляется от мастера (trunk = master) каждый раз, когда проект подходит к очередному релизу. release candidate – состояние ветки beta release, а не отдельная ветка.


В транке могут делаться тяжелые задачи, релизы выпускаются чаще, чем они завершаются => необходима как минимум еще одна ветка для насущных задач и правки багов, которую можно безболезненно выкатить в продакшн. И вопрос был не об организации релизной политики, а о том как через гит воплощается наличие связанных веток, когда коммит в beta release мержится выше вплоть до trunk.
> Имел ввиду, что перед каждой задачей, нужно ответвляться?
Это исключительно организационный вопрос.

> И вопрос был не об организации релизной политики, а о том как через гит
> воплощается наличие связанных веток, когда коммит в beta release мержится выше вплоть до trunk.
Вот этот вопрос меня тоже интересует, если честно. Пока что единственный известный мне способ – мержить коммиты руками через cherry-pick.
Если нужен hotfix в trunk, то он делается отдельной веткой, и уже ИЗ trunk'а мёржится в beta release (согласно gitflow). А если не хотфикс, то зачем коммит из беты брать в trunk?
Имел ввиду, что перед каждой задачей, нужно ответвляться?

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

В транке могут делаться тяжелые задачи

Большинство рекомендаций и реальных практик предполагают что есть одна ветка (часто — master, но это не более чем соглашение — технически все ветки равнозначны), которая опережает продакшен/текущий релиз максимум на один мержкоммит, а других коммитов напрямую в ветке делаться не должно. Вся разработка, тестирование и приёмка ведутся в других ветках, которые мержатся в мастер только перед деплоем.
git clone копирует весь удаленный репозиторий (всю историю проекта), после этого git fetch/pull заливает с удаленного репозитория только изменения. При переключении локальных веток сначала как бы откатываются коммиты текущей ветки до последнего общего коммита ветки на которую переключаешься, а потом накатываются её коммиты. При создании локальной ветки вообще ничего не копируется, просто создаётся ссылка на какой-то (обычно HEAD) коммит.

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

"как бы", но не так ))
коммит — это уже snapshot репозитория
при переключении веток, да, проверяются изменялись ли текущие изменённые (если таковые есть) файлы в переключаемой ветке, но никакие коммиты не накатываются, ибо состояние файлов уже известно, нужно их просто поместить в рабочую копию.

Ваше описание бы подошло, если бы коммит хранился как патч… но Git хранит состояние, а патчи вычисляет на лету
>И как быть с ветками, которые должны жить постоянно (вроде beta release, release candidate, trunk),
>они считаются независимыми проектами? Как проходят мержи между ними?

Обычно проще иметь одну постоянную ветку master которая по сути является копией кода на продакшене, в остальных случаях создавать ветки от нее и убивать, когда в них необходимость пропала.
Ну т.е. например каждую неделю в пятницу необходимо все что сделано отдавать тестерам, а в среду выливать в продакшен.
В пятницу создаем ветку prereleaseN, мержим туда все изменения, выкатываем куда-то для теста.
По ходу обнаружения и исправления багов, мержим туда фиксы, выкатываем.
В среду мержим ветку в мастер и убиваем ее, мастер выкатываем на продакшен.
Коллеги, а есть кто в ветке, кто сможет мне объяснить, зачем все вообще носятся с этим Git Workflow? После svn последние 6 лет работаем на hg, выпускаем и поддерживаем версии модульного продукта по одной-две версии в год. Поддерживаем 2-3 последних версии.

Так вот, для нас, как мне кажется, гораздо удобней схема — ветка = версия продукта/модуля. Т.е. сперва ветка находится в состоянии разработки, потом в альфе, потом в бете и релизе.
Хотфиксы — внутри ветки. Новая версия — новая ветка. Не поддерживаемые версии — закрываем.

Что мы делаем не так? Какие возможности теряем?
image
> гораздо удобней схема — ветка = версия продукта/модуля
Тут все можно делать так же, просто можно еще например любые изменения, пачки изменений в отдельный ветки выносить.
Т.е. к примеру есть основная задача, а есть необходимость хотфиксов. Все делаешь в разных ветках, почти моментально переключаясь между ними. Когда что-то готово, можно слить несколько любых веток в одну — влить их к примеру в ветку альфа.
Больше свободы конкретному разработчику, он может создавать веток столько сколько захочет, переключаться между ними, никому не мешая, а наружу отдавать уже нечто готовое так как ему сказали.
Так и у нас схема аналогичная, крупные фичи — в ветках. Они отдельно тестируются, потом вливаются в нерелизную ветку (она ровно одна).
При этом, как мне кажется, мы избегаем кучи мерджей, связанных с процессом выпуска версии. Типа исправили баг и вмерджили его сперва исправление в альфу, потом в бету, потом в пререлиз.
Практически единственные мерджи, не связанные с параллельностью разработки — когда находим баги в старых но поддерживаемых ветках. 2-3% всех багов.
Никто не мешает делать точно так же в гите. Гитфлоу — это просто рекомендация из разряда «бест-практисис», набор паттернов ведения истории, если можно так сказать. На самом деле в чистом виде он не всегда удобен. В общем, в каждом проекте команда сама выбирает стратегию ветвления, и ваш вариант тоже вполне используется.
Я могу рассказать о паре своих наиболее эпичных факапов с GIT. Попрошу фанатов Git-а не читать, так как это может быть больно. Как говорится: Graphic content; viewer discretion is adviced.

Случай раз случился, когда я возжелал использовать merge --squash. Отличная, казалось бы, возможность переносить изменения из приватной дев-ветки, где ты что-то делаешь, в общую ветвь репозитория, делая красивый коммит с комментарием «Исправлен баг #32143». Казалось бы, что может пойти не так? Идея умерла в муках, когда оказалось, что конфликт, единожды разрешённый при merge --squash, требуется разрешать снова и снова при каждом последующем слиянии между эти двумя ветками. То же самое относится и к git cherry-pick.

Что делать? Забудьте всё, что вы слышали про то, что гит круто мерджит коммиты. Вы должны делать cherry-pick или squash только в том случае, если после этого выбросите исходную ветку, все остальные варианты вам гарантируют боль. Разумеется, в документации об этом забыли сообщить. Не нравится? Используйте Mercurial. Или даже SVN. Потому что даже отсталый SVN вам позволит смержиться с той веткой, из которой вы перед этим делали cherry-pick, не разрешая повторно те же самые конфликты! Чертова магия.

Случай два случился, когда я попробовал реорганизовать проект моей группы с использованием git submodules. Идея заключалась в том, что, раз у нас есть пяток модулей, каждый из которых проходит свой небольшой цикл разработки и по сути версионируется, логично было бы разделить историю проекта на несколько репозиториев, чтобы упростить историю и облегчить мерджи. Опять же, казалось бы, что может пойти не так? Я уже предвкушал в своём воображении, как у меня в основном репозитории будет ветка RC с оттестированным кодом и ветка Dev, в которой мы будем проводить интеграцию…

Я затрудняюсь сказать, сколько рабочего времени мы потеряли, пытаясь использовать эту конструкцию. Правда заключается в том, что единственное, для чего предназначен git submodules — это чтобы вы могли зачекаутить версию Linux Kernel, которую специально обученный человек собрал для вас по модулёчку. Всякие идеи о том, что разработчик может зачекаутить проект с сабмодулями, внести изменения в один из модулей, исправить баг во втором, а потом засунуть всё это обратно на сервер, надо сразу отбросить, потому что git submodules не предоставляет вам ничего. Ссылки на сабрепы не трекают ветви (вернее, трекают на уровне default pull/push, но эта привязка никак не сохраняется на сервере); git commit толком не умеет обнаруживать изменения в сабмодулях; попытка откатить или смерджить корневой репозиторий обычно приводит вас куда-то в ад из конфликтов слияния, которые были сто лет назад разрешены… Опять же, какой ответ? Можно написать кучу скриптов для того, чтобы этот велосипед делал только безопасные действия: скрипт чекаута, скрипт коммита, скрипт слияния — но мы предпочли позорно отказаться от борьбы с сабмодулями.

А ещё я могу назвать третью идею из GIT-агиток, которую нужно сразу отбросить: «Коммитим часто!». Нет, даже не думайте, что git заменит вам ваш костыльный скрипт с бекапом воркспейса через rsync. Коммитить недоделанные вещи, потому что вы собрались в командировку или в отпуск, вам категорически не рекомендуется. Любая тестовая правка «туда-обратно» непременно потом вылезет на git blame, даже если в итоге ничего не изменилось; редактирование истории выходит себе дороже… в общем, просто представьте, что ваш GIT — это такой SVN, в который вы коммитите большой блоб кода раз в неделю, и не пытайтесь хотеть от него ничего большего. Ну, или используйте Mercurial.

Сложно представить, сколько я получу минусов за то, что не встроился в общий хвалебный хор, но это реальный опыт человека, который рвался использовать Git сам и учить этому других, но не получил в результате ничего, кроме боли и проблем. Мне жаль, что разработчики Гита считают себя выше того, чтоб думать о типовых сценариях использования VCS, но это их личный выбор, а мы делаем свой собственный: Mercurial.
>Случай раз случился, когда я возжелал использовать merge --squash. Отличная, казалось бы, возможность переносить изменения из >приватной дев-ветки, где ты что-то делаешь, в общую ветвь репозитория, делая красивый коммит с комментарием «Исправлен баг #32143».
А зачем так делать? Почему просто незамержить? Объединять у себя надо было.

>Коммитить недоделанные вещи, потому что вы собрались в командировку или в отпуск, вам категорически не рекомендуется.
Фигня какая-то, можно комитить все что захочешь в контексте своей ветки, вот в паблик что-то неработающее отдавать нельзя да, при этом при сливе своей ветке в общую всегда можно все коммиты объеденить например в один, если хочется.
Да можно и опубликовать свою ветку, если, что, при условии, что ты уверен, что никто из команды не будет её трогать. Тогда можно будет её потом вытянуть, скажем, на домашнем компе, поправить, отребейзить и запушить с форсом обратно. Гит даёт редкостную свободу, но любая свобода подразумевает ответственность.

К меркуриалу у меня в этом плане есть претензия. Тут много говорилось, что он не даёт многое делать. Ужасно не люблю, когда мне что-то не дают делать. Не люблю системы, которые умнее меня и лучше знают, что куда мне можно лезть, а куда нет.
И как вы тогда относитесь к тому, что гит не дает вам право указать на переименование-перемещение файла?
можно комитить все что захочешь в контексте своей ветки, вот в паблик что-то неработающее отдавать нельзя да, при этом при сливе своей ветке в общую всегда можно все коммиты объеденить например в один, если хочется.

Если ветка куда-то пушится, то никак нельзя при сливе в общую «все коммиты объединить в один». Потому что если объединение коммитов делать через git rebase -i на себя — то у ветки появится новый хид, и пушить её придётся потом с --force (и с бубном по замене HEAD если она хоть куда-то зачекаучена, хоть даже на вторую твою же машину). Если это делать через git rebase на публичную ветвь — то тогда тебе нужно свою ветку закрыть и отделить заново (см. описание ситуации с merge --squash и сherry-pick). Не закроешь — все повторные мерджи будут выдавать все те конфликты слияния, которые ты уже разрешил раньше.

Если же своя ветка никуда не пушится, а существует только локально, то проблем нет, но здравствуй скрипт бэкапа воркспейса. Который нужен только для того, чтобы изменения, которые ты закоммитил в VCS, при отказе винта никуда не пропали. К чему я, собственно, и пришёл. Но прикручивать костыльное резервное копирование к крутой и прогрессивной системе версий, это так стильно…
зачем скрипт бэкапа?
git push <backup_repo> --all/--mirror
не хватает?
Идея умерла в муках, когда оказалось, что конфликт, единожды разрешённый при merge --squash, требуется разрешать снова и снова при каждом последующем слиянии между эти двумя ветками. То же самое относится и к git cherry-pick.

мне кажется git rerere помог бы. Вот, вроде, практика использования

Всякие идеи о том, что разработчик может зачекаутить проект с сабмодулями, внести изменения в один из модулей, исправить баг во втором, а потом засунуть всё это обратно на сервер, надо сразу отбросить, потому что git submodules не предоставляет вам ничего. Ссылки на сабрепы не трекают ветви (вернее, трекают на уровне default pull/push, но эта привязка никак не сохраняется на сервере); git commit толком не умеет обнаруживать изменения в сабмодулях;

это в какой версии Git было?
помнится, в 1.6, да, не было, а вот в 1.7 начали пилить,
сейчас (и уже давно) git diff и status показывает статус сабмодулей (см. соответствующие маны, поиском по «submodule»)
git push может проверять (и пушить, если надо) запушенность сабмодулей, чтобы сохранять целостность связки запушенных коммитов с сабмодулями
Коммитить недоделанные вещи, потому что вы собрались в командировку или в отпуск, вам категорически не рекомендуется. Любая тестовая правка «туда-обратно» непременно потом вылезет на git blame, даже если в итоге ничего не изменилось; редактирование истории выходит себе дороже

эээ… коммитить тестовые правки в master/stable? или Вы о чём?
git clone https://github.com/funny_guy/just_for_lulz_code
вот черт, github не разрешает регистрировать funny_guy из-за подчеркивания ((
а так хотелось немного «оживить» статью…
В слиянии твоя ветка «наша», а чужая ветка — «их». Но в перемещении все наоборот — ты начинаешь с чужой ветки и заново добавляешь свои собственные коммиты поверх нее, даже если ты думал, что перемещал свою текущую ветку. Поэтому с точки зрения Git, твоя ветка «их», а чужая ветка — «наша»!
не сразу понял, что это mine и theirs. Может стоит вписать в статью? Так как все diff-tool (по крайней мере, которыми я пользовался) пишут именно так.
А вообще большое спасибо, это внесло ясность для меня: на моем текущем проекте все делается богомерзким rebase, а не православным merge, и я долго не мог понять, почему в конфликтах все наоборот!

Статья хорошая, но есть пара "но":


  1. неужели есть недостаток во всевозможных туториалах по Гит?
  2. любая статья на тему Гит/Меркуриал мнгновенно поднимает холивар на одни и те же темы между адептами обеих систем, который не заканчиваются вообще ничем (если кто-то твердо решил переметнуться, напишите комментарий).
НЛО прилетело и опубликовало эту надпись здесь

Публикации