Pull to refresh

Comments 292

Сравнение не о чем. Скорость операций — это далеко не первый пункт. Это как, если бы к вам подошел отчисленный Вася и предложил сделать операцию в 3 раза быстрее и дешевле чем квалифицированный хирург.
Да он вроде тоже может, но результат будет отличаться.

Туда же и mercurial (hg), я его лет пять использовал (после svn), не хотел переходить на гит, т.к. там вроде бы все тоже самое. Пришлось перейти под «давлением общественности», и не зря, т.к. гит на прядок лучше. Теперь для меня норма — то, что не приятно было трогать в hg. Продуктивность выросла, и не важно кто там быстрее клоны делает.
Расскажите, что вам было «неприятно трогать в hg», и в чём именно «гит на порядок лучше [hg]»?
Например работа с бранчами и другие мелочи. Чем мерседес лучше жигуля? Вроде у обоих есть и руль и сиденье, тут надо пробовать чтобы почувствовать.
А можете побольше рассказать? Я 6 лет работаю с git-ом и все время комплексую, что hg наверное лучше и я что-то теряю.
Навскидку могу сказать про ветки в hg — commit содержит имя ветки, соответственно принадлежность commit'а к ветке однозначна. Ветка в git'е это блуждающий указатель на commit — после разветвления или мёржа о том в какой ветке были созданы «старые» commit'ы можно только догадываться. Tag'и в git'е — это только метки/указатели на дерево истории; в mercurial — установка tag'а это тоже часть истории. В целом, hg несколько более формализован а git несколько более гибок — соотвественно hg дает чуть больше шансов понять что, где и как изменялось, а git несколько меньше путается под ногами.

Спасибо за комментарий по существу вместо балабольства о жигулях vs мерседесах!


Можете привести пример того, когда важно знать, в какой ветке родился commit? С Git это и правда не определить. Так что, например, после cherry-pick так сразу и не скажешь, что откуда пришло (но мне и не приходилось задаваться вопросом).

Во многих командах принято в git начинать сообщение коммита с метки тиккета/таска, работа по тиккету/таску обычно ведётся в одной ветке, коммитов может быть много и каждый раз писать надо или как-то автоматизировать. В mercurial достаточно указать метку в названии ветки и все коммиты в ней будут её хранить, то есть по коммиту мы сможем всегда сказать в рамках какой задачи он был сделан.

В гите можно мерждить ветку с флагом --no-ff и тогда в network будет видно откуда коммиты пришли.

Будет видно какие коммиты мержелись, но не какие ветки, если указателей веток ушли с этих коммитов или вообще удалены
В коммите написано: Merge 'very_hot_featrue' into 'master'.
Это по умолчанию будет, но их можно изменять.
А что запрещает договориться чтобы не меняли или писали что-то отслеживаемое?
Кодинг конвенции же существуют.
Для гит требуется больше договоренностей, чтобы отследить в рамках какой задачи был сделан тот или иной коммит. Ну и собственно отслеживание сложнее.
Знаете, вы меня убедили.

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

Это только в мёрж коммите. В остальных коммитах будет всякая ерунда.

Да, конечно, но остальные коммиты будут в ветке. В network будут отдельно коммиты сделанные в мастер и отдельно коммиты сделанные в ветку + мердж коммит.
А для того что бы по номеру коммита из истории в мастере определить из какой ветки он в нее пришел достаточно посмотреть вверх по истории до ближайшего мержда. Ну и конечно ветку нужно называть по номеру тикета.


https://habrahabr.ru/post/106912/

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

Вы что, не читали статью по ссылке?


После удаления ветки удаляется только метка ветки, а коммиты никуда не деваются. Они все еще висят в истории как отдельная ветка (если конечно ветку смерджили куда-то с флагом --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 из коробки может добавлять номер тикета в коммит?
Именно номер тикета, а не название ветки?
И hg из коробки привязывает коммит к тикету?
Похожу вы просто не понимаете о чем говорите.


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

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

Есть такая штука, называется: Внутренний регламент разработки ПО.
Документ в котором описано что и как нужно писать, а что писать не надо, code style и т.д. В него также входит описание настройки окружения и работы с ним. Каждый разработчик обязан ознакомится с регламентом и подписать его. В документе можно описать установку хук для гита.


В другом комментарии вы упомянули контейнеры. На контейнерах можно собрать окружение для проекта и распространять между разработчиками именно его. Таким образом у всех разработчиков будет одинаковое и актуальное окружение. В те же контейнеры можно добавить хуки для гита.


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


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

Какое счастье, что в hg хуки версионируются вместе со всем остальным кодом.

UFO just landed and posted this here

В том-то и дело, что нет.

UFO just landed and posted this here

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

UFO just landed and posted this here
Это как? Рабочую копию в контейнере держать? Хостить в нём репозиторий?

Я с контейнерами не работал. Если верить статьям по работе, то это можно сделать. Я же имел дело с использованием такого подхода в vagrant.

UFO just landed and posted this here
Хорошо, пусть будет vagrant. У вас в виртуалке рабочая копия, снимок репозитория или хостинг?

У меня в vagrant все. База, исходники, репозиторий и тд. Это не точная копия прода, так-как отличаются некоторые параметры окружения, но в остальном копия, максимально приближена к прод.

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

Если говорить вашим языком:
Вы сами заявляете, что у вас есть кожух на циркулярке, но ваши люди продолжают резать руки. Значиь либо кожух плохой и не защищает, либо людей нужно учить им пользоваться.
У меня нет кожуха на циркулярке. Я и мои коллеги не режем руки. Может не в инструменте дело?


PS: не смотря на мои критические заявления, я не хочу сказать что git лучше hg. Вам он больше нравится и лучше подходит. Окей. Рад за вас. Я не хочу оспаривать ваш выбор. Я лишь хочу донести мысль, что hg не серебрянная пуля. Он не решает ваши проблемы в полной мере, как и не будет их решать git.

detached commits в GIT пропадают через некоторое время, поскольку чистятся сборщиком мусора. Поэтому удаление ветки чревато тем, что через недели 3-4 уже даже ref-log может не спасти.

Забыл сказать. Проблемы есть только с тестированием, когда нужно отдать задачу на тестирование тестировщикам.


По правильному нужно тестировать задачу сначала отдельно (как отдельную ветку), а потом сливать в 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 действительно только мешает, а при разработки крупных сайт-проектов сильно спасает.

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


Идеальный воркфлоу выглядит следующим образом:


  1. Разработка идёт в фиче-ветке
  2. Фичеветка всегда доступна на сервере по урлу вида feature-123.api-345.example.org
  3. Там же она тестируется и задача переводится в статус "завершена".
  4. Когда нужно выпустить релиз, создаётся фичеветка "release-678", куда автоматически сливаются все завершённые задачи.
  5. Как и любая фича, релиз тестируется, потом деплоится, тестируется уже на проде и только потом вливается в мастер.
  6. Фича конфликтует с другими, то она возвращается в разработку и автоматически удаляется из релиза путём его пересоздания.
  7. Если автоматическое слияние не проходит, то ставится статус "требуется ручное вливание в релиз".
  8. Хотфиксы вносятся либо в фичеветку и они автоматом подливаются в релиз. Либо в сам релиз, если это фикс интеграции. Никаких ребейсов и прочих мёржей релиза в фичеветку.

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

Ну это уже савсем идеальный мир. Я с таким не сталкивался и необходимости в такой идеалезированности не было.
Но я учту вашу мысль на будущее

Перечитал еще раз ваш комментарий


решение о том попадёт ли фича в релиз может быть принято только после полного её тестирования и в том числе тестирования совместимости её с другими фичами релиза

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


Тестирование на совместимость в идеальном мире должно происходить многосторонне. В вашем примере получается, что группа разработчикав работавшая над фичей А должна проверить все ли у них работает после объединения с фичей Б, а разработчики фичи Б должны проверить весь свой функционал после мерджа с фичей А. Тестирование должно повторится после добавления фичи С и еще раз после добавления фичи Д и т.д.


Да, мы можем тестировать ветку на совместимость с другими ветками которые должны попасть в релиз. Но пока релиз не создан это просто висячие в воздухе ветки. Их список знает только тимлид и нет гарантии что пока вы тестируете ветки на совместимость не изменится список веток и сами ветки. На мой взгляд это перебор. Тестирование ради тестирования. Если фич всего 2-3, то еще можно жить, а если 30-40, то уже проблема тестировать все это у себя.


Потому я и говорю что нужна ветка с релизом чтоб не делать одну и туже работу многократно:


  1. Мерджмастер создает ветку релиза (это может быть develop, release-678, issue-123 и тд. Название в данном случае не столь важно).
  2. Мерджит туда все фичи и баги которые должны попасть в следующий релиз.
  3. Если есть конфликты, то релиз отменяется и тикеты возвращаются разработчикам для доработки. Возвращаемся к п. 1
  4. Если все смерджилось нормально, то ветка отправляется на тестирование на совместимость.
  5. Каждая команда проверяет работу того куска за который отвечает она.
  6. В случае проблем с совместимостью релиз отменяется и задачи возвращаются на доработку. Возвращаемся к п. 1
  7. После успешного завершения тестирования релиз выкатывается.

Идея с feature-123.api-345.example.org моя голубая мечта и я пытался такое внедрить, но у меня еще не было ни одного проекта и компании которые могли себе такое позволить, а я работал над очень крупными hl проектами с милионами пользователей. Проблема же не только в доменах и автоматическом развертывании фич. Проблема еще в том что фичи зачастую завязаны на базе и для каждой фичи нужна своя копия базы, может и урезанная, но своя. Тоже может касаться NoSQL и ElasticSearch. Фактически, окружение для фичи должно быть максиму приближено к прод, но должно быть изолировано от других фич. А это уже совсем не детские ресурсы. Может в mail.ru или яндекс такое есть)))


