Gitに代わる新たなバージョン管理ツール「jujutsu」を使ってみる

にあえん

February 14, 2024

お久しぶりです。ナナオです。

今回は今注目を集めているコードのバージョン管理ツール「jujutsu」を触ってみて、実際Gitと何が違うのか?を検証してみようと思います。

ちなみに、私は普段git-flowを使用したブランチ運用をしており、主に使用しているコマンドはこれくらいです。

インストール

Windowsを使用している場合、cargoを使用してインストールします。

Installation and Setup - Jujutsu docs

cargo install --locked --bin jj jj-cli --features vendored-openssl

インストールできました。

> jj --help
Failed to spawn pager 'LESSCHARSET=utf-8 less -FRX': program not found
Jujutsu (An experimental VCS)

To get started, see the tutorial at https://github.com/martinvonz/jj/blob/main/docs/tutorial.md.

Usage: jj.exe [OPTIONS] [COMMAND]

Commands:
  abandon    Abandon a revision
  backout    Apply the reverse of a revision on top of another revision
  branch     Manage branches
  cat        Print contents of a file in a revision
  checkout   Create a new, empty change and edit it in the working copy [aliases: co]
  chmod      Sets or removes the executable bit for paths in the repo
  commit     Update the description and create a new change on top [aliases: ci]
  config     Manage config options
  describe   Update the change description or other metadata
  diff       Show changes in a revision
  diffedit   Touch up the content changes in a revision with a diff editor
  duplicate  Create a new change with the same content as an existing one
  edit       Edit a commit in the working copy
  files      List files in a revision
  git        Commands for working with the underlying Git repo
  init       Create a new repo in the given directory
  interdiff  Compare the changes of two commits
  log        Show commit history
  merge      Merge work from multiple branches
  move       Move changes from one revision into another
  new        Create a new, empty change and edit it in the working copy
  obslog     Show how a change has evolved
  operation  Commands for working with the operation log [aliases: op]
  rebase     Move revisions to different parent(s)
  resolve    Resolve a conflicted file with an external merge tool
  restore    Restore paths from another revision
  show       Show commit description and changes in a revision
  sparse     Manage which paths from the working-copy commit are present in the working copy
  split      Split a revision in two
  squash     Move changes from a revision into its parent [aliases: amend]
  status     Show high-level repo status [aliases: st]
  util       Infrequently used commands such as for generating shell completions
  undo       Undo an operation (shortcut for `jj op undo`)
  unsquash   Move changes from a revision's parent into the revision [aliases: unamend]
  untrack    Stop tracking specified paths in the working copy
  version    Display version information
  workspace  Commands for working with workspaces
  help       Print this message or the help of the given subcommand(s)

Options:
  -h, --help
          Print help (see a summary with '-h')

  -V, --version
          Print version

Global Options:
  -R, --repository <REPOSITORY>
          Path to repository to operate on

          By default, Jujutsu searches for the closest .jj/ directory in an ancestor of the current working directory.

      --ignore-working-copy
          Don't snapshot the working copy, and don't update it

          By default, Jujutsu snapshots the working copy at the beginning of every command. The working copy is also updated at the end of the command, if the command modified the working-copy commit (`@`). If you want to avoid snapshotting the working and instead see a possibly stale working copy commit, you can use `--ignore-working-copy`. This may be useful e.g. in a command prompt, especially if you have another process that commits the working copy.

          Loading the repository is at a specific operation with `--at-operation` implies `--ignore-working-copy`.

      --at-operation <AT_OPERATION>
          Operation to load the repo at

          Operation to load the repo at. By default, Jujutsu loads the repo at the most recent operation. You can use `--at-op=<operation ID>` to see what the repo looked like at an earlier operation. For example `jj --at-op=<operation ID> st` will show you what `jj st` would have shown you when the given operation had just finished.

          Use `jj op log` to find the operation ID you want. Any unambiguous prefix of the operation ID is enough.

          When loading the repo at an earlier operation, the working copy will be ignored, as if `--ignore-working-copy` had been specified.

          It is possible to run mutating commands when loading the repo at an earlier operation. Doing that is equivalent to having run concurrent commands starting at the earlier operation. There's rarely a reason to do that, but it is possible.

          [default: @]
          [aliases: at-op]

  -v, --verbose
          Enable verbose logging

      --color <WHEN>
          When to colorize output (always, never, auto)

      --no-pager
          Disable the pager

      --config-toml <TOML>
          Additional configuration options

jujutsuリポジトリの初期化

まずはリポジトリを作成してみましょう。

適当なディレクトリを作成します。

mkdir jujutsu-playground

ディレクトリに移動して、初期化してみましょう。

> jj init
Error: The native backend is disallowed by default.
Hint: Did you mean to pass `--git`?
Set `ui.allow-init-native` to allow initializing a repo with the native backend.

失敗しました。

はい、そもそもデフォルトの状態ではjujutsuのinitコマンドを使用することはできません。

一応以下のコマンドでjujutsuのリポジトリを作成することができます。

jj init --config-toml ui.allow-init-native=true

このコマンドを実行すると、.jjというディレクトリが作成されます。

これがjujutsuリポジトリの根幹になります。

ただ、jujutsuリポジトリはまだ開発が追い付いていないようなので、ここは安定して使えるgitリポジトリを作成しましょう。

jj git init

実行すると.jjディレクトリが作成されます。

ディレクトリ名は違いますが、gitリポジトリになっています。

コードの追加

コードを追加してみましょう。

このディレクトリを適当にCargoパッケージとして初期化しましょう。

--vcs noneを使用して、バージョン管理システムの指定はnoneにしてあげましょう)

cargo init --vcs none

実行後、src/main.rsCargo.tomlが作成されます。

ついでにgiboでRustの.gitignoreも作っておきましょう。

gibo dump Rust > .gitignore

Gitの場合、これらのファイルをバージョン管理の対象とするときにはgit add --allによってステージングする必要がありますが、jujutsuは変更を即時反映するため、その作業はいりません。

ではファーストコミットをしてみます。

gitではgit commitでコミットの説明とコミット操作を同時に行っていましたが、jujutsuではdescでコミットの説明を書き、newでコミットを行うというように操作が分かれています。

# コミットの説明を書く
jj desc -m 'first commit'
# コミットを行う
jj new

今まではcommit操作の中でまとめて変更を書かなければいけませんでしたが、**jujutsuではコードを変更するたびにdescを行い、まとまったタイミングでnewしてコミットするといったやり方ができるようになります。**これは便利ですね。

また、Gitのようにcommitを使用することもできます。

jj commit

複数の変更を分割してコミットする

gitを使っていてよくある、複数のファイル追加を別々のコミットとして行うにはjj splitを利用します。

jj split

実行すると以下のような編集画面が立ち上がります。

ここから任意のファイルを選択することで、コミットが実行されます。

選択する前にjj descでコミットの説明を追記しておくのを忘れずに!

まとめ

私は普段Gitの操作にはtigというCUIを使っているんですが、これの使い勝手があまりにもよすぎるので、これと比較するとjujutsuへの乗り換えはまだ先になるかもなぁ…と思いました。

参考

Git に足りなかったもの|君のレポジトリを領域展開 - 次世代バージョン管理システム Jujutsu の世界