Системы контроля версий — это программные инструменты, помогающие разработчикам отслеживать изменения в исходном коде и управлять ими. Существует множество систем контроля версий (version control system, VCS), каждая из которых имеет собственные функции и возможности.

Одними из самых популярных VCS являются Git, Mercurial и Subversion. Все эти системы предназначены помогать разработчикам совместно работать над проектами, отслеживать изменения в своём коде и поддерживать историю работы. В этом посте я расскажу о новом игроке в этой области, разработанном внутри компании Meta* — VCS Sapling.

Зачем нам нужна Sapling?


Учитывая то, что наряду со многими другими уже есть Git, Mercurial и Subversion, сложно понять, зачем же нам нужна ещё одна система контроля версий. По словам Meta*, Sapling основной упор делает на удобство пользования и масштабируемость, заявляя, что стандартные рабочие процессы в ней реализованы проще, а восстанавливаться после ошибок намного легче. Кроме того, Meta* спроектировала Sapling и Sapling Server таким образом, чтобы они были высокомасштабируемыми и справлялись с обработкой миллионов файлов.

Sapling SCM (source code management) состоит из трёх частей:

  • Sapling CLI — инструмент командной строки, при помощи которого пользователи могут клонировать репозитории, выполнять коммиты и пушить изменения на сервер
  • Sapling Server — бэкенд-приложение на стороне сервера, хостящее репозитории и управляющее ими.
  • Sapling Virtual Filesystem — файловая система, используемая Sapling для ускорения процесса работы.

На конец 2022 года был выпущен только Sapling CLI, а Sapling Server и Virtual Filesystem пока публично недоступны. Однако Sapling можно использовать с имеющимися репозиториями Git, и он даже хорошо интегрируется с GitHub!

Как установить Sapling


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

В macOS — установить из Homebrew при помощи следующей команды:

$ brew install sapling

В Windowsскачать последнюю версию в ZIP и выполнить в PowerShell следующие команды:

PS> Expand-Archive NAME_OF_DOWNLOADED_ZIP 'C:\\Program Files' 
PS> setx PATH "$env:PATH;C:\\Program Files\\Sapling" -m

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

В Ubuntu 22.04 — выполнить следующие команды:

$ curl -L -O <https://github.com/facebook/sapling/releases/download/0.1.20221213-150011-h9b0acf12/sapling_0.1.20221213-150011-h9b0acf12_amd64.Ubuntu22.04.deb> 
$ sudo apt install -y ./sapling_0.1.20221213-150011-h9b0acf12_amd64.Ubuntu22.04.deb

В Ubuntu 20.04 — выполнить следующие команды:

$ curl -L -O <https://github.com/facebook/sapling/releases/download/0.1.20221213-150011-h9b0acf12/sapling_0.1.20221213-150011-h9b0acf12_amd64.Ubuntu20.04.deb> 
$ sudo apt install -y ./sapling_0.1.20221213-150011-h9b0acf12_amd64.Ubuntu20.04.deb

В других Linux — при наличии Homebrew можно установить Sapling из него:

$ brew install sapling

Если у вас нет Homebrew, то пока единственным оставшимся вариантом для вас является сборка из исходников.

Как настроить Sapling


После установки Sapling в систему в терминале должна стать доступной команда sl. Чтобы приступить к её использованию, необходимо сначала настроить свою идентификацию. Она используется для авторизации коммитов. Настроить её можно следующим образом:

$ sl config --user ui.username "YOUR NAME <YOUR EMAIL>" 
# для примера... 
$ sl config --user ui.username "Michael Krasnov <[email protected]>"

После выполнения этих команд Sapling готов к работе. Однако если вы хотите использовать Sapling с GitHub, нужно настроить аутентификацию GitHub для Sapling. Для этого рекомендуется установить GitHub CLI (gh) и выполнить следующую команду:

$ gh auth login --git-protocol https

На мой взгляд, наличие двух инструментов для работы с репозиториями GitHub — это уже перебор. Можно заставить работать его без GitHub CLI, если создать персональный токен доступа и при запросе передать его Sapling.

Как пользоваться Sapling