PS: мне немножко странно почему вы релиз тестируете на проде и сливаете его в местер только после завершения тестирования. Мастер должен быть всегда эквевалентен проду. А для фиксации статуса используются теги, они же релизы в большинстве случаев. Если на проде баг то мы откатываем как прод, так и мастер. Не должно быть разделения. А то у вас получается мастер вообще как-то отдельно от всего, в воздухе висит. Ну это уже ваше дело. Я не критикую.

Каждая команда проверяет работу того куска за который отвечает она.

После этой проверки обязательный этап тестирования в целом как минимум критической функциональности тестировщиками, которые отвечают за проект, а не за фичи и куски…

А это уже совсем не детские ресурсы.

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

Вы, фактически, описали то же, что и я, перечитайте мои 8 пунктов. :-)


Мастер физически не может быть всегда эквивалентен проду в любой момент времени. Но он никогда не должен обгонять прод иначе отмена релиза может привести к куче проблем с реверсмёржем и последующим реверсреверсмёржем.

Вы, фактически, описали то же, что и я, перечитайте мои 8 пунктов. :-)

Да, фактически я скопиравал, переупорядочил и переформулировал ваш список, так же как и вы мой до этого)))

В hg есть классические тяжелые ветки и легкие скользящие указатели bookmarks. Корректнее сравнивать с git-ом именно последние.
Теги в гите могут быть аннотированными, и они таки часть истории.

Немного не так.
У мерка есть аналог гитовых веток — букмарки.
У гита аналогов мерковых веток нет.

Насколько я вижу, архитектура mercurial позволяет запилить туда в качестве расширений git’овские ветки (закладки начинали как расширение), фазы (аналогично) и даже таких монстров как evolve — расширение, позволяющее “переписывание” истории, при этом в значительной степени сохраняя её неизменность — должно позволять делать rebase без push -f, насколько я понимаю. Вопрос: почему ничего подобного не делали в git? Не то что evolve, git’оводы на вопрос «как ко всем изменениям автоматически прикреплять номер тикета» нормально ответить не могут — архитектура не позволяет.


Собственно, по моему мнению для закапывания git достаточно посмотреть на его потенциал развития — сразу после рассматривания его CLI. К сожалению, github вместе с большинством разработчиков сами знаете на чём.

github вместе с большинством разработчиков сами знаете на чём.


Простите за невежество, а на чём же, собственно? С пруф-линком если возможно, пожалуйста.
В hg ветки — это настоящие ветки и остаются такими даже после закрытия и слияния. Это самое главное, пожалуй.
Ну и hg более «человечен» что ли. Я работал с тем и другим и в hg всё понятно интуитивно и есть прекрасный удобный клиент (TortoiseHg). В git же надо либо вникать, либо курить мануалы. И GUI хуже.

А чем не устроил TortoiseGit? TortoiseSvn в туже степь. Можно еще gui из PhpStorm, но я лично gui не использую. Мне консоль удобнее.

Может, сейчас что-нибудь улучшилось, но раньше это была очень тонкая надстройка над командной строкой. Например, начинаешь что-нибудь делать, а оно визуально просто висит намертво, потому что угадай, там вообще хоть что-то происходит или зависло уже. Причём шаг влево-вправо, уже расстрел, потому что сами инструменты тоже откомпилированы не совсем родным для Windows способом. Скажем, имя папки ему не нравится или имя файла. А для аутентификации мне приходилось ещё pageant осваивать — не rocket science, конечно, но с чего бы такие сложности.
UFO just landed and posted this here

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

Присоединяюсь к вопросу, т.к. испытываю абсолютно такой же дискомфорт при использовании git после hg.

Особенно учитывая, что у гита бранчей фактически нет, а есть лишь "автоперемещаемые теги".

Основные и чрезвычайно ценные вкусности Git — это interactive rebase, index и stash.

Rebase позволяет формировать цепочки изменений в том виде, в котором они должны быть представлены независимо от внутренних процессов разработчика; он может коммитить каждую секунду, может для себя делать что-то в таком стиле, но на публичную фиксацию и/или командное взаимодействие подаётся уже продукт, а не сырьё. Качественного аналога в Hg нет.

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

Index (с add -i, add -e) или помогает stashʼу, или позволяет отправлять только часть изменений; например, в моих задачах типично, что я навешиваю в локальных функциональных и интеграционных тестах расширенную отладку, которая не должна попадать аплинку; также могут быть адаптации под локальную платформу, и т.п. (Замечу, что Tortoise клиенты дают такое для всех поддерживаемых SCM; но «из коробки» в Hg и SVN этого нет.)

