お久しぶりです。ナナオです。
今回は今注目を集めているコードのバージョン管理ツール「jujutsu」を触ってみて、実際Gitと何が違うのか?を検証してみようと思います。
ちなみに、私は普段git-flowを使用したブランチ運用をしており、主に使用しているコマンドはこれくらいです。
- init
- add
- branch
- commit
- checkout (swith)
- remote
- stash
- merge
- status
インストール
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.rs
とCargo.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への乗り換えはまだ先になるかもなぁ…と思いました。