В чем разница коммита и ветки в системах контроля версий
Что проверяют
Понимаете ли вы, как Git устроен внутри, или знаете только команды. Для ML-позиции следом почти всегда спрашивают, как вы версионируете эксперименты, данные и ноутбуки, раз ветка сама по себе ни метрик, ни датасета не хранит.
Как отвечать
Суть одной фразой: коммит это неизменяемый снимок проекта, а ветка это подвижный указатель на коммит.
- коммит: объект с полным состоянием дерева файлов, ссылкой на родителя (у merge-коммита их два и больше), автором, датой и сообщением. Его имя это хэш от содержимого, поэтому «поправить» коммит нельзя,
--amendиrebaseсоздают новые; - ветка: по сути запись с хэшем одного коммита. Создаётся мгновенно, данные не копируются. При новом коммите указатель ветки сдвигается на него;
HEAD: указатель на текущую ветку. Послеgit checkout <хэш>вы в detached HEAD, и новые коммиты там легко потерять, их не держит ни одна ветка;- история: коммит не «принадлежит» ветке, он достижим из одной или нескольких веток по цепочке родителей.
git branch --contains <хэш>покажет, из каких.
Для ML сразу покажите практику. Ветка на эксперимент удобна для кода, но веса моделей и датасеты в Git не кладут: репозиторий раздувается навсегда, даже если файл потом удалить. Их выносят в DVC (в Git едет маленький .dvc-файл с хэшем данных) или в Git LFS, а метрики и параметры запусков пишут в MLflow с привязкой к хэшу коммита. Тогда любой результат воспроизводится: коммит плюс версия данных.
Где спотыкаются
Говорят, что ветка это копия кода или папки. Отсюда страх заводить много веток и непонимание, почему переключение почти мгновенное.
Считают, что коммит хранит только diff. Модель данных Git построена на снимках, а дельта-сжатие в pack-файлах это оптимизация хранения, на смысл коммита она не влияет.
Коммитят ноутбуки вместе с выводами и картинками: диффы нечитаемы, конфликты почти не разрешаются. Выводы чистят через nbstripout или держат ноутбук в паре с .py-файлом через Jupytext.