Теперь про «ветки» в Hg — тут есть ряд злобных засад. В Hg понятие ветки это смешение нескольких разнородных сущностей в одну не сильно приятную (именно из-за смешения) кашу:
  1. «Голова» процесса развития, которых может быть несколько в пределах одной рабочей копии или «ветки» в другом понимании. При операциях push, pull передаются все эти головы. В некоторых местах это называется напрямую словом head.
  2. Некий установленный локальным режимом тег под названием «branch», который приклеивается к каждому новому changesetʼу, и больше ничего не делает. Именно его чаще всего называют «веткой».
  3. Полный пучок п.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 тут, как правило, была иной — им нравилась хотя бы частичная эмуляция стиля линейной последовательной истории, начиная с номеров коммитов для локального репо. Синтаксис команд звучал как аргумент, но не для лёгкости перехода. Я не психоаналитик, чтобы раскапывать тут реальные связи, поэтому ограничился наблюдаемым.
UFO just landed and posted this here
> Не совсем понятно, чем именно вас не устраивает hg histedit

До последних версий (3.8? я сбился с историей нумерации) он был непригоден. Сейчас надо перещупать заново.

> частичный коммит реализован искаробочным плагином record

1) deprecated 2) принципиальная разница в отсутствии явного индекса, я не могу перед коммитом посмотреть, что же получилось. (В описании вообще подтасовка — «interactively select changes to commit» не подразумевает самого коммита, но он происходит.) Да, можно потом корректировать историю, но это много лишних движений. Ещё и легко ошибиться (strip без --keep потеряет изменения).

> hg shelve (правильно, это тоже искаропки)

И снова без возможности учесть индекс. Как-то его, я смотрю, в Hg совсем не оценили, и всё сравнение в итоге утыкается в него.

> Mercurial же просто записывает всё за пользователем.

Я бы оценил эту фичу в варианте 1) автоматически не включена, 2) препятствует внешнему обмену, пока не указана конкретная голова или не осталась одна. Но в текущем варианте это источник тяжёлых диверсий.
UFO just landed and posted this here
> Так а чем именно? После 3.8 его практически не правили.

Я про «до».

> Ну это, в гите наличие индекса существенно усложняет чуть менее, чем весь интерфейс. А пользы — чуть.

Ну вот тут и видна фатальная разница. Для меня это не «чуть», это критично. И соответственно ценность всех остальных механизмов, если они это не поддерживают, снижается в разы.

> Таким образом, без дополнительных телодвижений новые головы просто-напросто не выпинываются.

OK, принято. Я не помню, откуда взял про передачу всех голов — скорее всего, это утверждал один из апологетов Hg, а я не проверил. Осталось не разрешать их локально по умолчанию :)
Осталось не разрешать их локально по умолчанию

Так они локально появляются после pull естественным образом.
Наверно, при желании можно и руками такое сотворить… но это потребует сознательных усилий и мотивации.

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», но за одним файлом уже не следит.
UFO just landed and posted this here
> Да и нет,

Я не говорил о публично выставленной части (тут скорее надо сослаться на концепцию Phases), хотя и тут есть разные мнения — иначе бы в `git help rebase` не было секции «Recovering from upstream rebase». Но именно свою локальную работу привести в порядок, по-моему, обязательно.

> вероятно, речь об угадывании rename/copy вместо записывания

Тут я тоже удивляюсь, что мешает в Git добавить запись этих данных, если автор явно хочет. Вероятно, они не считают частный случай настолько существенным (над частичным разбросом содержимого в разные файлы), а детект по содержимому сейчас работает достаточно неплохо (и для log, и для merge).
UFO just landed and posted this here

За git push -f любому дятлу следует отрывать клюв.

UFO just landed and posted this here

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

UFO just landed and posted this here
можно, конечно, и git push someremote +somebranch, но это тот же самый force push

Одной конкретной явно указанной ветки, а не просто текущей ветки. Гораздо нагляднее и заставляет задуматься перед тем как нажать enter.

UFO just landed and posted this here
Ссылки на статьи после этого — забавны, но не имеют отношения к текущему обсуждению, и, по-моему, вообще ни о чём

Фальсификация истории системой контроля версий с внесением ошибок туда, где их не было — это "вообще ни о чем"? Ну-ну.


Но хуже то, что с 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, и я знаю, что он не поможет, если нужных изменений на моей машине никогда не было).

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

UFO just landed and posted this here

Я думал, подождут до официального выпуска evolve и потом ещё будут тормозить. Большие файлы вон до сих пор не поддерживаются (вроде хотят, как минимум, дождаться варианта от facebook вместо стандартного).

UFO just landed and posted this here

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

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

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

> Отсоединеннный коммит — это вообще уникальная гитофича, похожая до степени смешения на багу.

Оно существует только при особых режимах работы. Меня вот множественные головы напрягают больше :)

> Необходимость помнить, запушен ли коммит, после мерка вымораживает.

Этого не понял совсем. Сравнение с Hg или CVS/SVN? В любой распределённой системе локальный коммит может быть не запушен.

> Любовь к rebase есть любовь к фальсификации истории в угоду чисто эстетического профита от няшной линеечки коммитов.

«Эстетический профит» превращается в реальную потребность понимать, что происходило, при разборе через 1-2-5-10 лет, когда никто не помнит подробностей происходящего. И главное не линейка, а чёткость и законченность каждого отдельного действия, а также разделение действий по характеру (как минимум, ни в коем случае не смешивать форматирование, рефакторинг и изменение функциональности). Линейчатость удобна, но не критична.

> но посмотрев и сравив, выбрали и мерк и не пожалели ни разу.

Ну так не CVS же выбрали (имел я дело с одной конторой в 2015-м, принципиально сидящей на CVS — это был ужас). Но стоит таки оценить, как это повлияло на методы работы с кодом и с задачами.
В гите можно удалить ветку, при этом коммиты в ней (если они не были никуда вмержены), убудут висеть с безымянной головой, и в какой-то момент могут быть почищены GC.

Отсоединенный коммит — это тот, у которого есть предки (понятно почему), но нет потомков, и он не существует ни в какой ветке. Даже найти такой коммит бывает непросто. И да, так как он не в ветке — тоже будет когда-нибудь подчищен GC.

rebase позволяет полностью выстрелить себе в ногу, так как как раз разобрсять что происходило в последствии не будет возможным. Будешь видить красивые эстетические ветки, а как и из чего они получились — нет, и в истории CI будешь видеть одно, а потом бац и совсем другое.
То есть rebase с одной стороны позволяет получить красивый git log, с историей коммитов в виде чистовика, но вот цепочка реальных событий в жизни будет несовпадать. Поэтому проекты, где не используют rebase — организованы лучше.

Впервые слышу про «отсоединённый коммит». Обычно говорят про отсоединённую голову (detached HEAD) или «осиротевшие/удалённые изменения» (orphan[ed]/deleted), хотя говорить «осиротевшие» здесь несколько неверно. Причём в первом случае отсоединённым вы можете оказаться на абсолютно любом изменении, а во втором речь идёт про изменения, недостижимые ни из какой ссылки (не ветке, тёги тоже держат), безотносительно наличия/отсутствия потомков и предков.


И вы вполне можете удалить все ссылки и увидеть «удалённое изменение», не имеющее предков. Или сделать самостоятельно сделать git checkout --orphan (именно поэтому неверно: осиротевшие не имеют предков, а не недостижимы), чтобы затем создать изменение без предков и потом успешно получить удалённое изменение, не имеющее предков.