Теперь давайте разберёмся с базовыми рабочими процессами, чтобы понять, как пользоваться Sapling в реальных проектах. Для экспериментов я создал в своём аккаунте GitHub форк репозитория Redux. Начнём с клонирования репозитория из Github. Для клонирования репозитория из GitHub при помощи Sapling выполним следующую команду:

$ sl clone <GITHUB REPO URL> 
# для примера... 
$ sl clone <https://github.com/r3dm1ke/redux>

Мы получим результаты, знакомые всем, кто раньше пользовался Git:

remote: Enumerating objects: 20640, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 20640 (delta 1), reused 1 (delta 1), pack-reused 20633
Receiving objects: 100% (20640/20640), 23.78 MiB | 2.27 MiB/s, done.
Resolving deltas: 100% (13183/13183), done.
From https://github.com/r3dm1ke/redux
 * [new ref]           fbfe51458ca2addf97f426d505bf2c27503a5ff1 -> remote/master
452 files updated, 0 files merged, 0 files removed, 0 files unresolved

Теперь можно выполнить cd в клонированный проект и проверить, всё ли получилось, запустив команду sl:

$ sl
@  fbfe51458  Dec 15 at 10:20  65634467+Ahmed-Hakeem  remote/master
│  change reducer type validation place (#4452)
~

По умолчанию команда sl показывает нам последний коммит в репозитории, а также все ваши собственные коммиты в вашем стеке (подробнее об этом ниже).

Для просмотра полной истории коммитов в Sapling нужно выполнить команду sl log:

$ sl log
changeset:   fbfe51458ca2addf97f426d505bf2c27503a5ff1  (@)
user:        Hakeem <65634467+Ahmed-Hakeem@users.noreply.github.com>
date:        Thu, 15 Dec 2022 10:20:08 -0500
summary:     change reducer type validation place (#4452)

changeset:   a0754310222ad61bde675078963afb7fc038d5d7
user:        Mark Erikson <mark@isquaredsoftware.com>
date:        Mon, 05 Dec 2022 10:49:27 -0500
summary:     Merge pull request #4448 from jshoung/docs/remove-dead-link

changeset:   89104853174e62de8ebbca4881ea14a04399f4e2
user:        julian <julianks@gmail.com>
date:        Mon, 05 Dec 2022 10:00:58 -0500
summary:     Remove link to deleted tweet

changeset:   9be553a2c5ba04d9d769f31e25a6dc93deb334cf
user:        Mark Erikson <mark@isquaredsoftware.com>
date:        Wed, 30 Nov 2022 10:12:49 -0500
summary:     Merge pull request #4447 from mariussd/patch-1

...        

Теперь давайте разберёмся, как коммитить и пушить работу в Sapling. Сначала я внесу изменения в проект:

$ echo "PS Redux is awesome" >> README.md
$ touch newfeature.js
$ echo "TODO: write new feature" >> newfeature.js
$ sl status
M README.md
? newfeature.js

Команда sl status работает так же, как git status. Видно, что Sapling заметил, что мы изменили README.md и создали newfeature.js. Вопросительный знак рядом с newfeature.js означает, что мы пока не выполнили add:

$ sl add newfeature.js
$ sl status
M README.md
A newfeature.js

Теперь можно выполнить коммит изменений. Чтобы внести коммит изменений в Sapling, нужно выполнить следующую команду:

$ sl commit -m "Initial work for my new feature"
$ sl
  @  b6989309b  2 seconds ago  mihalKrasnov
╭─╯  Initial work for my new feature
│
o  fbfe51458  Dec 15 at 10:20  remote/master
│
~

Мы видим наш новый коммит в виде графа. Чтобы просмотреть другие возможности, давайте добавим ещё коммитов:

$ echo "Developed new exiting feature!" >> CHANGELOG.md
$ sl commit -m "Updated changelog"
$ echo "const feature = () => console.log('abacaba')" >> newfeature.js
$ sl commit -m "Feature implementation"
$ sl
  @  8c9eb0035  1 second ago  mihalKrasnov
  │  Feature implementation
  │
  o  e445f1379  87 seconds ago  mihalKrasnov
  │  Updated changelog
  │
  o  b6989309b  3 minutes ago  mihalKrasnov
╭─╯  Initial work for my new feature
│
o  fbfe51458  Dec 15 at 10:20  remote/master
│
~

Теперь мы видим в стеке три коммита. Обратите внимание, что самый последний коммит помечен символом @. Перемещаться по стеку можно командами sl prev и sl next:

$ sl prev
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
[e445f1] Updated changelog

$ sl
  o  8c9eb0035  4 minutes ago  mihalKrasnov
  │  Feature implementation
  │
  @  e445f1379  5 minutes ago  mihalKrasnov
  │  Updated changelog # ТЕПЕРЬ @ НАХОДИТСЯ ЗДЕСЬ
  │
  o  b6989309b  7 minutes ago  mihalKrasnov
╭─╯  Initial work for my new feature
│
o  fbfe51458  Dec 15 at 10:20  remote/master
│
~

$ sl prev
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

$ sl
  o  8c9eb0035  4 minutes ago  mihalKrasnov
  │  Feature implementation
  │
  o  e445f1379  5 minutes ago  mihalKrasnov
  │  Updated changelog
  │
  @  b6989309b  7 minutes ago  mihalKrasnov
╭─╯  Initial work for my new feature # А ТЕПЕРЬ ЗДЕСЬ
│
o  fbfe51458  Dec 15 at 10:20  remote/master
│
~

$ sl next 2
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
[8c9eb0] Feature implementation

$ sl
  @  8c9eb0035  4 minutes ago  mihalKrasnov
  │  Feature implementation # И СНОВА ЗДЕСЬ
  │
  o  e445f1379  5 minutes ago  mihalKrasnov
  │  Updated changelog
  │
  o  b6989309b  7 minutes ago  mihalKrasnov
╭─╯  Initial work for my new feature
│
o  fbfe51458  Dec 15 at 10:20  remote/master
│
~

Теперь предположим, что мне не нравится реализация моей фичи и мне хотелось бы отменить последний коммит. Для отмены последнего коммита в Sapling нужно выполнить команду sl uncommit:

$ sl uncommit
$ sl
 # ПЕРВЫЙ КОММИТ ПРОПАЛ!
  @  e445f1379  9 minutes ago  mihalKrasnov
  │  Updated changelog
  │
  o  b6989309b  11 minutes ago  mihalKrasnov
╭─╯  Initial work for my new feature
│
o  fbfe51458  Dec 15 at 10:20  remote/master
│
~
$ sl status
M newfeature.js # ИЗМЕНЕНИЯ ОСТАЛИСЬ НЕТРОНУТЫМИ

После исправления последнего изменения нам нужно запушить изменения и открыть пул-реквест. Так как Sapling интегрируется с GitHub, сделать это очень просто: для пуша и открытия пул-реквеста достаточно выполнить команду sl pr:

$ sl pr
pushing 3 to https://github.com/r3dm1ke/redux
created new pull request: https://github.com/r3dm1ke/redux/pull/1
created new pull request: https://github.com/r3dm1ke/redux/pull/2
created new pull request: https://github.com/r3dm1ke/redux/pull/3

Как видите, Sapling создала три пул-реквеста, по одному для каждого коммита. Это кажется контринутитивным и совершенно неправильным, особенно при работе с GitHub. На самом деле, это сделано для работы с ReviewStack — UI, созданного Meta* для просмотра пул-реквестов GitHub. Подробнее о нём можно прочитать здесь.

Ещё одна полезная функция — это просмотр статусов PR из командной строки. Открыв пул-реквесты, для получения их статусов выполните sl ssl:

$ sl ssl
  @  b615c1183  7 minutes ago  mihalKrasnov  #4458 Closed ✓
  │  Implementation
  │
  o  e445f1379  17 minutes ago  mihalKrasnov  #4457 Closed ✓
  │  Updated changelog
  │
  o  b6989309b  19 minutes ago  mihalKrasnov  #4456 Closed ✓
╭─╯  Initial work for my new feature
│
o  fbfe51458  Dec 15 at 10:20  remote/master
│
~

Как пользоваться Sapling UI


Sapling — это не полностью CLI-программа, она имеет и GUI. Работа с GUI для контроля версий может оказаться удобнее и проще, чем работа с интерфейсами командной строки; она предоставляет такие визуальные функции, как графическое отображение ветвей и историй коммитов. Однако приложения с GUI могут быть более медленными и менее гибкими в настройке, чем CLI.

Чтобы открыть GUI Sapling, нужно выполнить команду sl web:

$ sl web
started a new server

access Sapling Web with this link:
http://localhost:3011/?token=

Открыв этот URL, вы увидите UI:


При помощи этого UI можно просматривать историю коммитов, открывать PR, diff, выполнять правки (amend) и коммиты, а также синхронизировать изменения с сервером. Однако мне он не показался особо полезным и для всего связанного с GUI я продолжу пользоваться GitKraken.

Ключевые отличия от Git


Sapling — это система контроля версий, имеющая множество общих с Git характеристик, например, распределённость, использование адресации коммитов на основе хэшей и наличие ветвей под названием «bookmark», а также схожий рабочий процесс, включающий в себя clone, pull, push, commit и rebase. Однако между двумя системами существует и много существенных различий.

  • Локальные ветви не требуются: в Git репозиторий определяется наличием локальных ветвей и в процессе работы вы обязательно должны быть на локальной ветви. Sapling позволяет при желании использовать локальные bookmark (эквивалент ��етвей Git), но они необязательны. Вместо этого можно просто ссылаться на коммиты по их хэш-значениям, отображающимся в дисплее «smartlog».
  • Частичные загрузки: при клонировании или пуллинге из репозитория в Git пользователь обычно получает все новые данные. В Sapling операции clone или pull считывают только основные ветви репозитория, а остальные ветви считываются по необходимости.
  • Функции отмены: эта функция определённо полюбится сообществу разработчиков. Sapling имеет специальные команды «uncommit», «unamend», «unhide» и «undo» для отката распространённых действий, а команда «undo -i» позволяет предварительно просматривать эффект нескольких undo перед их применением.
  • Отсутствие области подготовки (staging area): Git требует перед выполнением коммитов изменений помещать их в область подготовки, однако у Sapling её нет. Если вы хотите выполнить коммит или amend только части изменений, то можно использовать интерактивную опцию выбора конкретных изменений или создать временный коммит, а потом выполнить его amend до свёртывания его в реальный коммит.
  • Встроенный UI: эта функция понравится тем, кто не любит пользоваться CLI

Плюсы и минусы


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

▍ Плюсы


  • После многих лет использования Git система Sapling кажется глотком свежего воздуха. Рабочие процессы (по крайней мере, используемые мной) кажутся проще, Sapling более быстрым, а команды — более интуитивными
  • Команды undo очень часто спасают, и я с большей уверенностью пользуюсь сложными функциями VCS в Sapling, зная, насколько легко всё откатить

▍ Минусы


  • Отсутствие ветвления кажется мне контринтуитивным. Когда над одним репозиторием работает множество людей, очень легко просматривать все ветви и переключаться между ними, а также ребазировать другие изменения в свою ветвь. Возможно, всё придёт с опытом, но пока я отдаю предпочтение ветвлению Git, а не букмаркингу Sapling
  • По одному PR на коммит: это логично при использовании Sapling Server или ReviewStack, но бесполезно с «ванильным» GitHub
  • Sapling по-прежнему находится на ранних этапах разработки, поэтому в нём отсутствуют многие функции, доступные в Git, например, Git hooks (на стороне и клиента, и сервера), поддержка сообщества, инструменты и UI.

Пока я не буду переходить с Git на Sapling, но она очень любопытна и я рад, что в мире VCS кипит конкуренция. Кроме того, я с нетерпением жду релиза Sapling Server и Virtual Filesystem, чтобы сделать и их обзор тоже.

* Внесена в перечень общественных объединений и религиозных организаций, в отношении которых судом принято вступившее в законную силу решение о ликвидации или запрете деятельности по основаниям, предусмотренным Федеральным законом от 25.07.2002 № 114-ФЗ «О противодействии экстремистской деятельности».

Играй в нашу новую игру прямо в Telegram!