Comments 292
Да он вроде тоже может, но результат будет отличаться.
Туда же и mercurial (hg), я его лет пять использовал (после svn), не хотел переходить на гит, т.к. там вроде бы все тоже самое. Пришлось перейти под «давлением общественности», и не зря, т.к. гит на прядок лучше. Теперь для меня норма — то, что не приятно было трогать в hg. Продуктивность выросла, и не важно кто там быстрее клоны делает.
Спасибо за комментарий по существу вместо балабольства о жигулях vs мерседесах!
Можете привести пример того, когда важно знать, в какой ветке родился commit? С Git это и правда не определить. Так что, например, после cherry-pick так сразу и не скажешь, что откуда пришло (но мне и не приходилось задаваться вопросом).
В гите можно мерждить ветку с флагом --no-ff
и тогда в network будет видно откуда коммиты пришли.
Кодинг конвенции же существуют.
В моем текущем проекте меня больше волнует есть ли конкретный коммит в мастере, или его там нет.
на мой взгляд ничего сложного нет
https://habrahabr.ru/post/106912/
Это только в мёрж коммите. В остальных коммитах будет всякая ерунда.
Да, конечно, но остальные коммиты будут в ветке. В network будут отдельно коммиты сделанные в мастер и отдельно коммиты сделанные в ветку + мердж коммит.
А для того что бы по номеру коммита из истории в мастере определить из какой ветки он в нее пришел достаточно посмотреть вверх по истории до ближайшего мержда. Ну и конечно ветку нужно называть по номеру тикета.
Вы что, не читали статью по ссылке?
После удаления ветки удаляется только метка ветки, а коммиты никуда не деваются. Они все еще висят в истории как отдельная ветка (если конечно ветку смерджили куда-то с флагом --no-ff
). Я даже больше скажу. Можно восстанавить ветку после удаления и начать работать с того же места на котором остановился (доводилось такое делать). И все ветки прекрасно видно в истории даже после их удаления. Сами полистайте историю.
Если вам лень читать статью, то объясню все на пальцах:
- Ветка master всегда эквевалентна продакшену
- Ветка develop предназначена для разработки.
Перед релизом обязательно сливаться в master.
Также полезным будет слить master в develop.
Если develop не сливать в master, то через несколько итераций расхождение веток может стать критическим (сталкивался с таким). - Ветка issue-123 создается по тикету #123.
Создается из master и мерджится в develop.
Если ей для работы нужны другие задачи, то они мерджатся в нее.
Ни в коем случае нельзя в нее мерджить develop ибо может потребоваться выкатить эту задачу до полного релиза с мерджем develop в master, а в этот момент в develop может быть еще не доработанная или не до тестированная фича. - Ветка fix-456 hotfix по тикиту #456 со срочными правками.
Создается из master и мерджится в master, develop и другие активные ветки по необходимости.
Далее выкатывается master с hotfix-ами.
Ветку develop не трогаем.
Работаю по этой схеме уже несколько лет в разных компаниях и ни каких проблем.
Не сталкивался с таким и даже слабо себе это представляю.
Протестировал немного.
Да, сделать такое можно.
Получается если создать ветку Б из ветки А, то они будут эквевалентны и будет сложно понять что это ветка Б сделана из А или А из Б. То есть какая из веток является изначальной и соответственно к какой ветке относятся сделанные ранее коммиты. Но если ветки эквевалентны, то какая принципиальная разница какая из них изначально созданная?
Что вы в корзину положите одно яблоко, что одно яблоко положите в корзину, все равно в корзине будет одно яблоко.
То же самое происходит если создать ветку Б из корня ветки А и смерджить в нее ветку А, но при условии что ветка А не участвовала в других мерджах. В моем случае это ветки issue-345 и issue-456 с общими коммитоми 916908b и 4310c9e. А вот с веткой issue-3 это уже не работает так как ветки issue-1 и issue-2 уже участвовали в мерджах.
У меня нет под рукой SVN чтоб проверить, но думается мне что там будет похожая картина
Но если ветки эквевалентны, то какая принципиальная разница какая из них изначально созданная?
Для репозитория, для CI/CD-систем и прочих «ботов» — никакой. Для людей, прежде всего для менеджмента, а то и СБ, может быть очень важно установить хотя бы факт того, что кто-то нарушал принятые регламенты работ над задачами, например, не создавал отдельную ветку под каждую задачу.
А в чем проблема?
- Есть задача, должна быть и ветка.
- Нет ветки — нарушил регламент.
- Есть ветка — смотришь в схему.
- Если там бардак, то задаешь вопрос разработчику.
- Либо он нарушил регламент, либо git так слил ветки.
- Если первым коммитом в ветке будет не мердж, то в схеме все будет нормально.
- Если бардака в схеме нет, то регламент не нарушен.
Если вы ну совсем никак не можете разобраться в своих коммитах, пропишите хук в PROJECT/.git/hooks/prepare-commit-msg.
Этот добавит #<BRANCH_NAME>
в конце коммита.
Называйте ветки по номеру задачи или по номеру задачи с префиксом issue-
и будет вам счастье.
#!/bin/sh
#
# Automatically adds branch name to every commit message.
#
BRANCH_NAME=$(git symbolic-ref --short HEAD)
BRANCH_NAME=${BRANCH_NAME/issue-/}
if [ -n "$BRANCH_NAME" ] &&
[ "$BRANCH_NAME" != "master" ] &&
[ "$BRANCH_NAME" != "develop" ];
then
sed -i.bak -e "1s/$/ #$BRANCH_NAME/" $1
fi
GitHub, GitLab и Bitbucket автоматом подцепят тикеты
Ну и не забываем про
git config --global --add merge.ff false
hg из коробки может добавлять номер тикета в коммит?
Именно номер тикета, а не название ветки?
И hg из коробки привязывает коммит к тикету?
Похожу вы просто не понимаете о чем говорите.
Да, git не добавляет название ветки из коробки, потому что это просто не нужно. А тем кому это нужно могут настроить хук.
Проблема то не в инструменте, а в умении им пользоваться.
Мне это нужно, но я не могу настраивать хуки на машинах других разработчиков. Со своими коммитами я сам разберусь, но копаться мне нужно в чужих.
Есть такая штука, называется: Внутренний регламент разработки ПО.
Документ в котором описано что и как нужно писать, а что писать не надо, code style и т.д. В него также входит описание настройки окружения и работы с ним. Каждый разработчик обязан ознакомится с регламентом и подписать его. В документе можно описать установку хук для гита.
В другом комментарии вы упомянули контейнеры. На контейнерах можно собрать окружение для проекта и распространять между разработчиками именно его. Таким образом у всех разработчиков будет одинаковое и актуальное окружение. В те же контейнеры можно добавить хуки для гита.
Даже если другие разработчики работают на фрилансе удаленно, и вообще они индусы, то все равно можно распространить между ними регламент и контейнер с окружением.
Если вы находите ресурсы для контроля за работой других разработчиков, то найдите ресурсы для регламентирования и упорядочивания их работы.
Не усложняйте работу себе и другим.
Какое счастье, что в hg хуки версионируются вместе со всем остальным кодом.
Это как? Рабочую копию в контейнере держать? Хостить в нём репозиторий?
Я с контейнерами не работал. Если верить статьям по работе, то это можно сделать. Я же имел дело с использованием такого подхода в vagrant.
Если говорить вашим языком:
Вы сами заявляете, что у вас есть кожух на циркулярке, но ваши люди продолжают резать руки. Значиь либо кожух плохой и не защищает, либо людей нужно учить им пользоваться.
У меня нет кожуха на циркулярке. Я и мои коллеги не режем руки. Может не в инструменте дело?
PS: не смотря на мои критические заявления, я не хочу сказать что git лучше hg. Вам он больше нравится и лучше подходит. Окей. Рад за вас. Я не хочу оспаривать ваш выбор. Я лишь хочу донести мысль, что hg не серебрянная пуля. Он не решает ваши проблемы в полной мере, как и не будет их решать git.
Забыл сказать. Проблемы есть только с тестированием, когда нужно отдать задачу на тестирование тестировщикам.
По правильному нужно тестировать задачу сначала отдельно (как отдельную ветку), а потом сливать в develop и тестировать еще раз на совместимость с другими задачами в develop.
У нас тестировщики были ленивые и тестировали сразу develop что изрядно усложняло разработку и ветвление в git.
По правильному нужно тестировать задачу сначала отдельно (как отдельную ветку), а потом сливать в develop и тестировать еще раз на совместимость с другими задачами в develop.
По правильному никакого develop быть не должно.
По правильному никакого develop быть не должно.
Спорное утверждение. Ветка develop по сути содержит ветки которые попадут в следующий релиз. Можно ветку назвать release или release-1.2.3 по номеру версии следующего релиза. Можно для релиза создать отдельный тикет и соответственно ветку назвать по номеру тикета как и все обычные ветки.
Суть этой ветки в том что бы всегда видеть что будет в следующем релизе. Например показать спонсорам набор фич, лишний раз протестировать на совместимость фич, можно отдать на тестирование на сторону. Если ветки develop не будет, то придется каждый раз мерджить все ветки как появится необходимость и каждый раз по новой решать конфликты.
Если в качестве пререлизной ветки использовать master, то будут проблемы с выкатыванием хотфиксов без фич которые уже смерджены в master
Также частым решением бывает создание сайта разработки dev.example.com. Если example.com эквивалентен ветке master, то для сайта dev.example.com выбирают эквивалентом ветку develop. Если мы будем называть ветку release-1.2.3 или issue-123, то будут проблемы с настройкой автодеплоя сайта dev.example.com так как ветка постоянно меняется.
Это что касается web. Для других проектов это может быть не актуально и там возможно и правда не нужна ветка develop.
Из собственного опыта скажу, что при разработке библиотек, ветка develop действительно только мешает, а при разработки крупных сайт-проектов сильно спасает.
В том-то и дело, что решение о том попадёт ли фича в релиз может быть принято только после полного её тестирования и в том числе тестирования совместимости её с другими фичами релиза. Если вы начнёте мёржить/ребейсить фичу с девелопом, то намертво свяжете свою фичу с другими фичами и если хоть одна из этих фич не готова к продакшену, то весь релиз придётся отложить. В особо запущенных случаях девелоп становится на столько нестабильным, что приходится вводить целые стабилизационные спринты, чтобы никакая новая фича его не ломала, а вся команда сконцентровалась лишь на том, чтобы довести девелоп до продакшена.
Идеальный воркфлоу выглядит следующим образом:
- Разработка идёт в фиче-ветке
- Фичеветка всегда доступна на сервере по урлу вида feature-123.api-345.example.org
- Там же она тестируется и задача переводится в статус "завершена".
- Когда нужно выпустить релиз, создаётся фичеветка "release-678", куда автоматически сливаются все завершённые задачи.
- Как и любая фича, релиз тестируется, потом деплоится, тестируется уже на проде и только потом вливается в мастер.
- Фича конфликтует с другими, то она возвращается в разработку и автоматически удаляется из релиза путём его пересоздания.
- Если автоматическое слияние не проходит, то ставится статус "требуется ручное вливание в релиз".
- Хотфиксы вносятся либо в фичеветку и они автоматом подливаются в релиз. Либо в сам релиз, если это фикс интеграции. Никаких ребейсов и прочих мёржей релиза в фичеветку.
Готового инструментария для всего это дела я не встречал, так что приходится велосипедить, но оно того стоит.
Ну это уже савсем идеальный мир. Я с таким не сталкивался и необходимости в такой идеалезированности не было.
Но я учту вашу мысль на будущее
Перечитал еще раз ваш комментарий
решение о том попадёт ли фича в релиз может быть принято только после полного её тестирования и в том числе тестирования совместимости её с другими фичами релиза
Вы не заметили что описали рекурсию? Фича попадет в релиз только после проверки совместимости с другими фичами которые тоже должны пройти проверку на совместимость в том числе и с фичами которая добавляются в релиз после них.
Тестирование на совместимость в идеальном мире должно происходить многосторонне. В вашем примере получается, что группа разработчикав работавшая над фичей А должна проверить все ли у них работает после объединения с фичей Б, а разработчики фичи Б должны проверить весь свой функционал после мерджа с фичей А. Тестирование должно повторится после добавления фичи С и еще раз после добавления фичи Д и т.д.
Да, мы можем тестировать ветку на совместимость с другими ветками которые должны попасть в релиз. Но пока релиз не создан это просто висячие в воздухе ветки. Их список знает только тимлид и нет гарантии что пока вы тестируете ветки на совместимость не изменится список веток и сами ветки. На мой взгляд это перебор. Тестирование ради тестирования. Если фич всего 2-3, то еще можно жить, а если 30-40, то уже проблема тестировать все это у себя.
Потому я и говорю что нужна ветка с релизом чтоб не делать одну и туже работу многократно:
- Мерджмастер создает ветку релиза (это может быть develop, release-678, issue-123 и тд. Название в данном случае не столь важно).
- Мерджит туда все фичи и баги которые должны попасть в следующий релиз.
- Если есть конфликты, то релиз отменяется и тикеты возвращаются разработчикам для доработки. Возвращаемся к п. 1
- Если все смерджилось нормально, то ветка отправляется на тестирование на совместимость.
- Каждая команда проверяет работу того куска за который отвечает она.
- В случае проблем с совместимостью релиз отменяется и задачи возвращаются на доработку. Возвращаемся к п. 1
- После успешного завершения тестирования релиз выкатывается.
Идея с feature-123.api-345.example.org моя голубая мечта и я пытался такое внедрить, но у меня еще не было ни одного проекта и компании которые могли себе такое позволить, а я работал над очень крупными hl проектами с милионами пользователей. Проблема же не только в доменах и автоматическом развертывании фич. Проблема еще в том что фичи зачастую завязаны на базе и для каждой фичи нужна своя копия базы, может и урезанная, но своя. Тоже может касаться NoSQL и ElasticSearch. Фактически, окружение для фичи должно быть максиму приближено к прод, но должно быть изолировано от других фич. А это уже совсем не детские ресурсы. Может в mail.ru или яндекс такое есть)))
PS: мне немножко странно почему вы релиз тестируете на проде и сливаете его в местер только после завершения тестирования. Мастер должен быть всегда эквевалентен проду. А для фиксации статуса используются теги, они же релизы в большинстве случаев. Если на проде баг то мы откатываем как прод, так и мастер. Не должно быть разделения. А то у вас получается мастер вообще как-то отдельно от всего, в воздухе висит. Ну это уже ваше дело. Я не критикую.
Каждая команда проверяет работу того куска за который отвечает она.
После этой проверки обязательный этап тестирования в целом как минимум критической функциональности тестировщиками, которые отвечают за проект, а не за фичи и куски…
А это уже совсем не детские ресурсы.
В редких случаях тип инцидентов по производительности нужна база по объему близкая к базе прода, а то и её клон. Обычно для разработок фич и фикса багов достаточно копии схемы базы и совсем немного фейковых записей, может даже автоматически генерируемых. И разворачивание копии базы под каждую активную ветку задача доступная по ресурсам даже фрилансеру-одиночке, особенно если делать это в контейнерах, а не виртуалке.
Вы, фактически, описали то же, что и я, перечитайте мои 8 пунктов. :-)
Мастер физически не может быть всегда эквивалентен проду в любой момент времени. Но он никогда не должен обгонять прод иначе отмена релиза может привести к куче проблем с реверсмёржем и последующим реверсреверсмёржем.
Теги в гите могут быть аннотированными, и они таки часть истории.
Существует слово "тег". https://habrahabr.ru/post/212657/
Немного не так.
У мерка есть аналог гитовых веток — букмарки.
У гита аналогов мерковых веток нет.
Насколько я вижу, архитектура mercurial позволяет запилить туда в качестве расширений git’овские ветки (закладки начинали как расширение), фазы (аналогично) и даже таких монстров как evolve — расширение, позволяющее “переписывание” истории, при этом в значительной степени сохраняя её неизменность — должно позволять делать rebase
без push -f
, насколько я понимаю. Вопрос: почему ничего подобного не делали в git? Не то что evolve, git’оводы на вопрос «как ко всем изменениям автоматически прикреплять номер тикета» нормально ответить не могут — архитектура не позволяет.
Собственно, по моему мнению для закапывания git достаточно посмотреть на его потенциал развития — сразу после рассматривания его CLI. К сожалению, github вместе с большинством разработчиков сами знаете на чём.
Ну и hg более «человечен» что ли. Я работал с тем и другим и в hg всё понятно интуитивно и есть прекрасный удобный клиент (TortoiseHg). В git же надо либо вникать, либо курить мануалы. И GUI хуже.
А чем не устроил TortoiseGit? TortoiseSvn в туже степь. Можно еще gui из PhpStorm, но я лично gui не использую. Мне консоль удобнее.
Не троллинга ради, я сижу на hg, и те пару раз, что пришлось иметь дело с гитом, казалось, что пересел на жигуль. Без аллегорий, расскажите подробнее о преимуществах, а то чувствую себя отщепенцем на hg, а мотивации переходить на гит нет.
Особенно учитывая, что у гита бранчей фактически нет, а есть лишь "автоперемещаемые теги".
Rebase позволяет формировать цепочки изменений в том виде, в котором они должны быть представлены независимо от внутренних процессов разработчика; он может коммитить каждую секунду, может для себя делать что-то в таком стиле, но на публичную фиксацию и/или командное взаимодействие подаётся уже продукт, а не сырьё. Качественного аналога в Hg нет.
Stash позволяет формировать внятную последовательность изменений в типичном (в моих краях и задачах) случае, когда, начиная какую-то мелкую правку, обнаруживаешь, что вслед требуется цеплять что-то более крупное, а там и докатываться до больших рефакторингов. Изменения, которые стронули лавину, откладываются, и так может быть несколько раз. И даже без этого, после приёма новых чужих изменений из аплинка, он помогает их аккуратно скрестить. (Аналог — говорят про queues, но это только частичная замена, и говорят, что их выпилят за концептуальную несовместимость.)
Index (с add -i, add -e) или помогает stashʼу, или позволяет отправлять только часть изменений; например, в моих задачах типично, что я навешиваю в локальных функциональных и интеграционных тестах расширенную отладку, которая не должна попадать аплинку; также могут быть адаптации под локальную платформу, и т.п. (Замечу, что Tortoise клиенты дают такое для всех поддерживаемых SCM; но «из коробки» в Hg и SVN этого нет.)
Теперь про «ветки» в Hg — тут есть ряд злобных засад. В Hg понятие ветки это смешение нескольких разнородных сущностей в одну не сильно приятную (именно из-за смешения) кашу:
- «Голова» процесса развития, которых может быть несколько в пределах одной рабочей копии или «ветки» в другом понимании. При операциях push, pull передаются все эти головы. В некоторых местах это называется напрямую словом head.
- Некий установленный локальным режимом тег под названием «branch», который приклеивается к каждому новому changesetʼу, и больше ничего не делает. Именно его чаще всего называют «веткой».
- Полный пучок п.1, между которыми тоже можно переключаться.
Основное неприятное тут то, что именно авторы Hg принципиально поддерживают этот бардак. (И я ещё не вспомнил bookmarks, которые тоже ветки, но иначе.) Прямая цитата из родной вики: «The term branch is sometimes used for slightly different concepts. This may be confusing for new users of Mercurial.» Но в результате те, кто хвалят ветки Hg за их персистентность, имеют в виду только ветки-2 и только факт явной пометки в истории. Но на самом деле эти пометки не являются ветками — это теги ченжсетов. (А почему именно один такой тег и только branch, если механизм таких тегов в принципе существует, почему он не расширяем?)
Аналог «веток-2» (тегов коммитов) для Git делается не прямо, но через pre-commit hook можно редактировать сообщение коммита. Но если такое делают, то лучше вписывать не какой-то непонятный branch name, а ссылку на тикет, в рамках которого это делается; на моей прошлой работе такое делали — такой хук вылавливал номер тикета из имени локальной ветки (в смысле Git).
По всему описанному, для меня пробы работы под Hg закончились только возмущением «и как в этом бардаке можно что-то делать?», после продирания через грязные коммиты с посторонним мусором, зависшие головы и невозможность без дикого напряга привести всё это в порядок (в итоге я перекинул всё в Git и успокоился). Некоторые из этих возможностей Hg, однако, выглядят иногда полезно. Безымянные головы (но при условии — только в рабочей копии, и нельзя делать push, пока их больше одной, и не по умолчанию). Или автоприклеиваемые к сообщению коммита строки (лучше — набор с именами и содержимым). Но и без них отлично работается.
И ещё одно — очень часто говорят, что на Hg легче переходить после CVS и SVN, чем на Git. Мне получилось строго противоположно — после CVS Git оказался лёгким и простым, а с SVN и Hg резко не сложилось.
Спасибо за подробный ответ.
Кстати, что касается stash, в Mercurial версии 2.8 и выше поставляется ShelveExtension. Как я понимаю, это тот самый stash и есть.
Для git add -i
тоже есть аналог и без TortoiseHg. Раньше это было реализовано в RecordExtension. А сейчас уже есть "из коробки": hg commit --interactive
А про "легче переходить", скорее всего, обычно имеется в виду более согласованный синтаксис команд в Mercurial, в отличие от "полной анархии" в командах Git (см. мой комментарий ниже). Вряд ли на этапе перехода всплывают концептуальные нюансы использования веток.
> ShelveExtension
Нет аналога --keep-index. Также непонятно, относится это только к файлам, которые уже под контролем, или вообще ко всем. В Git это управляется опциями, можно stashʼем убрать вообще всё, можно только то, что в известных ему файлах.
> hg commit --interactive
В Git я могу набирать индекс по частям и постепенно, анализируя, что получилось, возвращая части и снова добавляя, сравнивая диффы между рабочей копией и индексом, и что попало в сам индекс, могу что-то подправлять прямо в самих диффах (в варианте add -e), могу сложить его в stash. (Как правило, нужно в таких диффах удалять дополнительную отладку или специфические локальные опции, но иногда бывает и то, что должно идти в следующий коммит.)
hg commit --interactive
это набор подмножества патчей одним махом. Если они меня не устраивают в таком виде — начинается некрасивая работа по бэкапу файлов и ручной вычистке ненужного.И описанные тут «могу» и «приходится вручную» относятся к реальным и регулярным случаям.
> А про «легче переходить», скорее всего, обычно имеется в виду более согласованный синтаксис команд в Mercurial,
Аргументация сторонников Hg тут, как правило, была иной — им нравилась хотя бы частичная эмуляция стиля линейной последовательной истории, начиная с номеров коммитов для локального репо. Синтаксис команд звучал как аргумент, но не для лёгкости перехода. Я не психоаналитик, чтобы раскапывать тут реальные связи, поэтому ограничился наблюдаемым.
До последних версий (3.8? я сбился с историей нумерации) он был непригоден. Сейчас надо перещупать заново.
> частичный коммит реализован искаробочным плагином record
1) deprecated 2) принципиальная разница в отсутствии явного индекса, я не могу перед коммитом посмотреть, что же получилось. (В описании вообще подтасовка — «interactively select changes to commit» не подразумевает самого коммита, но он происходит.) Да, можно потом корректировать историю, но это много лишних движений. Ещё и легко ошибиться (strip без --keep потеряет изменения).
> hg shelve (правильно, это тоже искаропки)
И снова без возможности учесть индекс. Как-то его, я смотрю, в Hg совсем не оценили, и всё сравнение в итоге утыкается в него.
> Mercurial же просто записывает всё за пользователем.
Я бы оценил эту фичу в варианте 1) автоматически не включена, 2) препятствует внешнему обмену, пока не указана конкретная голова или не осталась одна. Но в текущем варианте это источник тяжёлых диверсий.
Я про «до».
> Ну это, в гите наличие индекса существенно усложняет чуть менее, чем весь интерфейс. А пользы — чуть.
Ну вот тут и видна фатальная разница. Для меня это не «чуть», это критично. И соответственно ценность всех остальных механизмов, если они это не поддерживают, снижается в разы.
> Таким образом, без дополнительных телодвижений новые головы просто-напросто не выпинываются.
OK, принято. Я не помню, откуда взял про передачу всех голов — скорее всего, это утверждал один из апологетов Hg, а я не проверил. Осталось не разрешать их локально по умолчанию :)
Rebase позволяет формировать цепочки изменений в том виде, в котором они должны быть представлены независимо от внутренних процессов разработчика...
Это в каком виде? В виде, не соответствующем реальности? А зачем? Какой прок от недостоверной истории?
https://habrahabr.ru/post/179123/
https://habrahabr.ru/post/179673/
Stash позволяет формировать внятную последовательность...
Оно всего-лишь создаёт скрытую локальную ветку для незаконченной работы. Это даже в SVN не сложно реализовать, не говоря уж о том, что в HG оно есть из коробки.
Index (с add -i, add -e) или помогает stashʼу, или позволяет отправлять только часть изменений...
Чувствую у вас не редки ситуации, когда у вас на машине "всё работает", а у того, кто пульнёт ваши изменения, всё сломается, ибо вы то забыли закоммитить, то закоммитили чего лишнего.
Hg понятие ветки это смешение нескольких разнородных сущностей в одну не сильно приятную (именно из-за смешения) кашу...
Я так и не уловил этого тонкого различия. Почему вы противопоставляете часть (голова) целому (ветка)? Ветка метро — это всё множество последовательно соединённых станций, или только лишь конечная станция?
после CVS Git оказался лёгким и простым, а с SVN и Hg резко не сложилось.
Ничего удивительного. Git — это этакий прокачанный CVS, который отслеживает не отдельные файлы, а группы файлов, и плевать он хотел на историю их содержимого (которое кочует между файлами).
Должна ли история сохранять все опечатки и душевные метания программиста? Я лично живу в мире, где лучше, что автор выставляет некоторое «предложение», и только с момента его принятия оно становится частью истории, независимо от того, какие внутренние процессы привели к нему.
Ссылки на статьи после этого — забавны, но не имеют отношения к текущему обсуждению, и, по-моему, вообще ни о чём. Если требуется рабочее состояние после каждого коммита, то это должна обеспечить автоматизированная проверка. Например, у нас к Gerritʼу для этого был прикручен Jenkins. Если коммиты были отправлены под другую версию, и корректировка под новое API была сделана потом одним рывком, а не на каждый участвующий, то проверка не прошла, и это уже вопрос административный, допускать такое вообще или нет. Но хуже то, что с merge, которое предложено взамен, если это именно merge, то по любому получим неработающую версию после слияния, а если тут же править результат слияния, то это будет уже не честное слияние, а доработка. По-моему, тут идеального выхода нет вообще.
> Оно всего-лишь создаёт скрытую локальную ветку для незаконченной работы. Это даже в SVN не сложно реализовать,
Локальную — в SVN?
> Чувствую у вас не редки ситуации, когда у вас на машине «всё работает», а у того, кто пульнёт ваши изменения, всё сломается, ибо вы то забыли закоммитить, то закоммитили чего лишнего.
Бывают — там, где нет автоматизированной проверки коммита. (Сейчас я расслабился, потому что основную компоненту веду один. Раньше за счёт центрального Gerrit с code review такое не проходило, и приходилось заботиться сразу.) Но доля таких ситуаций всё равно в разы меньше, чем грязи в процессе, когда вначале коммитится со всеми локальными мотлохами, а потом они вычищаются (а часто даже тупо забываются, пока не всплывают на продакшене). Так что чисто статистически от этого тоже польза.
> Я так и не уловил этого тонкого различия. Почему вы противопоставляете часть (голова) целому (ветка)? Ветка метро — это всё множество последовательно соединённых станций, или только лишь конечная станция?
Потому что Hg позволяет быть нескольким безымянным головам одновременно. А это уже в случае метро не одна ветка, а несколько, вплоть до всей сети.
> Ничего удивительного. Git — это этакий прокачанный CVS, который отслеживает не отдельные файлы, а группы файлов, и плевать он хотел на историю их содержимого (которое кочует между файлами).
Я не понял логики этого замечания. CVS следил за каждым файлом отдельно, а Git, оказывается, «прокачанный CVS», но за одним файлом уже не следит.
Я не говорил о публично выставленной части (тут скорее надо сослаться на концепцию Phases), хотя и тут есть разные мнения — иначе бы в `git help rebase` не было секции «Recovering from upstream rebase». Но именно свою локальную работу привести в порядок, по-моему, обязательно.
> вероятно, речь об угадывании rename/copy вместо записывания
Тут я тоже удивляюсь, что мешает в Git добавить запись этих данных, если автор явно хочет. Вероятно, они не считают частный случай настолько существенным (над частичным разбросом содержимого в разные файлы), а детект по содержимому сейчас работает достаточно неплохо (и для log, и для merge).
За git push -f любому дятлу следует отрывать клюв.
Нечаянно такое запушить не получится, так что разработка в адекватной команде не пострадает.
а если речь идет о неадекватной команде, то да, хуки или галочки в gui, смотря какой софт используется для репозитория.
можно, конечно, и git push someremote +somebranch, но это тот же самый force push
Одной конкретной явно указанной ветки, а не просто текущей ветки. Гораздо нагляднее и заставляет задуматься перед тем как нажать enter.
Ссылки на статьи после этого — забавны, но не имеют отношения к текущему обсуждению, и, по-моему, вообще ни о чём
Фальсификация истории системой контроля версий с внесением ошибок туда, где их не было — это "вообще ни о чем"? Ну-ну.
Но хуже то, что с merge, которое предложено взамен, если это именно merge, то по любому получим неработающую версию после слияния
Это еще почему? Вы после слияния конфликты не правите, тесты не прогоняете, упавшие сразу не чините?
Полностью автоматического слияния в общем случае не бывает, ручные правки являются частью процесса.
Да, после слияния логично ожидать наличия ошибок.
Вот только если вы те же самые коммиты склеите ребейзом — вы получите целую цепочку нерабочих коммитов и заведомо неверный результат поиска места ошибки, если она всплывет не сразу.
Зато история будет красивая и линейная.
В мерке вмсето мержа можно использовать graft AKA transplant, позволяющий копировать коммиты из ветки в ветку с разрешением конфликтов по одному. Связь скопированного коммита с оригинальным сохраняется в метаданных и показывается в дереве. Даже если будет ошибка из-за смены контента — ее легко проверить и установить по оригиналу.
У гита есть аналог cherry pick но он ссылку на оригинальный коммит добавляет только опциально и только в комментарий.
Мержит мерк лучше, поскольку учитывает не только текущее состояние файлов, но и историю их изменений.
И какой смысл рассказывать про чудо-индекс, если хороший тон — это маленькие коммиты, а mq в мерке кроет индекс как бык овцу?
Да, именно. Если убрать эмоции и само слово «фальсификация», которое уже содержит в себе эмоциональную оценку, то надо начать с признания, что истории, если она не зафиксирована в некоем авторитетном хранилище, вообще нет. Даже без SCM на локальных файлах можно написать любую историю, а с distributed SCM любого вида это становится тривиально — всегда есть возможность взять другую ветку или рабочую копию и повторить начисто. Поэтому вопрос должен стоять так — чего мы хотим от истории? Видеть коммит промежуточного кривого состояния каждый раз, когда программист отшёл в туалет, или всё-таки набор логически цельных изменений? Не знаю, как у вас, а вокруг меня второе таки преобладает.
> Это еще почему? Вы после слияния конфликты не правите, тесты не прогоняете, упавшие сразу не чините?
> Полностью автоматического слияния в общем случае не бывает, ручные правки являются частью процесса.
Именно потому, что ручные правки при merge предполагают правки именно конфликта, а не произвольного места.
Если у вас в foo.h поменялось getFoo() на getFoo(FooContext*), это не повлияет на неправильное использование уже несуществующего getFoo() в bar.c.
Чаще (по тому, что я видел) делают таки правки после мержа, чтобы разделять логически разные действия в разные диффы. Но это требует возможности отменить тестирование самого merge commit.
> Вот только если вы те же самые коммиты склеите ребейзом — вы получите целую цепочку нерабочих коммитов и заведомо неверный результат поиска места ошибки, если она всплывет не сразу.
Именно поэтому я и рекомендовал при таком ребейзе надо править нерабочие коммиты, а не делать правку им вдогон.
Это не настояние на ребейзе вместо мержа или наоборот. Это именно как сделать такой ребейз беспроблемным для будущего поиска.
> У гита есть аналог cherry pick но он ссылку на оригинальный коммит добавляет только опциально и только в комментарий.
Ну я её добавляю всегда. Автоматизация показа этой связи, возможно, полезна, но пока что не сталкивался с такой необходимостью.
> И какой смысл рассказывать про чудо-индекс, если хороший тон — это маленькие коммиты, а mq в мерке кроет индекс как бык овцу?
Не кроет он никак индекс, потому что для представления патча для mq он уже должен быть чистым от прочих изменений.
Rebase позволяет формировать цепочки изменений в том виде, в котором они должны быть представлены независимо от внутренних процессов разработчика; он может коммитить каждую секунду, может для себя делать что-то в таком стиле, но на публичную фиксацию и/или командное взаимодействие подаётся уже продукт, а не сырьё. Качественного аналога в Hg нет.
Пока дело касается только «внутренних процессов разработчика» rebase/histedit
в Mercurial работает. Чтобы он работал после push пилят changeset evolution. Единственное но: когда я последний раз использовал histedit в mercurial, цепочка «fold fold fold» (аналог «squash squash squash») требовала вводить сообщение об изменении три раза, при этом сохранялся лишь последний. В git всё было нормально. Как сейчас — не знаю.
Stash позволяет формировать внятную последовательность изменений в типичном (в моих краях и задачах) случае, когда, начиная какую-то мелкую правку, обнаруживаешь, что вслед требуется цеплять что-то более крупное, а там и докатываться до больших рефакторингов. Изменения, которые стронули лавину, откладываются, и так может быть несколько раз. И даже без этого, после приёма новых чужих изменений из аплинка, он помогает их аккуратно скрестить. (Аналог — говорят про queues, но это только частичная замена, и говорят, что их выпилят за концептуальную несовместимость.)
Есть расширение shelve
(в стандартной поставке, но не включено по‐умолчанию). Но для вашего use-case же используют что‐то вроде hg record
.
Насчёт последнего: по моему мнению, git add --interactive
неудобен, а hg record
неудобен вдвойне (если его за это время не допилили). Поэтому мной был запилен UI как часть дополнения Vim. Принцип работы является совместимым с любой VCS, единственное требование — возможность указать, в каких файлах изменения нужно зафиксировать (т.е. если вы найдёте VCS, принципиально фиксирующую только все изменения во всех файлах, то … это возможно и принцип будет примерно тот же, но моё расширение придётся сильно допиливать).
Index (с add -i, add -e) или помогает stashʼу, или позволяет отправлять только часть изменений; например, в моих задачах типично, что я навешиваю в локальных функциональных и интеграционных тестах расширенную отладку, которая не должна попадать аплинку; также могут быть адаптации под локальную платформу, и т.п. (Замечу, что Tortoise клиенты дают такое для всех поддерживаемых SCM; но «из коробки» в Hg и SVN этого нет.)
Ответил выше. Не удивлюсь, если узнаю, что tortoise клиенты используют тот же принцип, что и я (кстати, я, кажется взял его то ли из hg record
, то ли из hg crecord
: просто нужно сохранить где‐то «полную» версию изменённого файла, а на её место подсунуть то, что вы хотите сохранить).
Аналог «веток-2» (тегов коммитов) для Git делается не прямо, но через pre-commit hook можно редактировать сообщение коммита. Но если такое делают, то лучше вписывать не какой-то непонятный branch name, а ссылку на тикет, в рамках которого это делается; на моей прошлой работе такое делали — такой хук вылавливал номер тикета из имени локальной ветки (в смысле Git).
Бардак есть, но у mercurial здесь преимущество: проконтролировать поведение разработчика с ветками‐тёгами проще: pre-commit можно и забыть поставить на какой‐то машине и вам придётся писать ещё какой‐то hook на сервере, чтобы проваливался push
. Сделать так, чтобы у изменения оказалось неправильное имя ветки куда как сложнее (для всех изменений, кроме первого).
И откуда взялось «непонятный branch name»? Вам запрещают писать туда номер тикета (причём именно в mercurial: «хук вылавливал номер тикета из имени локальной ветки»)? Тут только вопрос к Web‐интерфейсу, будет ли он делать это ссылкой. Технически препятствий нет.
Лично мне в mercurial не хватает возможности изменения истории с помощью допиленного changeset evolution — так можно и приводить в порядок бардак, получая нормальную отображаемую историю, и при том сохранять неизменность истории. «Не хватает» в смысле «не поддерживается на bitbucket» и «официально не допилено» («the full implementation of the changeset evolution concept is still in progress»). Бардак в коммитах в mercurial действительно образуется и с ним нельзя нормально бороться после push — это основное достоинство git в моих глазах. Только с git я уже стрелял себе в ногу с помощью push -f
после rebase -i
, тогда как с changeset evolution что‐то невосстановимо удалить просто невозможно (невосстановимо без помощи администратора github либо контактов с другими разработчиками — я знаю про reflog, и я знаю, что он не поможет, если нужных изменений на моей машине никогда не было).
Честно говоря, не вижу смысла прятать "бардак", если это объективно отражает историю изменений.
Все, кроме гитоводов, привыкли к тому, что ветка растет от ствола или ветки потолще и включает все свои коммиты.
И только в гите ветка — это именованная голова, а принадлежность коммитов определяется только по связям и работает лишь до первого мержа.
Отсоединеннный коммит — это вообще уникальная гитофича, похожая до степени смешения на багу.
Необходимость помнить, запушен ли коммит, после мерка вымораживает.
История файла, меняющаяся при одних и тех же данных при изменении настройки чувствительности поиска совпадений, доставляет отдельно.
Любовь к rebase есть любовь к фальсификации истории в угоду чисто эстетического профита от няшной линеечки коммитов.
Я в свое время компанию-работодателя агитировал на переход с CVS на распределенную систему контроля версий. Сначала хотели на гит, но посмотрев и сравив, выбрали и мерк и не пожалели ни разу.
Я имею опыт эффективной работы с обеими системами, но гит напрягает больше, перекладывая массу мелочей (которые можно контролировать автоматически) на пользователя
> И только в гите ветка — это именованная голова, а принадлежность коммитов определяется только по связям и работает лишь до первого мержа.
Этого я не понял, учитывая, что безымянные головы вроде есть только в Hg, а для остальных различие между этими интерпретациями несущественно.
> Отсоединеннный коммит — это вообще уникальная гитофича, похожая до степени смешения на багу.
Оно существует только при особых режимах работы. Меня вот множественные головы напрягают больше :)
> Необходимость помнить, запушен ли коммит, после мерка вымораживает.
Этого не понял совсем. Сравнение с Hg или CVS/SVN? В любой распределённой системе локальный коммит может быть не запушен.
> Любовь к rebase есть любовь к фальсификации истории в угоду чисто эстетического профита от няшной линеечки коммитов.
«Эстетический профит» превращается в реальную потребность понимать, что происходило, при разборе через 1-2-5-10 лет, когда никто не помнит подробностей происходящего. И главное не линейка, а чёткость и законченность каждого отдельного действия, а также разделение действий по характеру (как минимум, ни в коем случае не смешивать форматирование, рефакторинг и изменение функциональности). Линейчатость удобна, но не критична.
> но посмотрев и сравив, выбрали и мерк и не пожалели ни разу.
Ну так не CVS же выбрали (имел я дело с одной конторой в 2015-м, принципиально сидящей на CVS — это был ужас). Но стоит таки оценить, как это повлияло на методы работы с кодом и с задачами.
Отсоединенный коммит — это тот, у которого есть предки (понятно почему), но нет потомков, и он не существует ни в какой ветке. Даже найти такой коммит бывает непросто. И да, так как он не в ветке — тоже будет когда-нибудь подчищен GC.
rebase позволяет полностью выстрелить себе в ногу, так как как раз разобрсять что происходило в последствии не будет возможным. Будешь видить красивые эстетические ветки, а как и из чего они получились — нет, и в истории CI будешь видеть одно, а потом бац и совсем другое.
То есть rebase с одной стороны позволяет получить красивый git log, с историей коммитов в виде чистовика, но вот цепочка реальных событий в жизни будет несовпадать. Поэтому проекты, где не используют rebase — организованы лучше.
Впервые слышу про «отсоединённый коммит». Обычно говорят про отсоединённую голову (detached HEAD) или «осиротевшие/удалённые изменения» (orphan[ed]/deleted), хотя говорить «осиротевшие» здесь несколько неверно. Причём в первом случае отсоединённым вы можете оказаться на абсолютно любом изменении, а во втором речь идёт про изменения, недостижимые ни из какой ссылки (не ветке, тёги тоже держат), безотносительно наличия/отсутствия потомков и предков.
И вы вполне можете удалить все ссылки и увидеть «удалённое изменение», не имеющее предков. Или сделать самостоятельно сделать git checkout --orphan
(именно поэтому неверно: осиротевшие не имеют предков, а не недостижимы), чтобы затем создать изменение без предков и потом успешно получить удалённое изменение, не имеющее предков.
Все таки, если у вас корпоративный медленный svn сервер, скорость работы с ним падает еще сильнее, если какая-то операция с svn делается 10-30 секунд, то за это время можно случайно на что-то отвлечься и потерять фокус над задачей и эти 10-30 секунд превращаются в 5 минут.
Пришлось перейти под «давлением общественности», и не зря, т.к. гит на прядок лучше.
Что можно сделать хуже, чем в гите?
Вы не работали с мерком.
Второе — гит всё-таки надо осваивать. Не бог весть какая rocket science, но если системой контроля версий пользуются не айтишники и возможностей svn им хватает — зачем заставлять людей тратить время и силы на непрофильные вещи?
Одну назову — возможность дать доступ только к определённым подпапкам в репозитории. Гит такого не может архитектурно — или всё, или ничего. Редкий юз-кейс, но возможный.
subtree позволяет вытащить любую папку, из которой потом можно сделать отдельный репозиторий. Мало того, это не просто даст доступ к папке, а также можно будет получить все историю изменений в этой папке.
Второе — гит всё-таки надо осваивать. Не бог весть какая rocket science, но если системой контроля версий пользуются не айтишники и возможностей svn им хватает — зачем заставлять людей тратить время и силы на непрофильные вещи?
Ну 95% использования git — это 5 команд. На моей практике осваивали даже люди около пенсионного возраста.
Тем не менее, заставлять, наверное, смысла нет. Но вот начинать новые проекты на svn — кощунственно.
Ваш кейс, ясное дело, не будет работать, потому что subtree split пробегается по всем коммитам и ищет такие, которые затрагивают нужную папку. Тут вопрос, зачем это вам.
Это миф. Если использовать только эти 5 команд — гите нет смысла.
Кстати, а перечислите эти 5 команд?
git flow можем посчитать за одну команду.
Ну ок, еще сюда можно вписать add, rebase, diff, log, хотя этого можно и не знать, используя какое-либо gui.
С Gui я могу и первые 5 не знать.Но надо изучать gui
Про 95% — чистая правда, но не все это понимают. Недавно пересаживал одну команду с архаики SVN на Git. БОльшая часть команды осваивала постепенно с базовых 5 команд к чему-то поумнее, типа cherry-pick, rebase [-i], и так далее. Но были и люди, которые привыкли учить что-либо "наскоком и целиком", как по учебнику. Вот они страдали больше, потому что learning curve выглядел для них хуже...
Ну 95% использования git — это 5 команд
«Привет, добро пожаловать в команду! Мы используем git-flow, вот ссылка на <те самые 5 команд, только во flow>. Все просто, вот эта ветка — девел, вот эта — мастер, вот тебе тикет на фичу, давай запили!»
git flow feature start, денек покоммитались, git flow feature finish, все красиво как на гламурной фотке в журнале… «ого, уже готово? отлично! слушай, это короче не могет ждать до следующего релиза, секурити риски, все такое, зафигачь это хотфиксом в мастер?»
Приплыли.
P.S. разумеется это решается, о да. Но нет, это вовсе не 5 команд.
subtree по гибкости раздачи прав и сложности использования сильно отстаёт от нормальных прав на файловой системе: во-первых, только папки, отдельные файлы нельзя; во-вторых, если в проекте появился новый файл с ограниченным правами доступа, достаточно сделать chown/setfacl, а не заморачиваться с заведением целого нового репозитория.
> Начинать новые проекты на svn — кощунственно
Кощунственно не использовать самый подходящий для конкретной задачи инструмент. Гит безусловно хорош, я сейчас только им и пользуюсь. Но стоит понимать, что в некоторых юз-кейсах он проигрывает svn. Кстати, посмотрел на упомянутый в статье svnvsgit.com и нашёл ещё один: работа с файлами по модели " Lock-Modify-Unlock".
subtree по гибкости раздачи прав и сложности использования сильно отстаёт от нормальных прав на файловой системе: во-первых, только папки, отдельные файлы нельзя; во-вторых, если в проекте появился новый файл с ограниченным правами доступа, достаточно сделать chown/setfacl, а не заморачиваться с заведением целого нового репозитория.
Наверное, есть где-то этот мир с единорогами, вечной радугой и гибкой раздачей прав на отдельные файлы в репозитории, но я его никак принять и представить не могу. Что будет делать пользователь с правами на три сорца, раскиданного по всему проект, для меня загадка. Как он будет что-то проверять, тестировать, кто потому это будет вливать и нести ответственность — для меня еще большая загадка.
о стоит понимать, что в некоторых юз-кейсах он проигрывает svn.
Этот тред начался с того, что я спросил, цитирую: «Какие вообще сегодня могут быть преимущества в использовании svn по сравнению с остальными vcs?». А вы мне говорите — в некоторых юз-кейсах git проигрывает svn. Я снова возвращаю к своему вопросу — в каких? :)
работа с файлами по модели " Lock-Modify-Unlock"
Вы серьезно что ли или троллите? Если серьезно, то у меня грустные новости — вы вообще не понимаете, как работает git. Тогда я не удивлен вопросам с непониманием перехода с svn на git.
Так расскажите же как правильно.
2. Можно ли разбить текстуру или модель на логические куски и в случае модели иметь один файл, который бы через ссылки собирал все воедино?
- Нужно-то как раз, чтобы несколько человек не редактировали одну текстуру одновременно, для чего и используются блокировки.
- В идеальном-то мире всегда можно, а в реальном как-то не всегда получается.
Такие вопросы должны решаться тем, кто распределяет задачи по конкретным исполнителям а не системой контроля версий.
Чем должен заниматься человек, если он получил (или дошел) до задачи, требующей редактирования какой-нибудь конкретной модели, а файл залочен?
Второй пункт всегда в силе ибо время, деньги first to market.
И почему вы считаете, что человек с этой задачей справится лучше программы?
Если файл заблокирован, то человек может либо заняться другой задачей, не требующей доступа к этому файлу, либо пойти к тому, кто его заблокировал и обговорить какие изменение тот вносит, когда закончит и не может ли он сразу же внести и необходимые первому изменения.
И почему вы считаете, что человек с этой задачей справится лучше программы?
Если мы говорим о распределении задач, то для этого и существуют менеджеры разных звеньев со своей областью ответственности. Когда программы будут заниматься менеджментом лучше людей профессия исчезнет сама собой.
Мне кажется, что менеджмент ресурсов и задач — не та задача, которая решается системой контроля версий по определению. Поэтому вменять гиту, что в нем нету локов на файлы потому что менеджер не проследил за ситуацией или менеджера нет вообще — несколько странно.
Вы когда-нибудь слышали про скрам, канбан и прочий аджайл, где менеджеры если и нужны, то только "на подхвате"?
Если все друг друга слушают, то выявить конфликт задач не составляет труда и поговорить до того как лок файла понадобится как инструмент разруливания конфликта.
Легко: репозиторий — какой-нибудь ansible или puppet. Файлики ssl_prod.pem и db_crypt_data_prod.key должны читать только админы, а ssl_dev.pem и db_crypt_data_dev.key — также программисты и тестировщики, чтобы наливать девелопмент и тестовые среды. А если роли шарятся между проектами, то db_crypt_data_prod.key должны читать только админы соответствующего проекта.
> А вы мне говорите — в некоторых юз-кейсах git проигрывает svn. Я снова возвращаю к своему вопросу — в каких? :)
Думайте шире. VCS применяются не только для разработки ПО с помощью редактирования кучи тесктовых файлов. Дизайнеры с *.psd, разные конструкторы/инженеры со своими специфичными CAD-ами, любые другие люди, чьи результаты труда храняться в бинарном виде.
> Вы серьезно что ли или троллите? Если серьезно, то у меня грустные новости — вы вообще не понимаете, как работает git
Я как раз понимаю как работает git, и понимаю, что «Lock-Modify-Unlock» он не может в принципе. Это не лучший воркфлоу для разработки ПО, но для специфичных юз-кейсов или для других задач(см. выше) он может очень даже подходить. Ну вот например не позволяет какой-нибудь схемотехнический CAD мёржить файлы описания плат, а одной платой два человека одновременно не занимаются, так у них построен рабочий процесс. Они сидят в SVN-е, лочат файлики и счастливы.
Легко: репозиторий — какой-нибудь ansible или puppet. Файлики ssl_prod.pem и db_crypt_data_prod.key должны читать только админы, а ssl_dev.pem и db_crypt_data_dev.key — также программисты и тестировщики, чтобы наливать девелопмент и тестовые среды. А если роли шарятся между проектами, то db_crypt_data_prod.key должны читать только админы соответствующего проекта.
Вариант "не хранить ключи и пароли в репозитории" не рассматривается?
В остальном (use case "svn как версионное хранилище артифактов") согласен.
А почему бы и нет, если с безопасностью репозитория всё не хуже, чем на продакшн-серверах? А скорее лучше, потому что доступен только из корпоративной сети и VPN. Ну то есть всё равно конечно дополнительная поверхность атаки, но если админы/безопасники считают это приемлимым, то почему бы и нет.
Мне сходу видятся следующие проблемы:
- сложность отзыва доступа (например, увольнение сотрудника: невозможно обеспечить недоступность закрытого ключа, т. к. он лежит в локально копии репозитория у этого сотрудника);
- отсутствие аудита доступа к ключевой информации (невозможно отследить как и куда копировался ключевой материал).
Но в некоторых пределах, конечно, рабочая схема, спорить не буду.
GIT-е такое настроить сложно, если вообще возможно — у него же все репозитории равноправны и нет какого-то главного, а стало быть они все должны обладать одинаковыми свойствами.
Это не так. И исходно было не так для того же linux'а. Существование blessed репозиториев вполне себе объективная реальность.
Вообще авторизация при работе с git'овыми репозиториями штука внешняя по отношению к git'у. Тот же gitolite (а ранее gitosis) позволяют относительно гибко работать с правами: защитить отдельные ветки/теги (начиная от push, заканчивая force push/create/delete операциями) в разрезе по пользователям/группам. Тот же gerrit (который уже управление code review) ещё более гибок и тяжел для нормального пользователя. Как промежуточный вариант — github/gitlab, которые позволяют управлять мержем pull request'ов по выбору владельца репозитория (или лиц к нему приравненных в рамках этих операций).
Ну вот юзкесы — хранение бинарных файлов. Например, мы храним картинки. Или тестовые данные. Тут сразу несколько недостатков git:
- нельзя залочить файл (а бинарники смерджить нельзя)
Два дизайнера пошли поменять одну картинку, и теперь работа одного из них пропадет. - необходимо вытягивать весь репозиторий, даже если нужно поменять один файл
Например, для смоук-тестов мы хотим брать только 5% тестовых данных. Или заранее подобранные для нужных тестов, тесты храним по папкам с id теста. Или дизайнеру надо поменять только иконочки, но ему придется вытянуть и фотографии. - невозможность просто раздачи прав на папка
— В разных папках разные виды картинок. Там, где 18+, доступ только для женатых.
— Там, где в тестовых файлах есть персональные данные — доступ только для подписавших бумажку.
Опять же, монотонно возрастающие целые номера коммитов в SVN как-то приятнее выглядят, чем гитовские хэш-суммы.
Например, у меня может быть часть проекта на аутсорсе (UI например), а IP в остальной части проекта. И я не хочу, чтобы вьетнамский фронтендер-фрилансер имел доступ к коду, реализующему мое конкурентное преимущество.
Или я хочу дать дизайнерам возможность force push-ить их кратинки, но чтобы они случайно не убили важный код.
Неужели вы думаете, что таких причин быть не может?
Что вы, я уверен, что у людей есть причины на любые глупости.
Но недостатком Гита будет не тогда, когда «а вы на шкаф залезьте», а когда идеология(и, в меньшей степени, реализация) не позволят решить бизнес-задачу.
Мне, например, кажется логичным или использовать репозиторий фрилансера как Submodules, или переносить в проект работу фронтэндера в рамках «приёмки» своими силами. А не давать физически публичный доступ к IP — парольная защита никогда не была идеальной, тем более на неё нельзя полагаться в каком-нибудь SVN, где это далеко не core-функционал.
Если у вас проблема с правами на подпроект фрилансера, то это проблема у вас.
Если у вас проблема с Submodules, то проблема у гита
> Submodules работает без подводных камней?
Да всё в этой жизни работает не без подводных камней :(
Да всё в этой жизни работает не без подводных камней :(
А вот это было бы интересно почитать.
и свой репозиторий. И Submodules.
- я правильно понимаю, что они сидят как подкаталоги? И система сборки должна быть настроена именно на такое расположение путей?
- я правильно понимаю, что при N проектах получится N копий каждого сабмодуля на диске?
- Какие ещё есть подводные камни?
> при N проектах получится N копий каждого сабмодуля на диске?
Можно попробовать сделать directory junctoin, или на подмодуль, или на .git подмодуля. Но это вручную
2) Это из серии «назвался груздем — полезай в кузовок». Если нужна отдельная, но активно разрабатывается библиотека, — надо под это workflow подгонять, что бы не комитить каждый раз все бранчи.
Смотрите: библиотека — это зависимость. Обновление зависимости нужно поддерживать (если интерфейс поменялся) и обязательно тестировать (потому что могло поменяться что-то внутри). Поэтому очень логично, что пока вы сознательно и явным образом не перешли на новый коммит библиотеки, ничего менять не нужно.
Работал тестировщиком на проекте на C++ с кучей зависимостей в субмодулях. Всегда было так, что обновление библиотеки — это интеграция, под которую выделяется время на разработку и тестирование.
Если amend — это опция commit, тогда я не понимаю, при чем тут она, можете объяснить поподробнее?
Ну например у нас часто встречается ситуация, когда сабмодуль обновляется несколько раз, а в надмодуле приходится делать уродские коммиты типа submodule++, следующие один за другим. Если использовать amend то по крайней мере коммит с обновлением будет один, а то и вообще можно схлопнуть с предыдущим.
Есть N проектов на K конфигураций железа. Соответственно есть N прикладных частей, есть общая прикладная библиотека, есть K аппаратных частей и общая аппаратная библиотека. И все это имеет разные права доступа для разных программистов.
А несколько репозитариев — и впрямь морока. И более менее регулярные проблемы от того, что при рефакторинге надо обновить все затронутые им репозитарии. А если забыл git pull на одном из 10 репозитрариев сделать- «ты фигню сделал, у меня не собирается».
Я бы даже на SVN не стал при такой связности так с правами морочиться…
А частей (репозитариев) у нас примерно N+K+M, где M — число библиотек.
У каждой части — есть ответственный, он и определяет у кого какие права.
А ваше решение с правами? Разрешить всем всё?
> Но если библиотека меняет API, то идут синхронные изменения во всех частях, где этот API вызывался.
Если у вас изменения в N модулях происходят синхронно, я не уверен, что «ответственный» — ответственный. Он может наложить вето на ваши правки? Он вообще в курсе, что что-то поменялось?
Вы, перед рефакторингом, ходите и получаете права на 10 частей у каждого ответственного? И остальным, скорее всего, не надо. Остальные сделают фигню — получат то же «ты фигню сделал, у меня не собирается».
На мой взгляд, надо или ответственность вернуть ответственным (пусть сами обновляют после обновления библиотеки, асинхронно), или с правами перебор (не надо решать организационные проблемы техническими средствами)
С одной стороны, 99.9% времени мы живем дружно. С другой стороны — мы живем дружно именно потому, что у каждого репозитария есть мейнтейнер, который отвечает за этот код.
Если у вас изменения в N модулях происходят синхронно, я не уверен, что «ответственный» — ответственный.
Почему? Если я отвечаю за библиотеку — я могу понять, что стоит сменить API. Сменить его, и исправить все места, где этот API вызывается. Если API новый и экспериментальный, такое бывает довольно часто.
пусть сами обновляют после обновления библиотеки, асинхронно
Гм, вы путаете обновления кода репозитария с получением последней версии репозитария.
Видимо нас спасет git submodule foreach 'git pull". Это если можно из нормальных репозитариев сделать такой супермодуль с пустым содержимым.
Если при этом проект не компилиться у ответственного — что-то тут не так. Как минимум, ограничение прав не помогло.
> Гм, вы путаете обновления кода репозитария с получением последней версии репозитария.
с чего бы?
Ситуация простая — я обновил свою библиотеку и сменил в ней API. Соответственно сменил в трех репозиатриях, где этот API вызывался. Запушил все в git. А коллега сделал pull лишь тем репозитариям, с которыми он постоянно работает. Но в одном из них было использовано новое API… И на такое налетаем раз в неделю…
Вроде бы можно через хуки автообновление после git pull сделать.
$ git config alias.spull '!'"git pull && git submodule foreach 'git pull'"
А у нас пока сабмодулей нет и встает вопрос, а не стоит ли их ввести. Проблема в том, что или делать изменении структуры десятков проектов или делать симлинки, работающие и на windows и на linux. Скорее второе.
Таким образом, мы получаем контроль за зависимостями из коробки.
В случае с симлинками нужно написать скрипт, который выкачает нужную версию и его нужно так же держать в репозитории. Т.е. мы имеем тот же функционал, что из коробки, но своими руками, только зачем?
В этом и кайф от деления на репозитарии.
P.S. Для испытаний, само собой, все репозитарии обновляем. Но для разработки — это просто не важно.
То есть у вас получается 2 типа релизов библиотеки(на которые стоит завязываться в submodules): изменение API и перед испытанием.
> В этом и кайф от деления на репозитарии.
Эм? Такой кейс же даже в одной ветке так работает, не? )
Эм? Такой кейс же даже в одной ветке так работает, не? )
Не понял, поясните чайнику.
Релизы у нас отдельно идут. То есть интеграция непрерывная, а релизы — это уже после прохождения всех испытаний. Перед релизами — некий период общей заморозки кода, когда баги правим, а фичи не вставляем…
Вот это в одном репозитории в одном бранче работает.
А про релизы — это про другое, про библиотеки. С виду интеграция у вас непрерывная, по факту — как получиться (контролируется только в 2-х случаях). Вот с непрерывной интеграцией и submodules будет непросто, но вам, получается, и не надо.
В СВН используется идеология, что ветка — это директория. Эта идея подкупает своей простотой и элегантностью. Но есть один косяк — если вы будете иметь доступ лишь к поддиректории проекта, то:
- либо теряете возможность полноценно бранчеваться, так как ваш "репозиторий" находится лишь в одной конкретной ветке "всего репозитория".
- либо начинаете бранчеваться внутри бранча и получаются в результате /project/trunk/gui/branches/123-better-design/outsource/trunk/
Выделять 2 файла из модуля и давать кому-то на разработку, забивая на тесты и вообще целостность модуля — идиотизм высшей степени.
А как у вас отлаживают свои правки в такой проект люди, не имеющие доступа к коммерческой тайне?
У нас большой C++, состоящий из большого количества модулей (компилируются в итоге в статические/динамические библиотеки). Ясное дело, каждый модуль мы можем выделить в отдельный репозиторий, и дать к нему полный доступ. Юзер может писать там код, добавлять тесты и т.д.
Финальный проект собирает такие модули в один проект, и компилируется в готовый продукт. Дальше уже готовый продукт тестируется на наличие разных ошибок и багов.
А «Выделять 2 файла из модуля и давать кому-то на разработку» — это к чему было?
Есть большой проект, который состоит из большого количества библиотек. Скажем, ModuleA, ModuleB, ModuleC и т.д.ModuleA, например — купленный за лям баксов проект у сторонней организации, и допиленный нами до нужного функционала. Лежит в отдельном репе. ModuleB — наша математическая модель, которую пишет всего пара человек, разбирающиеся в вопросе. Он также закрыт от большинства.
ModuleC — какой-нибудь удобный враппер над какой-нибудь библиотекой, нам все равно, кто его пишет, главное — чтобы хорошо работал.
Каждый отдельный модуль является самодостаточным. Его можно скачать, собрать, прогнать юнит-тесты и прочее.
Большой прожект состоит из этих мелких проектов, которые вливаются в него с помощью subtree. Он собирается на билд-сервере, дальше уже прогоняются юнит-тесты и прочие тесты всего проекта. Дальше q&a берут с сервера deb пакет, ставятся себе и уже тыкают в него на поиск багов, которые спрогнозировать сложно.
Данный воркфлоу вполне себе пашет уже долгое время, свои задачи он решает, все довольны.
А «Выделять 2 файла из модуля и давать кому-то на разработку» — это к чему было?
Это было к предыдущего сообщению:
Почему вы думаете, что иметь один репозиторий, давая доступ к его части лучше, чем иметь 2 репозитория?
Гит осваивать почти не нужно — разъяснить что кроме commit надо еще push, написать краткую вики и все. Просто нужно, чтобы в проекте был человек, который первые пару месяцев сможет разруливать нестандартные конфликты.
1. При копировании файла сохраняется его история
2. Раздельные права доступа на отдельные каталоги
3. Externals (хотя фича крайне неоднозначная)
4. Не нужно распихивать .gitignore по пустым каталогам
В гите всегда теряется история. Он пытается угадать, ища похожий файл в предыдущем коммите, но как правило часто ошибается. Для сравнения — меркуриал пытается угадать перед коммитом и если он угадал не правильно — ему можно объяснить как правильно.
Ну так в гите эвристика простая — если отличия превышают определённый процент строк, то файлы считаются разными. Такой вот кривой дизайн Торвальдс придумал. Починить это можно, например, добавлением мета информации где-нибудь сбоку, как к в SVN прикрутили merge tracking, но работать этот костыль будет также криво и косо. Так и живём: притворяемся, что в гите есть ветки, что легко можно восстановить историю кода, что команды логичны и удобны, что сквашивание коммитов и перебазирование нужно для "чистоты истории", а не потому, что невозможно достоверно понять какой коммит к какой ветке относился.
- Как костыль можно переименование и изменение разбить на 2 коммита
- Я не знаю как гит относится к отступам при перемещении файлов, но если в этом случае файл считается полностью измененным тогда это несомненный косяк
- Это сломается, когда все коммиты фичеветки сольют в один коммит в мастер "для чистоты истории"..
По умолчанию, гит считает файлы разными, если различия превышают 50%.
Есть ещё кейсы, когда файл разделяется на два или сливаются в один или ещё как хитрее. У систем контроля версий с этим сейчас туго и у гита — особенно.
Поэтому с SVN надо переходить на HG, а не на Git :-)
2. Этот тред обсуждался чуть выше — решается subtree и отдельным репозиторием.
3. Я, честно говоря, не очень в теме, что это.
4. .gitignore достаточно положить в корень репозитория.
По пустым каталогам обычно .gitkeep
распихивают, если действительно нужно версионировать пустой каталог.
Я это к тому, что .gitkeep
, а не .gitignore
(как пишет Rend). Так-то любой файл можно, но .gitignore
слегка сбивает с толку.
Из очевидного, большие бинарные файлы все ещё боль в git и hg тоже.
Для этого придуман Git LFS.
Для этого придуман HG Largefiles extension. Идёт в комплекте поставки, надо только включить в конфиге.
Это я пишу, как Gitовод, но в компании любят Mercurial, видимо, за large files из коробки.
А Git LFS надо спецом клиенту ставить, иначе молча пропускает...
Возможно, не только за большие файлы.
Мерк помнит, была ли уже запушена конкретная ревизия.
Мерк при мерже сливает граф патчей, а не просто два файла.
В мерке не бывает отсоединенных коммитов.
Для меня гит на фоне мерка напоминает профессиональный инструмент. Профессиональный в том плане, что любитель в процессе эксплуатации с легкостью отрежет себе пальцы, потому что про изоляцию проводки и каком-нибудь защитном кожухе над циркулярной пилой никто не думал — профи должен соблюдат технику безопасности сам.
В git help clone прекрасно описаны параметры
--depth
и--branch
, которые позволяют вытащить определенную ветку/тэг на указанную глубину. О depth в комментариях говорилось уже не раз.
- Держать
/etc
в репозитории для сохранения истории изменений в принципе можно. Ради последующего просмотра. Делать checkout крайне не рекомендуется: проблемы бывают от побитых прав на файлы (user/group/xattr/acl) до приведения системы в нерабочее состояние, но это сильно зависит от того, что живёт на сервере, может и пронести.
Права и атрибуты можно так же сохранить в VCS. Готовых систем я не видел, но технических препятствий не вижу, другое дело, насколько и как именно придётся заморочится и чем вы за это заплатите. С git’ом, кажется, будет проще, если написать скрипты‐обёртку над commit/status/checkout и сохранять данные об атрибутах в отдельных файлах, mercurial вроде позволяет написать расширение, улучшающее функционал встроенных команд и позволяющее сохранять дополнительные метаданные (и ещё посылать пользователей, хотящих сделать clone без установки расширения), но это должно быть более трудоёмким. Subversion — не знаю. С сохранением метаданных у него вроде лучше чем у git, но про расширения я не слышал.
git archive "$BRANCH" "$OPTIONAL_PATH" --remote="$REPO" | tar -x -C "$DESTDIR"
Но сервер может не поддерживать. С гитхаба у меня так стянуть не удаётся.
Для этого там другая фича — режим просмотра файла Raw.
Но вообще файлы без истории как-то не ок.
Но вообще файлы без истории как-то не ок.
Сейчас стильно-модно-молодежно ставиться из репа напрямую, Атом так свои плагины ставит например. То есть речь идет о файле, для которого никто никогда не посмотрит не только историю, но и сам файл.
Например, деплой. Зачем там история? Нужен только определённый коммит
Понятно, что CVS могут выкатить данные без истории.
Но выкатка подразумевает другое, в зависимости от админов.
Почитайте на досуге про Capistrano (один подход) или про Opscode Chef.
P.S. у нас выкатка подразумевает Blue/Green, или хотя бы npm run build
/make build
.
Понятно, что CVS могут выкатить данные без истории.
Только CVS дико тормозной, если вы, конечно, имели ввиду Concurrent Versions System.
Понятно, что там ещё всякие проверки, миграции и прочее, но код-то из репозитория всё равно скачать надо, если язык не компилируемый
> Capistrano (один подход) или про Opscode Chef
Я люблю няшненький питончег, поэтому Ansible :)
Из статьи я так и не понял, почему же стоит мигрировать с уже работающего свна на гит
ну опровергнутые аргументы такие себе, получается правы сослуживцы, считающие, что шило на мыло
Когда говорят о том, что размер репозитория больше, говорят в основном о том, что нельзя часть репозитория вытащить. То есть если у вас 20 гигабайт репозиторий, то вам придется тащить сначала все 20 гигабайт, даже если вам нужно поменять 1 файлик на 10 байт. В SVN любая папка сама по себе практически репозиторий.
Про ветки — даже если в svn сделать ветку также легко, как и в git-e, то это не значит, что они такие же легкие. Операции с ветками, например слияние, в svn все-таки тяжелее проходят. А merge (и rebase) — это главная операция для веток все-таки.
Основные преимущества гит перед свн:
- скорость работы
- быстрые и качественные операции над ветками — merge и rebase
- образцово качественная утилита командной строки с очень богатым инструментарием
Основные преимущества свн перед гит:
- возможность заливать большие файлы без потери производительности (актуально для документации и не только в IT)
- наличие GUI для секретарш
- быстродействие не деградирует для очень больших репозиториев (монорепо или просто крупный проект)
- возможность назначать права на каталоги.
наличие GUI для секретарш
А что для Git не существует гуев "для секретарш"? SourceTree, Tower, GitUp — это то что на вскидку вспомнилось.
Source Tree — относительно универсальная среда и поэтому не всегда пользуется терминологией гита, что при знании консольных комманд заставляет каждый раз задумываться, что происходит под капотом.
Мое личное мнение — для гита нужно использовать либо консоль, либо GUI написанный специально для него, чтобы «секретарши» говорили на одном языке с теми, кто GUI не пользуется.
Для секретарш советую использовать расшаренный диск или FTP, или даже WebDAV. Меня всегда удивляло, что в плюсы SVN записывают аспекты, не относящиеся к разработке. SVN это инструмент для разработчика, в первую очередь.
Для секретарш и документооборота в целом главный плюс SVN — полная защита от повреждения информации, в том числе криптолокерами.
В случае с SVN — чтобы убить историю достаточно просто зашифровать сервер.
образцово качественная утилита командной строки
Да уж, "качественная".
Это не одна утилита, а несколько разрозненных команд.
В каждой свой подход к заданию параметров:
Вывести список веток: git branch -a
Вывести список тэгов: git tag
Вывести список стэшей: git stash list
Вывести список remote: git remote -v
Одна и та же команда может выполнять совершенно не связанные вещи:
Переключиться на другую ветку: git checkout
Создать ветку (и переключиться на неё): git checkout -b
Обновить содержимое файла: git checkout
В отличие от принятого в *nix подхода, длинные и короткие опции не эквивалентны:
git branch --help
выдаст полную информацию о команде, а git branch -h
— только краткую справку
Вот и появляются всякие Gitless да "Human Git Aliases".
Скажите, а откуда в документации берутся большие файлы? Это видеоинструкции или PDF-ки?
Except for the case of storing a lot of binary files, when Subversion repositories could be significantly smaller than Git ones (because Subversion’s xdelta delta compression algorithm works both for binary and text files)
После чего автор берет свн репозитарий исходных кодов без бинарей (фактов о наличии в нем бинарей в статье не приведено, да и количество файлов при размере 213 МБ намекает) и радостно рапортует, что текст git хранит лучше.
Пусть автор попробует создать репозиторий с 100мб бинарями. И сконвертит его в гит. Убедится что гит умрет, и включит LFS. После чего с удивлением узнает, что LFS ничего ни о каких дифах не знает и тупо хранит каждую измененную версию в отдельном файле. Итого по 100 и более мб на каждую ревизию. Поэтому git безусловно крут, но вот для смешанного хранилища бинарей и исходных кодов ничего лучше svn так и не придумали (maven, artifactory… это не vcs у них своя ниша)
Они сами выбрали wordpress, я лишь повторил тот же эксперимент но на ОДНОМ источнике, и сделал несколько дополнительных шагов.
Беда проверки с бинарными фалами — все они разные!
Я могу взять ISO образ с текстовыми файлами — такой формат данных отлично сжимается и я прогнозирую победу git-а.
С другой стороны, можно взять архивы и эту будет худший случай для гита.
Насколько я знаю у гита одна проблема с большими бинарными файлами по сравнению с svn — весь репозиторий будет у каждого клиента, а если там много несжимаемых бинарей — он будет большой. Фактически будет жраться место на компах и страдать время клонирования. LFS именно эту проблему и решает.
С другой стороны я провел кучу сравнений хранения бинарных файлов в git и svn для нашего проекта. Средний проект: пара десятков мелких файлов, десяток бинарных на 1-2 МБ, 1-2 крупных бинаря на 10-50 МБ. И в результате гит на наших файлах показывает приемлемый результат: 500 коммитов на проект, репозиторий весит в 2 раза меньше чем рабочая копия. Хранить на LFS полные копии несжатых файлов мне в этом случае кажется лишним.
Из-за специфики формата не думаю, что это будет интересно широкой публике.
du -sh .git
10G .git
10 гигабайт бинарей — изображения, звуки и видео. С ветками.
Отлично работает на машине с 2 гигабйтами оперативки.
Итого по 100 и более мб на каждую ревизию.
Неверно. Git хранит не полный слепок дерева файлов, а только изменённые. Поменяли 1 мегабайт, размер и увеличится на 1 мегабайт, а не на 100.
Прикол в том, что имя такого файла-объекта — его хеш. Поэтому гит в принципе не будет хранить две версии одинакового файла даже под разными именами. Просто у двух разных слепков дерева будут ссылки на тот же самый хеш.
В GIT есть такие сущности:
* коммит (автор, дата, коммит месседж и указатель на дерево)
* дерево файлов (собственно дерево каталогов с указателями на файлы-объекты)
* файлы-объекты
Каждый раз, когда вы делаете git add, создается новый файл-объект.
Каждый раз, когда вы делаете commit, создается новый коммит, и если требуется, создается новое дерево файлов для него (хранится отдельно)
Поменяли 1 мегабайт, размер и увеличится на 1 мегабайт, а не на 100.
Поменяли 1 мегабайт в десятиметровом файле — размер увеличится на 10 мегабайт
увеличится лишь на размер изменённых файлов + метаданные.
Я так и сказал потом. Да, git не разрабатывался для хранения бинарных файлов, и делает это не оптимальным способом.
Однако, по производительности этот способ выигрывает, т.к. не приходится при смене ревизии каждый раз накладывать все патчи, нужно лишь вытащить готовый кусок из блоба.
Имя файла в хранилище гита = хешу от содержимого файла. Т.е. измнение 1 байта в 100 мб файле приведет к изменению хеша файла и появлению нового имени = нового файла. Т.е. изменил 1 байт размер гит репозитария увеличится на 100 мб.
Появилось много фанатиков гита которые пытаются пихать его везде. При этом эффективно работать с бинарями гит не умеет и вообще его архитектура для этих целей не проектировалась. А главная фишка гита — веки и легкость слияний тем же дизайнерам вообще не нужна.
Кстати для любителей сравнивать новые версии гита с древними версиями свн. В какой то из новых версий добавили следующее. Специально чтоб не было проблем с глубиной накладывания патчей каждые N изменений делается полный снимок файла. Поэтому более N патчей не накладывается никогда. Не могу найти пруфлинк с точной цифрой.
Кстати у свн есть интересная возможность http://svnbook.red-bean.com/en/1.7/svn.webdav.autoversioning.html смонтировать его как обычную WebDAV папку. Никаких клиентов c которыми надо учится работать. Никакой командной строки и запоминания магических слов "svn co". И при этом есть история и можно откатить изменения.
Судя по тому, что никто не написал что‐то делающее то же самое для других VCS, это никому особо не нужно, или же те, кому нужно, хранят там те же бинарники (т.е. что‐то, к чему большинство DVCS не приспособлено). Других технических препятствий к тому, чтобы сделать то же на DVCS я не вижу, есть даже такая штука как https://github.com/mar10/wsgidav — автоматически изменения не фиксируются, но фиксировать их можно вручную, «перемещая» файлы (http://wsgidav.readthedocs.io/en/latest/addons-mercurial.html).
Есть куча специалистов которые работают с боьшими бинарями, которым совсем не помешает версионирование и возможность вернуть вчерашнюю версию но которые ни разу не программисты. Дизайнеры, маркетологи, продажники. И у них нет никакого желания разбираться как работает git. А WebDAV для пользователя подключается не сложнее сетевой samba шары. И да, DVCS им тоже не нужна. Поэтому в DVCS этого и нет.
Кстати для больших бинарей у svn есть еще одна замечательная фишечка. Выгрузить только нужную папку, а не весь репозитарий. При размере репозитария от 20Гб это очень удобно.
Да и вообще для больших бинарей git svn-у ни разу не конкурент. Тут с svn конкурируют maven, artifactory и samba шара (с версиям по папочкам) как совсем легкий и простой вариант.
Поправка. Насчет легкости слияний в git. Я вообще не представляю как слияния возможно использовать с бинарями.
Смотря какие бинари. Например, Word умеет сливать файлы от разных авторов, LabView тоже. Для некоторых типов файлов можно тоже сообразить что‐то ограниченно полезное: к примеру, zip архивы сливать как будто это каталоги с файлами, с изображениями: преобразовывать метаданные в форматированный YAML, сливать, преобразовывать обратно, сами изображения сливать только если изменения в разных ветках внесены в разные области изображения… Но если ПО, в котором вы работаете с бинарниками не предлагает своего варианта слияния, то, скорее всего, возможные методы слияния будут сильно зависеть от workflow (т.е. не универсальны).
Git хоть и не разрушает репозиторий, в аналогичной ситуации, но при выводе имён файлов выдаёт коды символов через слэш. С диффом и комментариями (в тексте программы) на русском языке та же проблема.
Git хоть и не разрушает репозиторий, в аналогичной ситуации, но при выводе имён файлов выдаёт коды символов через слэш. С диффом и комментариями (в тексте программы) на русском языке та же проблема.
Если git отображает имена файлов и содержимое с символами через бэкслеш (иногда в угловых скобках), то это означает, что ваш терминал плохо работает с используемой кодировкой. С большой вероятностью, с utf8. Проверяйте настройки терминала и локали.
Вы знаете, у меня даже emoji в описаниях коммитов нормально работают. Кажется, дело не в git-е.
Subversion vs. Git: Развенчивание мифов о развенчивании мифов