Все таки, если у вас корпоративный медленный svn сервер, скорость работы с ним падает еще сильнее, если какая-то операция с svn делается 10-30 секунд, то за это время можно случайно на что-то отвлечься и потерять фокус над задачей и эти 10-30 секунд превращаются в 5 минут.

Привязка к корп серверу и интернету вообще большое зло. Автономность с Hg/Git/… даёт большой выйгрыш при "переключении контекста".

Пришлось перейти под «давлением общественности», и не зря, т.к. гит на прядок лучше.

Что можно сделать хуже, чем в гите?
(уже ощущаю затылком коллективный пистолет)

Вы не работали с мерком.

Какие вообще сегодня могут быть преимущества в использовании svn по сравнению с остальными vcs? Время клонирования (при котором гит еще и выкачивает 100% репозитория, в отличии от)? Ну это смешно.
Одну назову — возможность дать доступ только к определённым подпапкам в репозитории. Гит такого не может архитектурно — или всё, или ничего. Редкий юз-кейс, но возможный.

Второе — гит всё-таки надо осваивать. Не бог весть какая rocket science, но если системой контроля версий пользуются не айтишники и возможностей svn им хватает — зачем заставлять людей тратить время и силы на непрофильные вещи?
Одну назову — возможность дать доступ только к определённым подпапкам в репозитории. Гит такого не может архитектурно — или всё, или ничего. Редкий юз-кейс, но возможный.

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

Второе — гит всё-таки надо осваивать. Не бог весть какая rocket science, но если системой контроля версий пользуются не айтишники и возможностей svn им хватает — зачем заставлять людей тратить время и силы на непрофильные вещи?

Ну 95% использования git — это 5 команд. На моей практике осваивали даже люди около пенсионного возраста.
Тем не менее, заставлять, наверное, смысла нет. Но вот начинать новые проекты на svn — кощунственно.
subtree, как я понимаю, сначала должен вытащить весь репозиторий, и только потом вытащить из этого папку. subtree нельзя сделать без fetch.
Человек спрашивал — как сделать доступ к отдельной папке. Вот я предложил: вытащить subtree нужную папку и сделать из нее отдельный репозиторий. Дальше уже можно дать юзеру к ней доступ, пусть пишет код.

Ваш кейс, ясное дело, не будет работать, потому что subtree split пробегается по всем коммитам и ищет такие, которые затрагивают нужную папку. Тут вопрос, зачем это вам.
> Ну 95% использования git — это 5 команд.

Это миф. Если использовать только эти 5 команд — гите нет смысла.
Ну если вы не можете организовывать и поддерживать порядок в своем репозитории, то ясное дело.
commit, pull, push, merge, branch

git flow можем посчитать за одну команду.

Ну ок, еще сюда можно вписать add, rebase, diff, log, хотя этого можно и не знать, используя какое-либо gui.
> хотя этого можно и не знать, используя какое-либо gui.

С Gui я могу и первые 5 не знать.Но надо изучать gui
Первые 5 команд — это фундамент всего git. В конце-концов, даже при общении с коллегами приходится говорить «ты запушил изменения?», «ща сделаю коммит и...», «смерж ветки» и прочее. Можно и в gui все делать, ок, ну надо понимать, что происходит. И, как я уже говорил, с этой задачей и бабушки справляются.
> И, как я уже говорил, с этой задачей и бабушки справляются.

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

«Потому что проект может состоять из десятков и сотней модулей» тоже на мой вопрос не отвечает никак.

Про 95% — чистая правда, но не все это понимают. Недавно пересаживал одну команду с архаики SVN на Git. БОльшая часть команды осваивала постепенно с базовых 5 команд к чему-то поумнее, типа cherry-pick, rebase [-i], и так далее. Но были и люди, которые привыкли учить что-либо "наскоком и целиком", как по учебнику. Вот они страдали больше, потому что learning curve выглядел для них хуже...

Берите SourceTree. Настроить репу нужно руками будет, но коммиты и ветки очень удобно делать.

Нет под никсами.
Одно время был жутко тормозной, как сейчас — хз.

Лично я юзаю консоль и SmartGit. Еще хотел поюзать gitkraken, но что-то он у меня с ходу не взлетел, а дальше я забил. Но уж много времени прошло, можно его и еще раз потыкать.
UFO just landed and posted this here
Ну 95% использования git — это 5 команд

«Привет, добро пожаловать в команду! Мы используем git-flow, вот ссылка на <те самые 5 команд, только во flow>. Все просто, вот эта ветка — девел, вот эта — мастер, вот тебе тикет на фичу, давай запили!»

git flow feature start, денек покоммитались, git flow feature finish, все красиво как на гламурной фотке в журнале… «ого, уже готово? отлично! слушай, это короче не могет ждать до следующего релиза, секурити риски, все такое, зафигачь это хотфиксом в мастер?»

Приплыли.

P.S. разумеется это решается, о да. Но нет, это вовсе не 5 команд.

Ну если у вас 95% использования это хотфиксы в мастер, тогда да.

В моем понимании, команда merge входит в ТОП-5 команд, которые нужно знать :)
Мерж тут разумеется не поможет, так как захочет невменяемого ребейза на пустом месте.
> subtree позволяет вытащить любую папку, из которой потом можно сделать отдельный репозиторий

subtree по гибкости раздачи прав и сложности использования сильно отстаёт от нормальных прав на файловой системе: во-первых, только папки, отдельные файлы нельзя; во-вторых, если в проекте появился новый файл с ограниченным правами доступа, достаточно сделать chown/setfacl, а не заморачиваться с заведением целого нового репозитория.

> Начинать новые проекты на svn — кощунственно

Кощунственно не использовать самый подходящий для конкретной задачи инструмент. Гит безусловно хорош, я сейчас только им и пользуюсь. Но стоит понимать, что в некоторых юз-кейсах он проигрывает svn. Кстати, посмотрел на упомянутый в статье svnvsgit.com и нашёл ещё один: работа с файлами по модели " Lock-Modify-Unlock".
subtree по гибкости раздачи прав и сложности использования сильно отстаёт от нормальных прав на файловой системе: во-первых, только папки, отдельные файлы нельзя; во-вторых, если в проекте появился новый файл с ограниченным правами доступа, достаточно сделать chown/setfacl, а не заморачиваться с заведением целого нового репозитория.

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

о стоит понимать, что в некоторых юз-кейсах он проигрывает svn.

Этот тред начался с того, что я спросил, цитирую: «Какие вообще сегодня могут быть преимущества в использовании svn по сравнению с остальными vcs?». А вы мне говорите — в некоторых юз-кейсах git проигрывает svn. Я снова возвращаю к своему вопросу — в каких? :)

работа с файлами по модели " Lock-Modify-Unlock"

Вы серьезно что ли или троллите? Если серьезно, то у меня грустные новости — вы вообще не понимаете, как работает git. Тогда я не удивлен вопросам с непониманием перехода с svn на git.
А чем вас потребность в " Lock-Modify-Unlock" так удивляет? Очень часто в репозитории приходится хранить не только текстовые файлы. Вот вам реальный пример из жизни: исходники флэша (.fla), текстуры (psd, tga), файлы 3ds max'а и еще куча всего остального. Поставил лок на файл, и спокойно его редактируешь и не волнуешься, что придется делать заново потому что кто-то успел закоммитить раньше.
Если одну и ту же текстуру или модель редактируют 2 и более человека одновременно, то это неправильная организация рабочего процесса или неправильное разделение на файлы.

