Непревзойденное удобство Git в JetBrains (и какую цену мы за него платим)
Если вы когда-либо писали код в WebStorm, IntelliJ IDEA или PyCharm, то наверняка знаете: в JetBrains создали эталонный, невероятно удобный рабочий процесс для работы с Git.
Дело не просто в добавлении файлов в индекс — дело в многолетней мышечной памяти:
- Changelists (Списки изменений): Возможность логически группировать файлы по задачам, отделять эксперименты от срочных хотфиксов и коммитить только нужную часть работы без утомительного
git add -p. - Git Shelf (Локальная полка): Откладывание незавершенной работы («зашелвить») с понятными описаниями и комментариями, оставляя рабочую директорию чистой и не засоряя анонимными записями
git stash. - Интерактивный Diff-редактор: Сравнение файлов side-by-side с возможностью прямо в окне диффа редактировать файл рабочей копии и сохранять по
Cmd+S, а также откатывать отдельные куски (hunks) одним кликом по стрелке в гаттере (↩). - Эргономика горячих клавиш: Перемещение между различиями по
F7/Shift+F7и моментальный коммит поCmd+Enter.
В чем проблема: налог на тяжеловесность
Несмотря на всю любовь к этому воркфлоу, меня постоянно преследовало раздражение. IDE от JetBrains — это огромные комбайны на JVM. Запуск WebStorm только ради того, чтобы посмотреть дифф, зашелвить пару файлов или сделать чистый аккуратный коммит, занимает от 15 до 30 секунд и сжирает 1.5–3 ГБ оперативной памяти.
Когда я пишу небольшие скрипты в терминале, редактирую конфиги в легких редакторах или переключаюсь между десятком микросервисных репозиториев, открывать полноценную IntelliJ IDEA ради пары кликов в Git — все равно что заводить тяжелый самолет, чтобы просто доехать до соседнего магазина.
Я перепробовал все популярные альтернативы:
- VS Code: Встроенная работа с Git лишена полноценных ченджлистов, нет аналога Shelf, а диффы не дают интерактивно откатывать конкретные куски кода удобными маркерами в гаттере.
- GitKraken: Сделан на Electron. Потребляет 700 МБ–1.2 ГБ RAM, запускается по 4–6 секунд, а базовые фичи прячет за платной подпиской.
- SourceTree: Медленный, визуально перегруженный и морально устаревший интерфейс.
- Sublime Merge: Очень быстрый, но в нем нет концепции ченджлистов, редактирования кода прямо внутри диффа и удобного шелвинга.
Тогда я задал себе простой вопрос:
А можно ли сделать отдельный автономный Git-клиент для macOS, который запускается меньше чем за 150 миллисекунд, потребляет всего ~35 МБ памяти и дает ровно тот самый любимый воркфлоу WebStorm?
Так родился проект ultra Git. Ниже — подробная история того, как устроена архитектура приложения, какие инженерные грабли встретились на пути и как удалось добиться такой скорости.
Архитектура: почему мы отказались от Electron в пользу Swift + WKWebView
Когда сегодня разрабатывают кроссплатформенные десктопные инструменты, первым делом берут Electron. Однако у Electron огромная цена: каждое окно тащит с собой целый экземпляр браузера Chromium и процесс Node.js. В итоге установщик весит 200+ МБ, в памяти приложение занимает от 400 МБ, а холодный старт заставляет ждать.
Чтобы на macOS приложение открывалось мгновенно и не расходовало ресурсы ноутбука, я выбрал гибридную нативную архитектуру:
1 | ┌────────────────────────────────────────────────────────┐ |
1. Нативный контейнер на Swift (macos/main.swift)
Приложение для macOS написано на чистом Swift без сторонних зависимостей:
- Создает нативное окно
NSWindowс темным оформлением и аккуратными системными кнопками управления. - Встраивает компонент Apple
WKWebViewс аппаратным ускорением графики. - Автоматически поднимает локальный бэкенд-процесс при старте.
- Скомпилированный бинарник весит всего 75 КБ, стартует за менее чем 150 миллисекунд и потребляет в покое всего ~35 МБ оперативной памяти.
2. Локальный Git микро-сервер
Вместо использования тяжелых нативных C-библиотек вроде libgit2 (которые регулярно вызывают проблемы со сборкой на разных архитектурах процессоров и не учитывают пользовательские конфиги), бэкенд общается напрямую со стандартным системным git CLI:
- Автоматически подхватывает ваш существующий
.gitconfig, SSH-ключи, GPG-подписи и алиасы. - Все операции (стейджинг, диффы, шелв, коммиты) выполняются стандартными проверенными командами Git без скрытых сайд-эффектов.
Воплощение возможностей WebStorm в жизнь
1. Ченджлисты: осознанный стейджинг файлов
В стандартном Git файлы либо не отслеживаются, либо изменены, либо находятся в индексе. JetBrains превратил работу с изменениями в удовольствие с помощью Changelists — виртуальных списков файлов, позволяющих разделить текущую работу на независимые части:
Default changelist: активная работа, готовая к ревью и коммиту.- Пользовательские ченджлисты (например,
Рефакторинг авторизации,Временные тесты,Правки в доках).
В ultra Git ченджлисты сохраняются в файле .git/ultra-changelists.json. Любой измененный файл можно перетащить мышкой (drag & drop) в другой список или переместить через контекстное меню.
При нажатии Cmd+Enter ultra Git берет только выбранные галочками файлы конкретного ченджлиста, аккуратно индексирует их и создает коммит.
2. Локальная полка (JetBrains Shelf)
В отличие от git stash, который работает как слепой стек по всему репозиторию сразу, функция Shelve позволяет:
- Выбрать конкретные файлы или целый ченджлист.
- Задать понятное текстовое описание.
- Сохранить их на диск в виде отдельного патча.
- В любой момент просмотреть дифф отложенных изменений прямо в интерфейсе.
- Вернуть изменения обратно в рабочую копию (Unshelve) в один клик (с возможностью опции Keep in shelf, чтобы сохранить патч для повторного применения).
В ultra Git все шелвы лежат в папке .git/ultra-shelf/ в виде чистых .patch файлов с метаданными в JSON. Они изолированы, не засоряют историю git reflog и не конфликтуют с удаленными ветками.
3. Вкладки проектов и история недавних репозиториев
Разработчики редко сидят в одном репозитории. В верхней панели ultra Git встроены вкладки с переключением за 0 миллисекунд:
- Параллельное открытие нескольких проектов.
- Быстрый доступ к 10 последним открытым репозиториям.
- Дерево файлов с ленивой подгрузкой, которое мгновенно открывает даже огромные монорепозитории с десятками тысяч файлов.
Редактор диффов: технические вызовы и решения
Сердце любого Git-клиента — это просмотр диффов. Создание по-настоящему удобного редактора изменений оказалось самой интересной инженерной задачей проекта.
1 | Оригинал (HEAD) Модифицированный (Рабочая копия) |
Вызов 1: Баг виртуализации отступов в CodeMirror 6
Первая версия редактора была построена на CodeMirror 6 с кастомными расширениями ViewPlugin для отрисовки стрелок отката (↩) в колонке номеров строк (гаттере).
Здесь мы натолкнулись на неприятную особенность: CodeMirror 6 агрессивно виртуализирует DOM-узлы за пределами экрана. При выравнивании параллельных панелей диффа с разным количеством строк движок вставляет пустые спейсеры (spacer elements). При быстрой прокрутке больших файлов (на 2000+ строк) расчет высоты спейсеров сбивался, и правая колонка внезапно становилась пустой серой областью!
Решение: Мы переписали расчет координат высоты строк, стабилизировали спейсеры через проекцию абсолютных координат и добавили автоматическое центрирование скролла на первом изменившемся блоке при открытии любого файла.
Вызов 2: Полностью автономный офлайн-запуск Monaco Editor
Многие разработчики привыкли к движку Monaco Editor (на котором работает VS Code) за его подсветку синтаксиса, миникарту и работу с мультикурсорами.
Однако библиотека @monaco-editor/react по умолчанию загружает ресурсы Monaco из публичных CDN. Для локального инструмента разработчика недопустимо зависеть от подключения к интернету.
Мы полностью собрали Monaco локально через Vite. Чтобы веб-воркер сборщика корректно отрабатывал без сетевых запросов, мы настроили инстанцирование воркера через нативный синтаксис ES URL:
1 | // Конфигурация локального офлайн веб-воркера Monaco |
Вызов 3: Коллизия URI моделей и баг «0 различий»
После первого подключения DiffEditor из Monaco проявился коварный баг: файлы с очевидными изменениями отображали «0 diffs», а обе панели показывали либо пустой текст, либо одинаковый контент.
Изучение исходников Monaco показало причину: редактор кэширует модели глобально по их URI. При переключении между файлами обертка @monaco-editor/react повторно использовала анонимный URI по умолчанию (inmemory://model/1). Monaco считал, что модель не поменялась, и отдавал старую кэшированную пустую модель!
Мы решили проблему явной изоляцией URI для каждого открываемого файла:
1 | const originalUri = monaco.Uri.parse(`inmemory://diff/${safeFilePath}/original`); |
После этого расчет диффов заработал со 100% стабильностью: появился мгновенный подсчет измененных блоков через Chunk.build и удобная навигация по клавишам F7 и Shift+F7.
Вызов 4: Синхронизированный поиск по коду (Cmd+F)
Стандартный браузерный поиск не видит текст внутри виртуализированных строк редактора. Мы реализовали кастомную строку поиска поверх редактора:
- Поиск ведется одновременно по обоим буферам: и в оригинальном (HEAD), и в модифицированном.
- Показывается общий счетчик совпадений (например,
3 из 14). - Кнопки «Вперед» и «Назад» плавно скроллят нужный редактор и подсвечивают найденные строки.
Сравнение производительности в цифрах
Вот как ultra Git показывает себя в реальной повседневной работе на MacBook с Apple Silicon (M-серия):
| Параметр | WebStorm Git | GitKraken | VS Code Git | ultra Git |
|---|---|---|---|---|
| Холодный старт | ~18.5 сек | ~4.2 сек | ~2.8 сек | < 0.18 сек (180 мс) |
| Память в покое (RAM) | ~2100 МБ | ~780 МБ | ~450 МБ | ~35 МБ |
| Размер нативного бинарника | ~1.4 ГБ | ~280 МБ | ~310 МБ | 75 КБ (Swift) |
| Редактирование прямо в диффе | ✅ Да | ❌ Нет | ⚠️ Частично | ✅ Да (Cmd+S) |
| Откат отдельных кусков в гаттере | ✅ Да | ❌ Нет | ❌ Нет | ✅ Да (↩) |
| Полноценный Git Shelf | ✅ Да | ❌ Нет | ❌ Нет | ✅ Да |
| Поддержка Changelists | ✅ Да | ❌ Нет | ❌ Нет | ✅ Да |
Что дальше и как поучаствовать 🤝
Разработка ultra Git доказала: современный веб-стек в сочетании с нативными системными возможностями операционной системы не обязан быть прожорливым монстром. При грамотном подходе можно получить визуальное богатство современных редакторов кода со скоростью нативного C- или Swift-софта.
Проект полностью открыт и разрабатывается с прицелом на чистоту и модульность архитектуры. В планах:
- Визуальный граф коммитов и история веток (Git Log)
- Окно произвольного сравнения файлов с ветками и ревизиями
- Интерактивное разрешение 3-way конфликтов при слиянии (Merge Conflicts)
- Переключатель тем оформления (Светлая JetBrains Light, классическая Darcula, Catppuccin)
Если вы цените быстрые и отзывчивые инструменты для разработчиков — заходите в репозиторий, пробуйте на своих проектах и присылайте Pull Request!