Так расскажите же как правильно.

1. Действительно ли нужно, чтобы несколько человек редактировали одну текстуру или модель одновременно? Чем это обусловлено?
2. Можно ли разбить текстуру или модель на логические куски и в случае модели иметь один файл, который бы через ссылки собирал все воедино?
  1. Нужно-то как раз, чтобы несколько человек не редактировали одну текстуру одновременно, для чего и используются блокировки.
  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-е такое настроить сложно, если вообще возможно — у него же все репозитории равноправны и нет какого-то главного, а стало быть они все должны обладать одинаковыми свойствами.
GIT-е такое настроить сложно, если вообще возможно — у него же все репозитории равноправны и нет какого-то главного, а стало быть они все должны обладать одинаковыми свойствами.

Это не так. И исходно было не так для того же linux'а. Существование blessed репозиториев вполне себе объективная реальность.


Вообще авторизация при работе с git'овыми репозиториями штука внешняя по отношению к git'у. Тот же gitolite (а ранее gitosis) позволяют относительно гибко работать с правами: защитить отдельные ветки/теги (начиная от push, заканчивая force push/create/delete операциями) в разрезе по пользователям/группам. Тот же gerrit (который уже управление code review) ещё более гибок и тяжел для нормального пользователя. Как промежуточный вариант — github/gitlab, которые позволяют управлять мержем pull request'ов по выбору владельца репозитория (или лиц к нему приравненных в рамках этих операций).

Ну вот юзкесы — хранение бинарных файлов. Например, мы храним картинки. Или тестовые данные. Тут сразу несколько недостатков git:


  • нельзя залочить файл (а бинарники смерджить нельзя)
    Два дизайнера пошли поменять одну картинку, и теперь работа одного из них пропадет.
  • необходимо вытягивать весь репозиторий, даже если нужно поменять один файл
    Например, для смоук-тестов мы хотим брать только 5% тестовых данных. Или заранее подобранные для нужных тестов, тесты храним по папкам с id теста. Или дизайнеру надо поменять только иконочки, но ему придется вытянуть и фотографии.
  • невозможность просто раздачи прав на папка
    — В разных папках разные виды картинок. Там, где 18+, доступ только для женатых.
    — Там, где в тестовых файлах есть персональные данные — доступ только для подписавших бумажку.
Когда начало нового проекта сводится к созданию на рабочем сервере коммита с папками projectname/{brancher,tags,trunk}, добавлению проекта в редмайн и копированию настроек хранилища из соседнего проекта — почему бы нет? Работает же.

Опять же, монотонно возрастающие целые номера коммитов в SVN как-то приятнее выглядят, чем гитовские хэш-суммы.
Честно говоря, я по первому абзацу мысль не уловил. Если я правильно понял, то гитом еще проще: git init и вперед, репа готова.

Ну про возрастающие коммиты — это, конечно, аргумент :)
Почему вы думаете, что иметь один репозиторий, давая доступ к его части лучше, чем иметь 2 репозитория?
В некоторых случаях это лучше. Активно работать одновременно с двумя репозиториями в одном проекте в git-е не очень-то удобно, если честно.
Одном проекте? А почему вы хотите кому-то показать только часть проекта?
Ну могут быть причины.
Например, у меня может быть часть проекта на аутсорсе (UI например), а IP в остальной части проекта. И я не хочу, чтобы вьетнамский фронтендер-фрилансер имел доступ к коду, реализующему мое конкурентное преимущество.
Или я хочу дать дизайнерам возможность force push-ить их кратинки, но чтобы они случайно не убили важный код.
Неужели вы думаете, что таких причин быть не может?
> Неужели вы думаете, что таких причин быть не может?

Что вы, я уверен, что у людей есть причины на любые глупости.
Но недостатком Гита будет не тогда, когда «а вы на шкаф залезьте», а когда идеология(и, в меньшей степени, реализация) не позволят решить бизнес-задачу.

Мне, например, кажется логичным или использовать репозиторий фрилансера как Submodules, или переносить в проект работу фронтэндера в рамках «приёмки» своими силами. А не давать физически публичный доступ к IP — парольная защита никогда не была идеальной, тем более на неё нельзя полагаться в каком-нибудь SVN, где это далеко не core-функционал.
А как вы отличаете одно от другого? :-) Submodules работает без подводных камней? Мы как-то в своей время погуглили и забоялись и использовать.
Примерно так:
Если у вас проблема с правами на подпроект фрилансера, то это проблема у вас.
Если у вас проблема с Submodules, то проблема у гита

> Submodules работает без подводных камней?

Да всё в этой жизни работает не без подводных камней :(
Ну идеология GIT — один репозитарий — один набор прав. А это входит в противоречие не только с бизнес-логикой, но и с чисто-программистскими реалиями. Потому что на каждую библиотеку — свой набор мейтейнеров.

Да всё в этой жизни работает не без подводных камней :(

А вот это было бы интересно почитать.
> Потому что на каждую библиотеку — свой набор мейтейнеров.

и свой репозиторий. И Submodules.
Свой репозитарий — само собой. А вот сабмодули…

  • я правильно понимаю, что они сидят как подкаталоги? И система сборки должна быть настроена именно на такое расположение путей?
  • я правильно понимаю, что при N проектах получится N копий каждого сабмодуля на диске?
  • Какие ещё есть подводные камни?
Вряд ли я вам поведаю подробнее https://git-scm.com/book/en/v2/Git-Tools-Submodules

> при N проектах получится N копий каждого сабмодуля на диске?

Можно попробовать сделать directory junctoin, или на подмодуль, или на .git подмодуля. Но это вручную
Ну вряд ли создатели git будут писать о подводных камнях. А потерпит ли subversion симлинки — это вопрос. Ведь тогда один каталог будет принадлежать сразу нескольким репозитариям.

«Using submodules isn’t without hiccups, however.»

subversion вряд ли, а гит более дубовый. Впрочем, надо проверять.
я имел ввиду submodules, конечно. :-) Прошу прощения, устал.
Ну зачем вы говорите неправду? Использовать активно разрабатывающуюся библиотеку как submodule очень неудобно. Просто катастрофически. По сути, вам надо на каждый коммит в библиотеку делать коммиты во все активные бранчи основного репозитория. Автоматизация тут слабо помогает, потому что проблема не в том, чтобы коммиты делать, а в том, что ваш код начинает ломаться постоянно. Решение, конечно, не в svn, но зачем же давать вредные советы?
1) Так у них и так ломается, и так ломается. Как вы то предлагаете?
2) Это из серии «назвался груздем — полезай в кузовок». Если нужна отдельная, но активно разрабатывается библиотека, — надо под это workflow подгонять, что бы не комитить каждый раз все бранчи.

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


Работал тестировщиком на проекте на C++ с кучей зависимостей в субмодулях. Всегда было так, что обновление библиотеки — это интеграция, под которую выделяется время на разработку и тестирование.

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

Если amend — это опция commit, тогда я не понимаю, при чем тут она, можете объяснить поподробнее?

Ну например у нас часто встречается ситуация, когда сабмодуль обновляется несколько раз, а в надмодуле приходится делать уродские коммиты типа submodule++, следующие один за другим. Если использовать amend то по крайней мере коммит с обновлением будет один, а то и вообще можно схлопнуть с предыдущим.

submodules УЖАСНО работает в гите. Вам это непонятно, потому что вы не использовали их в более-менее приличном количестве.
Не сколько показать, сколько дать разные права доступа.

Есть N проектов на K конфигураций железа. Соответственно есть N прикладных частей, есть общая прикладная библиотека, есть K аппаратных частей и общая аппаратная библиотека. И все это имеет разные права доступа для разных программистов.

А несколько репозитариев — и впрямь морока. И более менее регулярные проблемы от того, что при рефакторинге надо обновить все затронутые им репозитарии. А если забыл git pull на одном из 10 репозитрариев сделать- «ты фигню сделал, у меня не собирается».
Я правильно понимаю, что у вас один файл в нескольких репозитариях?
конечно, неправильно.
То есть у вас N*K частей, к каждой (зачем-то) свои права, но вы рефакторите вы все кусочки одновременно и регулярно?

Я бы даже на SVN не стал при такой связности так с правами морочиться…
Ну не все… Но если библиотека меняет API, то идут синхронные изменения во всех частях, где этот API вызывался.

А частей (репозитариев) у нас примерно N+K+M, где M — число библиотек.

У каждой части — есть ответственный, он и определяет у кого какие права.

А ваше решение с правами? Разрешить всем всё?
Ну может и всем всё, или 2-3 группы (железо, прикладники). Думаете все побегут в чужие части комитить в рабочее время? Или важно, что бы программисты одной аппаратной части не подглядывали код другой?

> Но если библиотека меняет API, то идут синхронные изменения во всех частях, где этот API вызывался.

Если у вас изменения в N модулях происходят синхронно, я не уверен, что «ответственный» — ответственный. Он может наложить вето на ваши правки? Он вообще в курсе, что что-то поменялось?

Вы, перед рефакторингом, ходите и получаете права на 10 частей у каждого ответственного? И остальным, скорее всего, не надо. Остальные сделают фигню — получат то же «ты фигню сделал, у меня не собирается».

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

С одной стороны, 99.9% времени мы живем дружно. С другой стороны — мы живем дружно именно потому, что у каждого репозитария есть мейнтейнер, который отвечает за этот код.

Если у вас изменения в N модулях происходят синхронно, я не уверен, что «ответственный» — ответственный.

Почему? Если я отвечаю за библиотеку — я могу понять, что стоит сменить API. Сменить его, и исправить все места, где этот API вызывается. Если API новый и экспериментальный, такое бывает довольно часто.

пусть сами обновляют после обновления библиотеки, асинхронно

Гм, вы путаете обновления кода репозитария с получением последней версии репозитария.

Видимо нас спасет git submodule foreach 'git pull". Это если можно из нормальных репозитариев сделать такой супермодуль с пустым содержимым.
> Если API новый и экспериментальный, такое бывает довольно часто.

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

> Гм, вы путаете обновления кода репозитария с получением последней версии репозитария.

с чего бы?
У ответственного — компилится. у остальных — частая проблема с тем, что забыли обновить (git pull) все репозитарии. А с чего вы путаете — вам виднее.

Ситуация простая — я обновил свою библиотеку и сменил в ней API. Соответственно сменил в трех репозиатриях, где этот API вызывался. Запушил все в git. А коллега сделал pull лишь тем репозитариям, с которыми он постоянно работает. Но в одном из них было использовано новое API… И на такое налетаем раз в неделю…

Вроде бы можно через хуки автообновление после git pull сделать.

Отсюда:


Just add files named post-checkout and post-merge to your .git/hooks directory of the relevant repositories, and put the following into each of them:
#!/bin/sh
git submodule update --init --recursive

И еще вот тут более подробно.
Сам не пробовал, но должно работать.

Это только для сабмодулей. А для них — проще через алиасы.

$ git config alias.spull '!'"git pull && git submodule foreach 'git pull'"


А у нас пока сабмодулей нет и встает вопрос, а не стоит ли их ввести. Проблема в том, что или делать изменении структуры десятков проектов или делать симлинки, работающие и на windows и на linux. Скорее второе.
Сабмодули хороши тогда, когда нужно фиксировать в репозитории проекта версии других репозиториев, например для систем CI/CD. Линки этой задачи не решают, часто приводят к ситуации «у меня всё работает — проблема на вашей стороне», потому что разработчик использовал, например, последний коммит из мастера, который на прод ещё не выложен, или, наоборот, забыл обновиться.
Торможу, почему линки этой проблемы не решают?
В сабмодуле можно указать фиксированный коммит, который будет взят с репозитория и изменение этого параметра является частью истории репозитория, так как файл конфигурации тоже заливается в репозиторий.
Таким образом, мы получаем контроль за зависимостями из коробки.

В случае с симлинками нужно написать скрипт, который выкачает нужную версию и его нужно так же держать в репозитории. Т.е. мы имеем тот же функционал, что из коробки, но своими руками, только зачем?
т.е. если API не менялся, то разработчик может и не узнать, что он на неактуальной версии?
А зачем? Ну написал коллега работу с USB, пока я не решу USB задействовать — мне это не важно. Аналогично, коллеге все равно, если изменил обработку ГЛОНАСС.

В этом и кайф от деления на репозитарии.

P.S. Для испытаний, само собой, все репозитарии обновляем. Но для разработки — это просто не важно.
Если у вас не стреляет — наверное, незачем.

То есть у вас получается 2 типа релизов библиотеки(на которые стоит завязываться в submodules): изменение API и перед испытанием.

> В этом и кайф от деления на репозитарии.

Эм? Такой кейс же даже в одной ветке так работает, не? )
Эм? Такой кейс же даже в одной ветке так работает, не? )

Не понял, поясните чайнику.

Релизы у нас отдельно идут. То есть интеграция непрерывная, а релизы — это уже после прохождения всех испытаний. Перед релизами — некий период общей заморозки кода, когда баги правим, а фичи не вставляем…
> Ну написал коллега работу с USB, пока я не решу USB задействовать — мне это не важно. Аналогично, коллеге все равно, если изменил обработку ГЛОНАСС.

Вот это в одном репозитории в одном бранче работает.

А про релизы — это про другое, про библиотеки. С виду интеграция у вас непрерывная, по факту — как получиться (контролируется только в 2-х случаях). Вот с непрерывной интеграцией и submodules будет непросто, но вам, получается, и не надо.
А в чем проблемы с непрерывной интеграцией?

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


  1. либо теряете возможность полноценно бранчеваться, так как ваш "репозиторий" находится лишь в одной конкретной ветке "всего репозитория".
  2. либо начинаете бранчеваться внутри бранча и получаются в результате /project/trunk/gui/branches/123-better-design/outsource/trunk/
Потому что проект может состоять из десятков и сотней модулей, часть из которых нужно либо сохранить в коммерческой тайне, либо их пишут определенные люди, и другим там делать нечего.

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

А как у вас отлаживают свои правки в такой проект люди, не имеющие доступа к коммерческой тайне?
Ну нужно пояснить, что у нас происходит.
У нас большой C++, состоящий из большого количества модулей (компилируются в итоге в статические/динамические библиотеки). Ясное дело, каждый модуль мы можем выделить в отдельный репозиторий, и дать к нему полный доступ. Юзер может писать там код, добавлять тесты и т.д.

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

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

Есть большой проект, который состоит из большого количества библиотек. Скажем, ModuleA, ModuleB, ModuleC и т.д.ModuleA, например — купленный за лям баксов проект у сторонней организации, и допиленный нами до нужного функционала. Лежит в отдельном репе. ModuleB — наша математическая модель, которую пишет всего пара человек, разбирающиеся в вопросе. Он также закрыт от большинства.
ModuleC — какой-нибудь удобный враппер над какой-нибудь библиотекой, нам все равно, кто его пишет, главное — чтобы хорошо работал.

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

Большой прожект состоит из этих мелких проектов, которые вливаются в него с помощью subtree. Он собирается на билд-сервере, дальше уже прогоняются юнит-тесты и прочие тесты всего проекта. Дальше q&a берут с сервера deb пакет, ставятся себе и уже тыкают в него на поиск багов, которые спрогнозировать сложно.

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

А «Выделять 2 файла из модуля и давать кому-то на разработку» — это к чему было?

Это было к предыдущего сообщению:
Почему вы думаете, что иметь один репозиторий, давая доступ к его части лучше, чем иметь 2 репозитория?
простой пример, поддержка версионирования двух репозиториев намного сложнее поддержки одного
В последнее время крайне редко видел чистый гит. Обычно все пользуются им через bitbucket/gerrit и др., где права доступа настраиваются на порядок гибче.

Гит осваивать почти не нужно — разъяснить что кроме commit надо еще push, написать краткую вики и все. Просто нужно, чтобы в проекте был человек, который первые пару месяцев сможет разруливать нестандартные конфликты.
Добавлю пять копеек за hg. В нем можно создавать полноценные сабрепозитории (например, в них можно перемещаться по любым веткам и даже создавать свои, но последнее не приветствуется) и давать доступ только к ним. Единственное неудобство — тем, кто имет доступ к основному репу, приходится подтягивать изменения в сабрепах и коммитить основной.
Из преимуществ вспоминаются:
1. При копировании файла сохраняется его история
2. Раздельные права доступа на отдельные каталоги
3. Externals (хотя фича крайне неоднозначная)
4. Не нужно распихивать .gitignore по пустым каталогам
UFO just landed and posted this here
Если я не ошибаюсь, то с версии 2.9 в гите переименование файла не теряет историю.

В гите всегда теряется история. Он пытается угадать, ища похожий файл в предыдущем коммите, но как правило часто ошибается. Для сравнения — меркуриал пытается угадать перед коммитом и если он угадал не правильно — ему можно объяснить как правильно.

UFO just landed and posted this here
Не очень понятна природа этой ошибки, если файл не переписывается почти полностью.

Ну так в гите эвристика простая — если отличия превышают определённый процент строк, то файлы считаются разными. Такой вот кривой дизайн Торвальдс придумал. Починить это можно, например, добавлением мета информации где-нибудь сбоку, как к в SVN прикрутили merge tracking, но работать этот костыль будет также криво и косо. Так и живём: притворяемся, что в гите есть ветки, что легко можно восстановить историю кода, что команды логичны и удобны, что сквашивание коммитов и перебазирование нужно для "чистоты истории", а не потому, что невозможно достоверно понять какой коммит к какой ветке относился.

Вопрос именно в этом проценте строк, которые поменялись. Если это 80% файла (например от старого остался только копирайт, а не поменяли уровни отступов), то уже не важно что было в прошлом — важно зачем это поменяли, что должно быть написано в самом коммите.
А если добавили try catch на основное тело и отступ сделали, то это новый файл
  1. Как костыль можно переименование и изменение разбить на 2 коммита
  2. Я не знаю как гит относится к отступам при перемещении файлов, но если в этом случае файл считается полностью измененным тогда это несомненный косяк


Насколько я знаю, у самого репозитория способа хранения копирования/перемещения/переименования вообще нет, для него этого новые/удаленные файлы. А решение показывать удаление и(или) создание или переименование принимается во время показа пользователю непосредственно в клиенте и там задаются параметры типа считать ли пробелы значимыми или сколько процентов должно быть совпадения, чтоб считать одним файлом
  1. Это сломается, когда все коммиты фичеветки сольют в один коммит в мастер "для чистоты истории"..

По умолчанию, гит считает файлы разными, если различия превышают 50%.


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

С моей точки зрения, фичеветка должна быть влита в мастер с --no-ff — так получится, что в мастере будет один коммит приносящий фичу, а история сохранится для потомков.

Поэтому с SVN надо переходить на HG, а не на Git :-)

1. Как было замечено рядом в треде, это ломается только при сильном изменении файла (что, может, и логично). Если файл просто переместился, все ок.
2. Этот тред обсуждался чуть выше — решается subtree и отдельным репозиторием.
3. Я, честно говоря, не очень в теме, что это.
4. .gitignore достаточно положить в корень репозитория.

По пустым каталогам обычно .gitkeep распихивают, если действительно нужно версионировать пустой каталог.

Обычно если нужно, чтобы при git clone он создавался.

Из очевидного, большие бинарные файлы все ещё боль в git и hg тоже.

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

Для этого придуман HG Largefiles extension. Идёт в комплекте поставки, надо только включить в конфиге.


Это я пишу, как Gitовод, но в компании любят Mercurial, видимо, за large files из коробки.


А Git LFS надо спецом клиенту ставить, иначе молча пропускает...

Всё верно, но, к сожалению, это тоже палка о многих концах, с largefiles мы хлебнули массы неочевидных проблем, хотя от безысходности пользуемся.

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

Я в некоторых проектах использую SVN для репозиториев Thirdparty. Нет смысла хранить локально всю историю изменений очень тяжелого редко обновляющегося репозитория.
С точки зрения хранения серверных конфигов SVN гораздо удобнее. Потому что не тянет локально на каждый сервак весь репозиторий, а позволяет системный каталог с конфигами (например, /etc или /usr/local/etc) сделать рабочей копией. Что очень удобно — поменял конфиг на серваке, дёрнул сервис, если всё заработало — сразу закоммитил прямо из /etc.
  1. В git help clone прекрасно описаны параметры --depth и --branch, которые позволяют вытащить определенную ветку/тэг на указанную глубину. О depth в комментариях говорилось уже не раз.


  2. Держать /etc в репозитории для сохранения истории изменений в принципе можно. Ради последующего просмотра. Делать checkout крайне не рекомендуется: проблемы бывают от побитых прав на файлы (user/group/xattr/acl) до приведения системы в нерабочее состояние, но это сильно зависит от того, что живёт на сервере, может и пронести.

Права и атрибуты можно так же сохранить в VCS. Готовых систем я не видел, но технических препятствий не вижу, другое дело, насколько и как именно придётся заморочится и чем вы за это заплатите. С git’ом, кажется, будет проще, если написать скрипты‐обёртку над commit/status/checkout и сохранять данные об атрибутах в отдельных файлах, mercurial вроде позволяет написать расширение, улучшающее функционал встроенных команд и позволяющее сохранять дополнительные метаданные (и ещё посылать пользователей, хотящих сделать clone без установки расширения), но это должно быть более трудоёмким. Subversion — не знаю. С сохранением метаданных у него вроде лучше чем у git, но про расширения я не слышал.

Готовое решение: etckeeper. Поддерживает не только git.
Git так и не научился отдавать один файл/директорию без скачивания всего репозитория со всеми изменениями? Менеджеры пакетов, постоенные на git так и качают 95 избыточных процентов в виде папки .git для каждого пакета?
В git можно задать (глубину) depth, и скачать только один «срез».
Спасибо. Не знал. А что насчет скачивания отдельного файла или директории?
Да легко

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.

Очевидно, человек имел ввиду VCS.

> выкатка подразумевает другое, в зависимости от админов

Понятно, что там ещё всякие проверки, миграции и прочее, но код-то из репозитория всё равно скачать надо, если язык не компилируемый

> Capistrano (один подход) или про Opscode Chef

Я люблю няшненький питончег, поэтому Ansible :)
Не сказал бы, так как проще выкачивать http/s, чем держать процессы архивации, которые жрут по 50-100% CPU.
tar не архив. Как минимум, не в современном понимании этого слова

tar именно архив без какой-либо компрессии. Просто благодаря всяким архиваторам типа zip/rar/arj народ привык, что архиватор не только архивирует, но ещё и жмёт.

не в современном понимании этого слова


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

ну на деле можно. через репозиторий. везде есть Edit или Upload.


понятно, что это делается клон и все такое в фоне.

Вы git с github'ом не перепутали?

с любой оболочкой сверху.


а у собственно git есть git archive,

Возьмите Git Extensions (для Windows), который умеет показать вам произвольный файл из произвольного коммита, Не думаю, что он работает с «базой данных» GIT'а не через его API.

С большой вероятностью он делает то же, что и git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>..., см. git-checkout(1).

А еcли для svn сделать svnadmin pack и посмотреть размер?
Отличное замечание, но особо не влияет.
svnadmin.exe pack svn
214 MB (4,644 Files, 89 Folders)
Помогло только с количеством файлов, объем незначительн вырос.
Ну как сказать у меня есть система где один раз в 6 минут идёт комит. Там объём с 20 гигов до 500 метров падал.

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

Статья опровергает, прежде всего, аргументы тех, кто против перехода.

ну опровергнутые аргументы такие себе, получается правы сослуживцы, считающие, что шило на мыло

Как бывает:
— Давайте перейдём на гит, у него есть такие-то такие-то плюсы!
— Плюсы, конечно, хорошо, но вот есть такие минусы — и список этих мифов
— Вот на хабре опровергли эти минусы — и ссылка на это пост.

Минусы перехода опровергнуты, а плюсы — нет.
Мифы, как мне кажется, неправильно сформулированы.
Когда говорят о том, что размер репозитория больше, говорят в основном о том, что нельзя часть репозитория вытащить. То есть если у вас 20 гигабайт репозиторий, то вам придется тащить сначала все 20 гигабайт, даже если вам нужно поменять 1 файлик на 10 байт. В SVN любая папка сама по себе практически репозиторий.
Про ветки — даже если в svn сделать ветку также легко, как и в git-e, то это не значит, что они такие же легкие. Операции с ветками, например слияние, в svn все-таки тяжелее проходят. А merge (и rebase) — это главная операция для веток все-таки.

Основные преимущества гит перед свн:


  • скорость работы
  • быстрые и качественные операции над ветками — merge и rebase
  • образцово качественная утилита командной строки с очень богатым инструментарием

Основные преимущества свн перед гит:


  • возможность заливать большие файлы без потери производительности (актуально для документации и не только в IT)
  • наличие GUI для секретарш
  • быстродействие не деградирует для очень больших репозиториев (монорепо или просто крупный проект)
  • возможность назначать права на каталоги.
наличие GUI для секретарш

А что для Git не существует гуев "для секретарш"? SourceTree, Tower, GitUp — это то что на вскидку вспомнилось.

Довелось работать с SourceTree — в итоге использовал для запуска консоли.
Source Tree — относительно универсальная среда и поэтому не всегда пользуется терминологией гита, что при знании консольных комманд заставляет каждый раз задумываться, что происходит под капотом.

Мое личное мнение — для гита нужно использовать либо консоль, либо GUI написанный специально для него, чтобы «секретарши» говорили на одном языке с теми, кто GUI не пользуется.
Юзаю TortoiseGit, всё устраивает. Если навести на элемент GUI, то он покажет какие ключики будут использоваться. Пишет команду, которую использовал, так что можно скопировать коллеге или на будущее, отображает процесс во время работы.

Для секретарш советую использовать расшаренный диск или FTP, или даже WebDAV. Меня всегда удивляло, что в плюсы SVN записывают аспекты, не относящиеся к разработке. SVN это инструмент для разработчика, в первую очередь.

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

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

В случае с 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-ки?

как правило, word, powerpoint, картинки. Одна инструкция пользователя чего стоит. Формы и образцы, если приложение относится к документообороту. Всякие-разные регулирующие документы по предметной области.

UFO just landed and posted this here
Прямо с первых строк статьи начинается подтасовка фактов. Надеятся что на хабре читатели не знают английский по меньшей мере странно.
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, создается новый коммит, и если требуется, создается новое дерево файлов для него (хранится отдельно)

Поэтому я и говорю, что размер репозитория увеличится лишь на размер изменённых файлов + метаданные.


Git хранит

Тут конечно же я имел ввиду сохранения файла в репозитории во время коммита.

Поменяли 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 шара (с версиям по папочкам) как совсем легкий и простой вариант.

конкурируют maven, artifactory и samba шара

Вы здесь под maven подразумевали Sonatype Nexus (если уж JFrog Artifactory в одном ряду)? Т. к. сам Apache Maven — не про хранение репозитория, а про разрешение зависимостей и сборку.

Поправка. Насчет легкости слияний в git. Я вообще не представляю как слияния возможно использовать с бинарями.

Смотря какие бинари. Например, Word умеет сливать файлы от разных авторов, LabView тоже. Для некоторых типов файлов можно тоже сообразить что‐то ограниченно полезное: к примеру, zip архивы сливать как будто это каталоги с файлами, с изображениями: преобразовывать метаданные в форматированный YAML, сливать, преобразовывать обратно, сами изображения сливать только если изменения в разных ветках внесены в разные области изображения… Но если ПО, в котором вы работаете с бинарниками не предлагает своего варианта слияния, то, скорее всего, возможные методы слияния будут сильно зависеть от workflow (т.е. не универсальны).

UFO just landed and posted this here

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

UFO just landed and posted this here
UFO just landed and posted this here
Лет 10 назад, использовал svn, добавил в проект файл с именем на кириллице. Он благополучно его закоммитил. А когда я пытался восстановить проект из репозитория, выдал ошибку и весь репозиторий сломался. Хорошо ещё что я регулярно делал .zip архивы.
Git хоть и не разрушает репозиторий, в аналогичной ситуации, но при выводе имён файлов выдаёт коды символов через слэш. С диффом и комментариями (в тексте программы) на русском языке та же проблема.
Git хоть и не разрушает репозиторий, в аналогичной ситуации, но при выводе имён файлов выдаёт коды символов через слэш. С диффом и комментариями (в тексте программы) на русском языке та же проблема.

Если git отображает имена файлов и содержимое с символами через бэкслеш (иногда в угловых скобках), то это означает, что ваш терминал плохо работает с используемой кодировкой. С большой вероятностью, с utf8. Проверяйте настройки терминала и локали.

Вы знаете, у меня даже emoji в описаниях коммитов нормально работают. Кажется, дело не в git-е.

Sign up to leave a comment.

Articles