fuzgit documentationfuzgit ドキュメント
fuzgit is a git CLI built around picking, searching and tracing with a fuzzy finder. The goal is to let you finish everyday git work without remembering branch names or commit hashes exactly: you narrow the list down and pick.
Every subcommand follows the same model —
build the candidate list → filter and pick it in the
fuzzy finder (with a preview) → run the git
operation. The fuzzy finder is
skim embedded as a
library, so no external fzf or sk binary
is needed.
- Package name:
fuzgit - Command (binary) name:
gz
fuzgit speaks English and Japanese, English being the default (see Language). Console excerpts on this page show the default English display.
fuzzy finder で「選ぶ」「探す」「辿る」ことを軸にした git 操作 CLI ツールです。
ブランチ名やコミットハッシュを正確に覚えていなくても、絞り込みと選択だけで日常的な
git 操作を完結できることを目指しています。すべてのサブコマンドが
候補一覧の取得 → fuzzy finder で絞り込み・選択(+プレビュー)→
git 操作の実行という同じ操作モデルに従います。fuzzy finder は
skim をライブラリとして組み込んでいるため、
外部の fzf / sk バイナリは不要です。
- パッケージ名:
fuzgit - 実行コマンド名(バイナリ名):
gz
Requirements前提条件 #
-
git must be installed on the system (required).
Write operations (
switch/cherry-pick/restore/add/stashand so on) and the coloured diffs used for previews are executed by shelling out to the systemgitcommand. Repository data is read with gix, but gix does not provide those write operations. Ifgitis not onPATH, fuzgit reports “git was not found. Install git and make sure it is on your PATH” and exits. -
Git 2.38 or newer is needed for the conflict prediction
of
gz merge(optional). The prediction usesgit merge-tree --write-tree. Older git rejects that option, so only the prediction is skipped and the merge still runs (the confirmation prompt says “Conflict prediction: skipped (`git merge-tree --write-tree` could not be run; the prediction needs Git 2.38 or later)”). It never stops with an error. No other feature has a minimum git version. - A stable Rust toolchain to build from source (Rust 1.85 or newer because the crate uses edition 2024; development is verified with 1.95.0).
-
システムに
gitがインストールされていること(必須)
書き込み系の操作(switch/cherry-pick/restore/add/stashなど)と プレビュー用の色付き差分生成は、システムのgitコマンドへ シェルアウトして実行します。リポジトリ情報の読み取りには gix を使いますが、gix は 上記の書き込み操作を提供していないためです。gitが PATH 上に 無い場合は「git コマンドが見つかりません」と表示して終了します。 -
gz mergeのコンフリクト予測には Git 2.38 以降が必要です(任意)
予測にはgit merge-tree --write-treeを使います。2.38 未満の git では このオプションが拒否されるため、予測の表示だけを省略して merge の実行は そのまま続けます(確認プロンプトに「コンフリクト予測: 省略しました」と 表示されます)。エラーで停止することはありません。これ以外の機能に git の 最低バージョン要件はありません。 - ビルドする場合は stable の Rust ツールチェイン(edition 2024 を使うため Rust 1.85 以降。開発時の確認は 1.95.0)
Installationインストール #
fuzgit is not published to crates.io, so clone the repository and install from the local checkout.
git clone https://github.com/hatohato25/fuzgit.git
cd fuzgit
cargo install --path .
This installs ~/.cargo/bin/gz (the package is
fuzgit, the command is gz).
To try it without installing:
cargo build --release
./target/release/gz --help
crates.io へは未公開のため、リポジトリを取得してローカルからインストールします。
git clone https://github.com/hatohato25/fuzgit.git
cd fuzgit
cargo install --path .
~/.cargo/bin/gz がインストールされます(パッケージ名は
fuzgit、コマンド名は gz)。
インストールせずに試す場合:
cargo build --release
./target/release/gz --help
Usage使い方 #
gz <subcommand> [options]
Running gz with no arguments, or
gz --help, lists the subcommands.
引数なしの gz および gz --help で
サブコマンド一覧を表示します。
An option gets a short form only when git itself spells it
the same way — gz restore -S
(git restore -S), gz fetch -p
(git fetch -p), gz sync -r
(git pull -r), gz branch delete -f
(git branch -f) and so on. fuzgit-specific options are
long-only, and a letter git already uses for something else is
never reused: gz tag --diff has no -d
because git tag -d deletes a tag.
オプションの短縮形は、git 本体に同じ意味の綴りがあるものだけに
付けています(gz restore -S =
git restore -S、gz fetch -p =
git fetch -p、gz sync -r =
git pull -r、gz branch delete -f =
git branch -f など)。fuzgit 固有のオプションは長い綴りだけとし、
git が別の意味で使っている文字は流用しません。gz tag --diff に
-d が無いのは、git tag -d がタグの削除だからです。
| Subcommandサブコマンド | What it does概要 | Selection選択 |
|---|---|---|
gz branch |
Pick a branch and switch to it (subcommands also create, delete and tidy up branches) ブランチを選んで切り替える(サブコマンドで作成・削除・整理も行う) | single / depends on subcommand 単一/サブコマンド次第 |
gz log |
Trace the commit history and print the full hash to stdout コミット履歴を辿り、フルハッシュを標準出力へ出す | single単一 |
gz cherry-pick |
Pick commits and cherry-pick them コミットを選んで cherry-pick する | multiple複数 |
gz restore |
Pick files to restore or unstage ファイルを選んで復元・アンステージする | multiple複数 |
gz add |
Pick unstaged and untracked files and stage them 未ステージ・未追跡ファイルを選んでステージする | multiple複数 |
gz stash <subcommand> |
Stash changes away, and search stashes to apply or drop them 変更を stash へ退避し、stash を検索して適用・破棄する | depends on subcommand サブコマンド次第 |
gz tag |
Pick a tag to print, switch to, or diff タグを選んで出力・切替・差分表示する | single単一 |
gz reflog |
Trace the HEAD reflog and recover lost commits HEAD の reflog を辿り、失われたコミットを取り出す | single単一 |
gz commit |
Pick changed files and commit only those 変更ファイルを選んで、選んだものだけをコミットする | multiple複数 |
gz fixup |
Pick the commit to amend and create a fixup commit 修正対象のコミットを選んで fixup コミットを作る | single単一 |
gz merge |
Pick the branch to merge (recovery menu while one is in progress) merge するブランチを選ぶ(進行中は復帰メニュー) | single単一 |
gz rebase |
Pick the base to rebase onto (recovery menu while one is in progress) rebase の base を選ぶ(進行中は復帰メニュー) | single単一 |
gz revert |
Pick the commits to undo and revert them 打ち消すコミットを選んで revert する | multiple複数 |
gz status |
List changed files and act on the ones you pick (two-step selection) 変更ファイルを一覧し、選んだファイルに操作を行う(2 段選択) | multiple → single 複数 → 単一 |
gz diff |
Pick what to compare and show the diff 比較対象を選んで差分を表示する | depends on modeモード次第 |
gz fetch |
Decide what to fetch and fetch it (--siblings also fetches the repositories next door; uses the network)
fetch の対象を決めて取得する(--siblings で隣のリポジトリも一括取得。ネットワークを使う)
|
single / multiple with --siblings
単一/--siblings は複数
|
gz pull |
Pick branches and bring them up to their upstream in one go (fast-forward only; uses the network) ブランチを選んで upstream へまとめて追随させる(fast-forward のみ。ネットワークを使う) | multiple複数 |
gz sync |
Sync the current branch with its upstream (uses the network) 現在ブランチを upstream と同期する(ネットワークを使う) | none選択なし |
gz worktree |
List and manage worktrees worktree を一覧・管理する | single単一 |
Language表示言語 #
Every piece of text fuzgit produces — messages, errors,
finder headers, confirmation prompts and --help
— is available in English and Japanese.
English is the default. To use Japanese:
git config --global fuzgit.lang ja # persistent (--local sets it per repository)
gz --lang ja branch # one-off, accepted by every subcommand
fuzgit が表示するすべての文言(メッセージ・エラー・finder のヘッダー・
確認プロンプト・--help)が日本語と英語に
対応しています。既定は英語です。日本語にするには次のように
指定します。
git config --global fuzgit.lang ja # 永続設定(--local ならリポジトリごと)
gz --lang ja branch # 単発の上書き。全サブコマンドで指定できる
| Priority優先 | Source取得元 | Meant for用途 |
|---|---|---|
| 1 | --lang <ja|en|auto> |
A one-off override. A global option, accepted by every subcommand; there is no short form. 単発の上書き。全サブコマンド共通のグローバルオプションで、短縮形はありません。 |
| 2 | FUZGIT_LANG |
Per shell or session. シェル・セッション単位の上書き。 |
| 3 | git config fuzgit.lang |
The persistent setting. system / global / local / worktree all apply exactly as they do for git itself. 永続設定。system / global / local / worktree の階層が git 本体と同じように効きます。 |
| 4 |
LC_ALL → LC_MESSAGES →
LANGUAGE → LANG
|
Read from the environment, in the POSIX and gettext order. 環境からの自動判定(POSIX / gettext と同じ順)。 |
| 5 | fallbackフォールバック | en |
-
Layers 1–3 are strict. They are explicit
instructions to fuzgit, so any value other than
ja,enorautostops with an error instead of quietly falling back. An empty value counts as “not set” and resolution moves to the next layer. If readingfuzgit.langfails altogether, fuzgit stops as well. -
Layer 4 is lenient. Locale variables describe
the environment rather than instruct fuzgit, so a value it
cannot interpret —
CandPOSIXincluded — is not an error; it simply means “not Japanese” and the fallback applies. -
automeans “skip the remaining explicit layers and read the environment”, wherever it appears in layers 1–3. -
There is no fuzgit configuration file. The
setting lives in git’s own
fuzgit.langkey, read in-process with gix — nogitprocess is started to resolve the language. -
The language resolves outside a repository too,
so
gz --helpand the “not a git repository” error are translated as well; system and global settings still apply there. One exception: afuzgit.langwritten under a conditional include (includeIf) in~/.gitconfigis not read when resolving outside a repository.
Two limits are worth knowing about.
-
Messages from git itself are not guaranteed to be
translated. fuzgit tells every git command it runs
which language to speak, but whether a catalog exists depends on
how git was built (NLS) and on the installed locale data. In
particular git upstream ships no Japanese
catalog, so git’s own output stays English even
when you pick
ja. Forcingenis the safe direction, because it only asks git for its original text. -
Text that clap prints on its own stays
English —
Usage:,Options:,Commands:and parser errors such aserror: unexpected argument. clap 4 has no localization hook. fuzgit’s own descriptions in--help, including the one for--lang, do switch.
Output that fuzgit parses is a separate matter: those git
invocations always run with LC_MESSAGES=C, whatever
display language was resolved, so parsing never depends on the
environment. See Debugging for how the two
kinds are told apart in the log.
-
層 1〜3 は厳格です。fuzgit への明示的な指定であるため、
ja/en/auto以外の値は 黙って既定へ倒さずエラーで停止します。空文字は「未設定」として扱い、 次の層へ進みます。fuzgit.langの読み取り自体に失敗した場合も 停止します。 -
層 4 は寛容です。ロケール環境変数は fuzgit への指示ではなく
環境の記述であるため、解釈できない値(
C/POSIXを 含む)はエラーにせず「日本語ではない」と判定してフォールバックへ進みます。 -
autoは層 1〜3 のどこに現れても「以降の明示指定を飛ばして 環境からの自動判定へ進む」という意味です。 -
fuzgit 独自の設定ファイルはありません。設定は git config の
fuzgit.langに置き、gix でプロセス内から読みます (言語の解決でgitプロセスは起動しません)。 -
言語はリポジトリの外でも解決できます。
gz --helpや「git リポジトリではありません」のエラーも 翻訳対象で、system / global の設定はそのまま効きます。ただし~/.gitconfigの条件付き include(includeIf)配下に 書いたfuzgit.langは、リポジトリ外での解決では読まれません。
以下の 2 点は制約として把握しておいてください。
-
git 本体のメッセージが翻訳されることは保証しません。
fuzgit は起動するすべての git へ言語を伝えますが、翻訳が存在するかは
git のビルド(NLS の有無)とロケールデータに依存します。とくに
git 本体には日本語カタログがありません。
jaを 選んでも git 自身の出力は英語のままです。enへの統一は git に原文を出させるだけなので、環境に依存せず成立します。 -
clap が自前で出す固定文言は英語のままです。
Usage:/Options:/Commands:とerror: unexpected argumentのようなパーサエラーが該当します (clap 4 に多言語化の機構がないため)。--langの説明を含め、--helpのうち fuzgit 自身の文言は切り替わります。
fuzgit がパースする git の出力は別扱いで、解決された表示言語に
関わらず常に LC_MESSAGES=C で実行します(実行環境によって
パースが壊れないようにするため)。ログ上での見分け方は
デバッグを参照してください。
gz branch — switch, create, delete and tidy up branches
gz branch — ブランチの切替・作成・削除・整理
#
gz branch # pick a local branch and run git switch (the classic behaviour)
gz branch --all # also list remote-tracking branches (origin/... and friends)
gz branch create <name> # pick the starting point and create a new branch
gz branch delete # pick branches and delete them
gz branch cleanup # delete every merged branch in one go
gz branch with no arguments and
gz branch --all are the branch switch, exactly as
before. create / delete /
cleanup are management operations added later, and
combining the switch flag (-a / --all)
with a management subcommand is rejected by clap, because it would
be ambiguous which operation was intended
(gz branch --all create x is an error).
Switching (no subcommand)
| Option | Description |
|---|---|
-a, --all | Also list remote-tracking branches |
- The current branch is marked with a leading
*, just likegit branch. - The preview shows the 50 most recent commits of the highlighted branch (
git log --oneline --decorate). -
Picking a remote-tracking branch (
origin/feature) runsgit switchwith the short name (feature), so git’s DWIM creates the tracking local branch.
gz branch create <name> — creating a branch
| Argument / option | Description |
|---|---|
<NAME> | Name of the branch to create (required positional argument) |
--switch | Switch to the branch after creating it |
-
What you pick in the fuzzy finder is the
starting point. Candidates are local branches,
remote-tracking branches and tags, each line prefixed with its
kind (
branch/tag), because a branch and a tag can share a name. -
It runs
git branch -- <name> <start point>. For an annotated tag the resolved ID is passed and git peels it to the commit. -
The branch name is a positional argument (skim
has no text input UI — see
Out of scope). Name validation is
left to git’s
check-ref-format; names starting with-are protected with--and then rejected by git. -
Without
--switchthe branch is only created, and the command to switch to it is printed to stderr.
gz branch delete — deleting branches
| Option | Description |
|---|---|
-f, --force | Delete branches that are not merged either (git branch -D) |
--into <BRANCH> | Branch used as the merged/unmerged baseline (defaults to HEAD) |
- Candidates are local branches except the current branch and branches checked out in another worktree (git refuses to delete either).
-
A candidate line is
<name> merged|unmerged <relative update time> tracking: <upstream>|no tracking branch. Only information that can be gathered for every branch at once is put on the line; details of the last commit are in the preview (git log --oneline). -
Tab selects several branches.
A confirmation prompt (
[y/N]) lists every target before anything runs. -
The default is
git branch -d(merged branches only). If even one unmerged branch is in the selection, fuzgit stops with a dedicated error before runninggit branch, so it never deletes part of the selection and then stops. -
Only
--forceswitches togit branch -D, and the confirmation prompt then warns about the unmerged branches.
gz branch cleanup — deleting merged branches in one go
| Option | Description |
|---|---|
--into <BRANCH> | Branch used as the merged baseline (defaults to HEAD) |
- Candidates are limited to merged branches, and all of them start out selected (use Tab to deselect).
-
After the confirmation prompt they are deleted with
git branch -d. There is no--force— handling unmerged branches is the job ofgz branch delete --force.
gz branch # ローカルブランチから選んで git switch(従来どおりの切替)
gz branch --all # リモート追跡ブランチ(origin/... 等)も候補に含める
gz branch create <name> # 作成元を選んで新しいブランチを作る
gz branch delete # ブランチを選んで削除する
gz branch cleanup # merged なブランチを一括で削除する
引数なしの gz branch と gz branch --all は
従来どおりのブランチ切替です。
create / delete / cleanup は
後から追加した管理操作で、切替用のフラグ(-a / --all)と
管理サブコマンドの併用は、どちらの操作を意図したのかが曖昧になるため clap の段階で
拒否されます(gz branch --all create x はエラー)。
切替(サブコマンドなし)
| オプション | 説明 |
|---|---|
-a, --all | リモート追跡ブランチも候補に含める |
- 現在のブランチは
git branchと同じく行頭の*で識別できます。 - プレビューには選択中ブランチの直近 50 件のコミットログ(
git log --oneline --decorate)を表示します。 -
リモート追跡ブランチ(
origin/feature)を選ぶと短縮名(feature)でgit switchするため、git の DWIM により追跡ローカルブランチが作成されます。
gz branch create <name> — ブランチの作成
| 引数・オプション | 説明 |
|---|---|
<NAME> | 作成するブランチ名(必須の位置引数) |
--switch | 作成後にそのブランチへ切り替える |
-
fuzzy finder で選ぶのは作成元です。候補はローカルブランチ・
リモート追跡ブランチ・タグで、行頭に種別(
branch/tag)が 付きます(同名のブランチとタグが共存できるため)。 -
実行するのは
git branch -- <name> <作成元>です。 annotated tag を選んだ場合は解決済みの ID を渡し、git が対象コミットまで peel します。 -
ブランチ名は位置引数です(skim にテキスト入力 UI が無いため。
スコープ外・非対応参照)。名前の妥当性検証は git の
check-ref-formatに委ねており、-始まりの名前は--で保護したうえで git が拒否します。 -
--switchを付けない場合は作成のみを行い、切り替えるためのコマンドを 標準エラーへ案内します。
gz branch delete — ブランチの削除
| オプション | 説明 |
|---|---|
-f, --force | merged でないブランチも削除する(git branch -D) |
--into <BRANCH> | merged 判定の基準ブランチ(既定は HEAD) |
- 候補はローカルブランチのうち、現在のブランチと、他の worktree で チェックアウト中のブランチを除いたものです(どちらも git が削除を許可しないため)。
-
候補行は
<名前> merged|unmerged <相対更新日時> 追跡: <upstream>|追跡なしです。 いずれも全件を一括取得できる情報に限っており、最終コミットの詳細はプレビュー (git log --oneline)で確認します。 -
Tab で複数選択できます。
実行前に確認プロンプト(
[y/N])で対象を全件列挙します。 -
既定は
git branch -d(merged のみ削除可)です。 unmerged が選択に 1 件でも含まれると、git branchを実行する前に 専用エラーで停止します(一部だけ削除して止まることはありません)。 -
--forceを指定したときだけgit branch -Dを使い、 確認プロンプトに unmerged である旨の警告を含めます。
gz branch cleanup — merged なブランチの一括削除
| オプション | 説明 |
|---|---|
--into <BRANCH> | merged 判定の基準ブランチ(既定は HEAD) |
- 候補を merged のブランチのみに絞り、全件を起動時から選択済みで 表示します(Tab で外せます)。
-
確認プロンプトを経て
git branch -dで一括削除します。--forceはありません(unmerged を扱うのはgz branch delete --forceの役目です)。
gz log — exploring the commit history
gz log — コミット履歴の探索
#
gz log # 1000 commits by default
gz log --limit 200 # limit how many commits are listed (-n also works)
git show "$(gz log)" # use the full hash of the picked commit directly
| Option | Default | Description |
|---|---|---|
-n, --limit <N> | 1000 | Maximum number of commits to list |
- Each candidate is one line,
<short hash> <date> <summary> (<author>), and that whole string is what you filter on. - The preview is
git show --color=always(commit details and diff). -
On confirmation only the full hash of the picked
commit goes to stdout, for pipes and copying. Messages
go to stderr, so
$(gz log)is safe.
gz log # 既定 1000 件を候補にする
gz log --limit 200 # 取得件数を制限する(-n でも可)
git show "$(gz log)" # 選んだコミットのフルハッシュをそのまま使う
| オプション | 既定値 | 説明 |
|---|---|---|
-n, --limit <N> | 1000 | 取得するコミットの最大件数 |
- 候補は
<短縮ハッシュ> <日付> <サマリ> (<作者>)の 1 行で、この文字列がそのまま絞り込み対象です。 - プレビューは
git show --color=always(コミットの詳細と差分)。 -
決定すると選択コミットのフルハッシュだけを標準出力へ出します
(パイプ・コピー用途)。メッセージ類は標準エラーへ出すため、
$(gz log)で 安全に受け取れます。
gz cherry-pick — picking commits to cherry-pick
gz cherry-pick — cherry-pick するコミットの選択
#
gz cherry-pick # commits from every branch
gz cherry-pick --branch feature # restrict to one branch
| Option | Description |
|---|---|
-b, --branch <BRANCH> | Target branch (without it, commits from all branches are listed) |
- Tab selects several commits. Whatever order you picked them in, they are always cherry-picked oldest first (history order).
- The candidate limit is 1000, the same as the default of
gz log --limit. -
On a conflict, git’s message is shown as-is and the exit
code is non-zero. Continue or abort with
git cherry-pick --continue/git cherry-pick --abort.
gz cherry-pick # 全ブランチのコミットを候補にする
gz cherry-pick --branch feature # 対象ブランチを指定する
| オプション | 説明 |
|---|---|
-b, --branch <BRANCH> | 対象ブランチ(未指定時は全ブランチのコミットを候補にする) |
- Tab で複数選択できます。選んだ順に関わらず、常に古い順(履歴順)に cherry-pick します。
- 候補件数の上限は
gz log --limitの既定値と同じ 1000 件です。 -
コンフリクト時は git のメッセージをそのまま表示して非ゼロ終了します。
続行・中止は
git cherry-pick --continue/git cherry-pick --abortで行ってください。
gz restore — picking files to restore or unstage
gz restore — 復元・アンステージするファイルの選択
#
gz restore # discard working tree changes (with confirmation)
gz restore --staged # unstage staged changes
gz restore --source HEAD~1 # overwrite with the content of a revision (with confirmation)
| Option | Description |
|---|---|
-s, --source <REV> | Revision to restore from; the file list of that commit becomes the candidate list |
-S, --staged | Unstage staged changes |
-
Tab selects several files. Candidates carry the same
status codes as
git status. The two status characters are left-aligned: a change that only exists in the working tree readsMwhere git writesM, and the column stays two characters wide so the paths still line up. They are coloured the way git colours them: green for the index (staged) column, red for the working-tree column, and red for both characters of an untracked file (??). Because of the left alignment, the colour is the only thing that tells a staged change from an unstaged one — where colour is unavailable (NO_COLOR, a pipe) the two look alike. - The preview is the diff of the file (with
--staged, the diff between HEAD and the index). -
Anything that rewrites the working tree shows a
confirmation prompt (
[y/N]) first. Unstaging with--stageddoes not damage the working tree, so it is not confirmed.
gz restore # 作業ツリーの変更を破棄する(確認あり)
gz restore --staged # ステージ済みの変更をアンステージする
gz restore --source HEAD~1 # 指定リビジョンの内容で上書きする(確認あり)
| オプション | 説明 |
|---|---|
-s, --source <REV> | 復元元のリビジョン。指定するとそのコミットのファイル一覧が候補になる |
-S, --staged | ステージ済みの変更をアンステージする |
-
Tab で複数選択できます。候補には
git statusと 同じ状態コードが付きます。状態コードの 2 文字は左詰めで表示します(作業ツリーだけの変更は git のMではなくM。列幅は 2 文字のままなのでパスの開始位置は揃います)。配色は git と同じで、index(staged)列は緑、作業ツリー列は赤、未追跡(??)は 2 文字とも赤です。左詰めにしたため、staged と unstaged の区別は色だけが担います(NO_COLORやパイプ経由など色の付かない環境では両者が同じ見た目になります)。 - プレビューは対象ファイルの差分(
--staged指定時は HEAD とインデックスの差分)。 -
作業ツリーを書き換える操作は実行前に確認プロンプト(
[y/N])を 表示します。--stagedによるアンステージは作業ツリーを 壊さないため確認しません。
gz add — picking files to stage
gz add — ステージするファイルの選択
#
gz add
-
Candidates are unstaged changes and untracked files (files that
are already staged with no remaining difference do not appear),
each line prefixed with the same status code as
git status. The two status characters are left-aligned: a change that only exists in the working tree readsMwhere git writesM, and the column stays two characters wide so the paths still line up. They are coloured the way git colours them: green for the index (staged) column, red for the working-tree column, and red for both characters of an untracked file (??). Because of the left alignment, the colour is the only thing that tells a staged change from an unstaged one — where colour is unavailable (NO_COLOR, a pipe) the two look alike. - Tab selects several files.
- The preview is the diff for tracked files, and the file content (up to the first 64 KiB) for untracked files.
-
候補は未ステージの変更と未追跡ファイル(既にステージ済みで差分の無いファイルは
出ません)で、行頭には
git statusと同じ状態コードが付きます。状態コードの 2 文字は左詰めで表示します(作業ツリーだけの変更は git のMではなくM。列幅は 2 文字のままなのでパスの開始位置は揃います)。配色は git と同じで、index(staged)列は緑、作業ツリー列は赤、未追跡(??)は 2 文字とも赤です。左詰めにしたため、staged と unstaged の区別は色だけが担います(NO_COLORやパイプ経由など色の付かない環境では両者が同じ見た目になります)。 - Tab で複数選択できます。
- プレビューは追跡ファイルは差分、未追跡ファイルはファイルの内容(先頭 64KiB まで)。
gz stash — creating, searching and restoring stashes
gz stash — stash の作成・検索・復元
#
push picks files in the working tree, while
apply / pop / drop pick an
existing stash. Because the thing being picked differs,
they are separate subcommands rather than flags. Bare
gz stash prints the subcommand help — it never
silently assumes one of them.
gz stash push # pick from the tracked changes and stash them
gz stash push -m "work in progress" # add a message
gz stash push -u # also list untracked files
gz stash apply # apply the picked stash (the stash stays)
gz stash pop # apply it and drop that stash
gz stash drop # discard the picked stash (with confirmation)
| Subcommand | Option | Description |
|---|---|---|
push | -m, --message <MESSAGE> | Message attached to the stash |
push | -u, --include-untracked | Also list untracked files (by default only tracked changes) |
apply / pop / drop | (none) | Pick one entry from the stash list |
-
pushsupports multi-select with Tab, and only the files you picked are stashed (the rest stay in the working tree). Staged changes are stashed too, so the preview is the diff against HEAD (git diff HEAD). -
Candidates for
apply/pop/droparestash@{n}: <message>, so you can filter by message. The preview isgit stash show -p --color=always. -
dropcannot be undone, so it shows a confirmation prompt ([y/N]) first.
push が選ぶのは作業ツリーの「ファイル」、apply /
pop / drop が選ぶのは既存の「stash」です。
選択対象が異なるため、フラグではなくサブコマンドで分けています。
引数なしの gz stash はサブコマンド一覧のヘルプを表示します
(どちらかへ暗黙に倒しません)。
gz stash push # 追跡済みの変更から選んで退避する
gz stash push -m "作業中" # メッセージを付ける
gz stash push -u # 未追跡ファイルも候補に含める
gz stash apply # 選んだ stash を適用する(stash は残る)
gz stash pop # 適用して、その stash を取り除く
gz stash drop # 選んだ stash を破棄する(確認あり)
| サブコマンド | オプション | 説明 |
|---|---|---|
push | -m, --message <MESSAGE> | stash に付けるメッセージ |
push | -u, --include-untracked | 未追跡ファイルも候補に含める(既定は追跡済みの変更のみ) |
apply / pop / drop | (なし) | stash 一覧から 1 件選ぶ |
-
pushは Tab で複数選択でき、選んだファイルだけが 退避されます(選ばなかった変更は作業ツリーに残ります)。ステージ済みの変更も 退避対象になるため、プレビューは HEAD との差分(git diff HEAD)です。 -
apply/pop/dropの候補はstash@{n}: <メッセージ>で、メッセージで絞り込めます。 プレビューはgit stash show -p --color=always。 dropは元に戻せないため、実行前に確認プロンプト([y/N])を表示します。
gz tag — picking a tag
gz tag — タグの選択
#
gz tag # print the tag name to stdout (default)
gz tag --switch # switch to the picked tag as a detached HEAD
gz tag --diff # show the diff between the picked tag and HEAD
| Option | Description |
|---|---|
--switch | Switch to the picked tag as a detached HEAD |
--diff | Show the diff between the picked tag and HEAD |
--switchand--diffcannot be combined.- Annotated tags show their tag message on the candidate line and in the preview.
- By default only the tag name is printed to stdout.
gz tag # タグ名を標準出力へ出す(既定)
gz tag --switch # 選んだタグへ detached HEAD で切り替える
gz tag --diff # 選んだタグと HEAD の差分を表示する
| オプション | 説明 |
|---|---|
--switch | 選択したタグへ detached HEAD で切り替える |
--diff | 選択したタグと HEAD の差分を表示する |
--switchと--diffは同時に指定できません。- annotated tag は候補行にタグメッセージを併記し、プレビューにもタグメッセージを含めます。
- 既定ではタグ名だけを標準出力へ出します。
gz reflog — investigating deleted branches
gz reflog — 削除済みブランチの調査
#
gz reflog # print the commit hash of the picked entry to stdout
gz reflog --restore recovered # create a new branch `recovered` from the picked commit
| Option | Description |
|---|---|
--restore <NAME> | Create a new branch with the given name from the picked commit |
- Candidates are
<short hash> HEAD@{n}: <message>, so you can filter on messages such ascheckout: moving from .... -
By default only the full hash goes to stdout.
The result of
--restoregoes to stderr, leaving stdout free for pipes.
gz reflog # 選んだエントリのコミットハッシュを標準出力へ出す
gz reflog --restore recovered # 選んだコミットから新規ブランチ `recovered` を作成する
| オプション | 説明 |
|---|---|
--restore <NAME> | 選択したコミットから指定名の新規ブランチを作成する |
- 候補は
<短縮ハッシュ> HEAD@{n}: <メッセージ>で、checkout: moving from ...等のメッセージで絞り込めます。 -
既定ではフルハッシュだけを標準出力へ出します。
--restoreの 実行結果は標準エラーへ出るため、標準出力はパイプ用途のまま空けてあります。
gz commit — picking the files to commit
gz commit — コミットするファイルの選択
#
gz commit # commit only the files you picked (message via the editor)
gz commit -m "fix authentication" # give the message directly (no editor)
| Option | Description |
|---|---|
-m, --message <MESSAGE> | Commit message (without it, git opens the editor) |
-
Candidates are staged, unstaged and untracked changes in
one single list, each line prefixed with the same
status code as
git status. The two status characters are left-aligned: a change that only exists in the working tree readsMwhere git writesM, and the column stays two characters wide so the paths still line up. They are coloured the way git colours them: green for the index (staged) column, red for the working-tree column, and red for both characters of an untracked file (??). Because of the left alignment, the colour is the only thing that tells a staged change from an unstaged one — where colour is unavailable (NO_COLOR, a pipe) the two look alike. - Files with staged changes start out selected. Tab deselects them, and a deselected entry never comes back when you keep typing a filter.
-
It runs a path-limited commit,
git commit -- <paths>.... Therefore changes you did not pick are not committed even if they were staged; they simply stay staged. - Untracked files you picked are
git added first, because a path-limited commit cannot target them. -
The preview is the diff against HEAD
(
git diff --color=always HEAD -- <path>; file content for untracked files). A path-limited commit records the working tree content, so the preview shows the difference from HEAD rather than from the index. - With no changes at all it prints “There are no candidates to select from” and exits.
A note about your editor
Without -m, entering the message is left to
git commit (that is, EDITOR /
GIT_EDITOR / core.editor).
If a GUI editor such as VS Code is configured without
waiting for the window to close, the editor exits immediately, git
decides the message is empty, and the commit is aborted with
Aborting commit due to empty commit message.
(Plain git commit behaves the same way.) Add the option
that makes it wait:
git config --global core.editor "code --wait" # example for VS Code
Passing -m avoids the problem entirely because no
editor is started. When a commit fails, fuzgit prints the above as
a hint on stderr.
gz commit # 選んだファイルだけをコミットする(メッセージはエディタで入力)
gz commit -m "認証を修正する" # メッセージを直接指定する(エディタを起動しない)
| オプション | 説明 |
|---|---|
-m, --message <MESSAGE> | コミットメッセージ(省略時は git がエディタを起動する) |
-
候補はステージ済み・未ステージ・未追跡の変更を1 つの一覧にしたもので、
行頭には
git statusと同じ状態コードが付きます。状態コードの 2 文字は左詰めで表示します(作業ツリーだけの変更は git のMではなくM。列幅は 2 文字のままなのでパスの開始位置は揃います)。配色は git と同じで、index(staged)列は緑、作業ツリー列は赤、未追跡(??)は 2 文字とも赤です。左詰めにしたため、staged と unstaged の区別は色だけが担います(NO_COLORやパイプ経由など色の付かない環境では両者が同じ見た目になります)。 - ステージ済みの変更があるファイルは起動時から選択済みです。 Tab で選択を外せます(外した選択が絞り込みのたびに復活することはありません)。
-
実行するのは
git commit -- <paths>...のパス指定コミットです。 そのため選ばなかった変更はステージ済みであってもコミットされず、 ステージ状態のまま残ります。 - 選んだ未追跡ファイルは、パス指定コミットの対象にできないため先に
git addします。 -
プレビューは HEAD との差分(
git diff --color=always HEAD -- <path>。 未追跡ファイルは内容)。パス指定コミットが記録するのは作業ツリーの内容であるため、 index との差分ではなく HEAD との差分を表示します。 - 変更が 1 件も無い場合は「選択できる候補がありません」と表示して終了します。
エディタの設定に関する注意
-m を省略した場合、コミットメッセージの入力は git commit
(= EDITOR / GIT_EDITOR / core.editor)に
委ねられます。VS Code のような GUI エディタを終了待ちなしで設定していると、
エディタが即座に終了するため git はメッセージが空だと判断し、
Aborting commit due to empty commit message. でコミットが
中止されます(これは素の git commit でも同じです)。
終了を待つオプションを付けてください。
git config --global core.editor "code --wait" # VS Code の例
-m でメッセージを指定すればエディタを起動しないため、この問題を
回避できます。コミットが失敗したときは、上記の内容をヒントとして標準エラーへ表示します。
gz fixup — picking the target of a fixup commit
gz fixup — fixup コミットの対象選択
#
gz fixup # git commit --fixup=<picked commit>
gz fixup --squash # git commit --squash=<picked commit>
| Option | Description |
|---|---|
--squash | Create a squash commit (messages are combined) instead of a fixup commit |
- What gets committed is the staged changes. With nothing staged, fuzgit prints “There are no staged changes. A fixup commit needs staged changes, so stage them with `gz add` and run this command again” and exits before starting the finder.
- Candidates are commits reachable from HEAD (1000 by default, shared with
gz log --limit). The preview isgit show --color=always. -
Afterwards the steps to fold the commit into history are printed
to stderr. The rebase is not run automatically
— rewriting history stays an explicit user action.
If the picked commit is the very first one (no parent),Hint: run the following to fold the new commit into the history: git rebase -i --autosquash <full hash of the picked commit>^<hash>^cannot be resolved, so the starting point becomes--rootand the reason is printed with it. --squashmakes git open the editor to append the message body (--fixupdoes not).
gz fixup # git commit --fixup=<選んだコミット>
gz fixup --squash # git commit --squash=<選んだコミット>
| オプション | 説明 |
|---|---|
--squash | fixup ではなく squash コミット(メッセージを結合する)を作成する |
- コミット対象はステージ済みの変更です。ステージ済みの変更が無い場合は、 finder を起動する前に「ステージ済みの変更がありません」と表示して終了します。
-
候補は HEAD からのコミット(既定 1000 件、
gz log --limitの既定値と共通)。 プレビューはgit show --color=always。 -
実行後、履歴へ取り込むための手順を標準エラーへ表示します。
rebase は自動実行しません(履歴改変はユーザーの明示操作に委ねます)。
選んだコミットが最初のコミット(親が無い)の場合はヒント: 作成したコミットを履歴へ取り込むには次を実行してください。 git rebase -i --autosquash <選んだコミットのフルハッシュ>^<hash>^を 解決できないため、起点が--rootになります(理由も併記します)。 --squashは git がメッセージ本文の追記のためにエディタを起動します(--fixupは起動しません)。
gz merge — picking the branch to merge
gz merge — merge するブランチの選択
#
gz merge # a normal merge (fast-forwards when it can)
gz merge --no-ff # always create a merge commit
gz merge --squash # only apply the result to the working tree and index, without committing
gz merge --ff-only # merge only when it can fast-forward
| Option | Description |
|---|---|
--no-ff | Create a merge commit even when a fast-forward is possible |
--squash | Apply the merge result to the working tree and index without committing |
--ff-only | Merge only when a fast-forward is possible |
- The three options are mutually exclusive (combining them is rejected before the selection starts).
- The merge destination is fixed to the current position (
HEAD); candidates are local and remote-tracking branches excluding the current branch. - The preview is the commits that would be pulled in (
git log --oneline HEAD..<candidate>, up to 50). -
A confirmation prompt (
[y/N]) is shown first, listing how many commits will be merged, the exact command that will run, and the conflict prediction. -
The conflict prediction is a dry run of
git merge-tree --write-tree(Git 2.38 or newer required). When it cannot be produced (older git, for example) the prompt says “Conflict prediction: skipped” and the merge still runs. “Could not predict” is never treated as “will not conflict”. -
On a conflict, git’s message is shown as-is and the exit code
is non-zero. Resolve it with the
recovery menu (run
gz mergeagain) or with plain git.
gz merge # 通常の merge(fast-forward できる場合は fast-forward)
gz merge --no-ff # fast-forward できる場合でもマージコミットを作る
gz merge --squash # 結果を作業ツリー・index へ反映するだけでコミットしない
gz merge --ff-only # fast-forward できる場合のみ merge する
| オプション | 説明 |
|---|---|
--no-ff | fast-forward できる場合でもマージコミットを作成する |
--squash | マージ結果を作業ツリー・index へ反映するだけでコミットしない |
--ff-only | fast-forward できる場合のみ merge する |
- 3 つのオプションは相互排他です(同時に指定すると選択を始める前に拒否されます)。
- merge 先は現在の位置(
HEAD)に固定で、候補は現在のブランチを除くローカルブランチとリモート追跡ブランチです。 - プレビューは取り込まれるコミット(
git log --oneline HEAD..<候補>、最大 50 件)。 -
実行前に確認プロンプト(
[y/N])を表示します。 取り込まれるコミット数・実際に実行するコマンド・コンフリクト予測を提示します。 -
コンフリクト予測は
git merge-tree --write-treeのドライラン (Git 2.38 以降が必要)です。予測できない場合(2.38 未満など)は 「省略しました」と表示し、merge の実行は継続します。「予測できなかった」を 「コンフリクトしない」として扱うことはありません。 -
コンフリクトした場合は git のメッセージがそのまま表示され、非ゼロ終了します。
解決は復帰メニュー(
gz mergeを再実行)または 素の git で行います。
gz rebase — picking the rebase base
gz rebase — rebase の base の選択
#
gz rebase # pick the base and run git rebase <base>
- Candidates are local and remote-tracking branches excluding the current branch (tags and arbitrary commits are not offered).
- The preview is the commits that would be replayed (
git log --oneline <candidate>..HEAD, up to 50). -
Because this rewrites history, a confirmation prompt
(
[y/N]) is shown first, stating how many commits will be replayed and that their hashes will change. - On a conflict, git’s message is shown as-is and the exit code is non-zero.
gz rebase # base を選んで git rebase <base>
- 候補は現在のブランチを除くローカルブランチとリモート追跡ブランチです(tag や任意コミットは候補に含めません)。
- プレビューは replay されるコミット(
git log --oneline <候補>..HEAD、最大 50 件)。 -
履歴改変操作のため、実行前に確認プロンプト(
[y/N])を表示します。 replay されるコミット数と、コミットハッシュが変わることを提示します。 - コンフリクトした場合は git のメッセージがそのまま表示され、非ゼロ終了します。
The recovery menu for conflicts (gz merge / gz rebase / gz sync / gz pull)
コンフリクト時の復帰メニュー(gz merge / gz rebase / gz sync / gz pull)
#
Running gz merge / gz rebase /
gz sync / gz pull while a merge or rebase
is in progress shows a recovery menu instead of the
usual flow. Its contents are decided by the operation that
is in progress (running gz merge during a
rebase shows the rebase menu).
| In progress | Menu entries |
|---|---|
| merge | Inspect the conflicted files and mark them resolved / resume the merge (git merge --continue) / abort the merge (git merge --abort) |
| rebase | Inspect the conflicted files and mark them resolved / resume the rebase (git rebase --continue) / skip the current commit (git rebase --skip) / abort the rebase (git rebase --abort) |
-
Whichever entry is highlighted, the preview shows the current
state (
git status --short --branch), so you can tell unresolved (UU) from resolved (M) on the spot. -
Choosing “inspect the conflicted files and mark them
resolved” lists the unmerged files. The preview shows
the diff including conflict markers
(
<<<<<<<and friends), and the files you pick with Tab aregit added (staged as resolved). Editing the files themselves is up to your own editor — fuzgit never launches one. - If you choose that entry with no unresolved files left, it tells you that you can resume with continue and exits.
- Aborting loses the resolutions made so far, so a confirmation prompt (
[y/N]) is shown first. - continue / skip run with inherited stdio, so git opens the editor when a commit message is needed.
- There is no recovery menu for cherry-pick or revert (that is left to git’s own
--continue/--abortguidance).
merge / rebase が進行中の状態で gz merge / gz rebase /
gz sync / gz pull を実行すると、通常のフローではなく
復帰メニューが表示されます。メニューの内容は
進行中の操作の種類で決まります(rebase 進行中に
gz merge を実行しても rebase のメニューが出ます)。
| 進行中 | メニュー項目 |
|---|---|
| merge | コンフリクトファイルを確認して解決済みにする / merge を再開する(git merge --continue)/ merge を中止する(git merge --abort) |
| rebase | コンフリクトファイルを確認して解決済みにする / rebase を再開する(git rebase --continue)/ 現在のコミットを飛ばす(git rebase --skip)/ rebase を中止する(git rebase --abort) |
-
どの項目を選んでいても、プレビューには現在の状態
(
git status --short --branch)が出ます。未解決(UU等)と 解決済み(M)の区別をその場で確認できます。 -
「コンフリクトファイルを確認して解決済みにする」を選ぶと、コンフリクト中(unmerged)の
ファイル一覧が出ます。プレビューにはコンフリクトマーカー
(
<<<<<<<等)を含む差分が表示され、 Tab で選んだファイルをgit add(=解決済みとして stage)します。 ファイルの編集そのものは各自のエディタで行ってください(fuzgit はエディタを起動しません)。 - 未解決のファイルが 1 件も無い状態でこの項目を選んだ場合は、continue で再開できる旨を表示して終了します。
- 中止(abort)はここまでの解決内容が失われるため、実行前に確認プロンプト(
[y/N])を表示します。 - continue / skip は継承 stdio で実行するため、コミットメッセージの入力が必要な場合は git がエディタを起動します。
- cherry-pick / revert には復帰メニューを用意していません(git の
--continue/--abortの案内に委ねます)。
gz revert — picking the commits to undo
gz revert — 打ち消すコミットの選択
#
gz revert # revert the picked commits (message reviewed in the editor)
gz revert --no-edit # commit with git's default message, without opening the editor
| Option | Description |
|---|---|
--no-edit | Commit with git’s default message without opening the editor |
- Candidates are commits reachable from HEAD (1000 by default, shared with
gz log --limit). The preview isgit show --color=always. -
Tab selects several commits. Whatever
order you picked them in, they are reverted
newest first (undoing an old commit first tends
to clash with the later changes stacked on top of it —
exactly the opposite of
gz cherry-pick). - Picking several commits opens the editor once per commit unless you pass
--no-edit. -
If the selection contains a merge commit (two or more
parents), fuzgit stops before running
git revert. Reverting a merge commit requires-m <parent-number>, and picking the mainline is not something a fuzzy finder adds value to, so it is unsupported. On stopping, a ready-to-rungit revert -m 1 <full hash>is offered (merge commits are never silently removed from the candidates). -
On a conflict, git’s message is shown as-is and the exit
code is non-zero. Continue or abort with
git revert --continue/git revert --abort.
gz revert # 選んだコミットを revert する(メッセージはエディタで確認)
gz revert --no-edit # エディタを起動せず git の既定メッセージのままコミットする
| オプション | 説明 |
|---|---|
--no-edit | エディタを起動せず、git の既定メッセージのままコミットする |
- 候補は HEAD からのコミット(既定 1000 件、
gz log --limitの既定値と共通)。プレビューはgit show --color=always。 -
Tab で複数選択できます。選んだ順に関わらず、常に新しい順に
revert します(古いコミットを先に打ち消すと、その上に積まれた後続の変更と衝突しやすいため。
gz cherry-pickの古い順とはちょうど逆になります)。 - 複数件を選ぶと
--no-editを付けない限りエディタが件数分だけ開きます。 -
選択にマージコミット(親が 2 つ以上)が含まれる場合は、
git revertを 実行する前に停止します。マージコミットの revert には-m <parent-number>の指定が必要ですが、mainline の選択は「選ぶ」価値が 乗らないため非対応です。停止時にはgit revert -m 1 <フルハッシュ>の形で そのまま実行できるコマンドを提示します(暗黙に候補から除外することはしません)。 -
コンフリクトした場合は git のメッセージをそのまま表示して非ゼロ終了します。
続行・中止は
git revert --continue/git revert --abortで行ってください。
gz status — the state dashboard (two-step selection)
gz status — 状態ダッシュボード(2 段選択)
#
gz status
There are no options. It is a two-step flow: pick the files, then pick the action.
1. File selection (multi-select)
-
Candidates are staged, unstaged and untracked changes in one list
(the same candidate generation as
gz commit), each line prefixed with the same status code asgit status. The two status characters are left-aligned: a change that only exists in the working tree readsMwhere git writesM, and the column stays two characters wide so the paths still line up. They are coloured the way git colours them: green for the index (staged) column, red for the working-tree column, and red for both characters of an untracked file (??). Because of the left alignment, the colour is the only thing that tells a staged change from an unstaged one — where colour is unavailable (NO_COLOR, a pipe) the two look alike. -
The header summarises the current state in one line:
Without an upstream the whole ahead/behind block is omitted (on a detached HEAD,main | ahead 2 / behind 1 | staged 2 / unstaged 2 / untracked 1 / stash 1detached HEADis shown instead of the branch name). ahead/behind is computed from the local remote-tracking ref, so it uses no network. -
The preview is split into per-state sections:
staged(git diff --cached) when there are staged changes andunstaged(git diff) when there are unstaged ones; sections that do not apply do not run git at all. Untracked files show their content as-is.
2. Action menu (single select)
| Entry | What it runs |
|---|---|
| Stage the selected files (git add) | Same as gz add |
| Discard the changes of the selected files (git restore) | Same as gz restore (with a confirmation prompt) |
| Stash the selected files (git stash push) | Same as gz stash push (--include-untracked is added when untracked files were picked) |
| Commit the selected files (git commit) | Same as gz commit (untracked files are git added first; message via the editor) |
| Print the paths of the selected files to stdout | For pipes. Nothing but the paths is printed |
- Each action is literally the same implementation as the corresponding command, so its safeguards (restore’s confirmation prompt, commit’s pre-
addof untracked files) keep working. - The menu preview shows the current state (
git status --short --branch). - Every message except “print the paths to stdout” goes to stderr, so stdout stays free for pipes.
-
With no changes at all it is not an error: it exits with
code 0 (checking that the tree is clean is a legitimate
use of status). In that case the header-equivalent information
goes to stderr.
$ gz status There are no changes (the working tree is clean) main | staged 0 / unstaged 0 / untracked 0 / stash 0
オプションはありません。ファイルを選ぶ → アクションを選ぶの 2 段構成です。
1. ファイル選択(複数選択)
-
候補はステージ済み・未ステージ・未追跡の変更を 1 つの一覧にしたもの
(
gz commitと同じ候補生成)で、行頭にはgit statusと 同じ状態コードが付きます。状態コードの 2 文字は左詰めで表示します(作業ツリーだけの変更は git のMではなくM。列幅は 2 文字のままなのでパスの開始位置は揃います)。配色は git と同じで、index(staged)列は緑、作業ツリー列は赤、未追跡(??)は 2 文字とも赤です。左詰めにしたため、staged と unstaged の区別は色だけが担います(NO_COLORやパイプ経由など色の付かない環境では両者が同じ見た目になります)。 -
ヘッダーに現在の状態を 1 行で表示します。
upstream が設定されていない場合、ahead / behind の区画ごと省略します (detached HEAD ではブランチ名の代わりにmain | ahead 2 / behind 1 | staged 2 / unstaged 2 / untracked 1 / stash 1detached HEADと表示します)。 ahead / behind はローカルのリモート追跡参照から算出するため ネットワークを使いません。 -
プレビューは状態別のセクションに分かれます。ステージ済みの変更があれば
staged(git diff --cached)、未ステージの変更があればunstaged(git diff)を表示し、該当しないセクションは git を実行しません。未追跡ファイルは内容をそのまま表示します。
2. アクションメニュー(単一選択)
| 項目 | 実行内容 |
|---|---|
| 選択したファイルをステージする (git add) | gz add と同じ |
| 選択したファイルの変更を破棄する (git restore) | gz restore と同じ(確認プロンプトあり) |
| 選択したファイルを stash へ退避する (git stash push) | gz stash push と同じ(未追跡を選んだ場合は --include-untracked が付く) |
| 選択したファイルをコミットする (git commit) | gz commit と同じ(未追跡ファイルは事前に git add、メッセージはエディタ) |
| 選択したファイルのパスを標準出力へ出力する | パイプ用途。パス以外は出力しない |
- 各アクションの実体は対応する既存コマンドと同じ実装であり、安全策 (restore の確認プロンプト、commit の未追跡ファイルの事前 add など)も そのまま働きます。
- メニューのプレビューには現在の状態(
git status --short --branch)を表示します。 - 「パスを標準出力へ出力する」以外のメッセージ類はすべて標準エラーへ出すため、標準出力はパイプ用途に空いています。
-
変更が 1 件も無い場合はエラーにせず、終了コード 0 で終わります
(クリーンな状態の確認も status の用途のため)。この場合はヘッダー相当の情報を
標準エラーへ出します。
$ gz status 変更はありません(作業ツリーはクリーンです) main | staged 0 / unstaged 0 / untracked 0 / stash 0
gz diff — pick what to compare and show the diff
gz diff — 比較対象を選んで差分表示
#
gz diff # unstaged changes (same as git diff)
gz diff --staged # staged changes (same as git diff --staged)
gz diff --head # HEAD against the working tree (including staged changes)
gz diff --upstream # HEAD against the upstream (the remote-tracking ref)
gz diff --branch # pick two branches and compare them
gz diff --commit # pick two commits and compare them
| Option | Description |
|---|---|
--staged | Target the staged changes (same as git diff --staged) |
--head | Compare HEAD with the working tree (including staged changes) |
--upstream | Compare HEAD with the upstream |
--branch | Pick two branches and compare them |
--commit | Pick two commits and compare them |
- The comparison modes are mutually exclusive. The flag names follow git’s own vocabulary.
-
--branch/--commitopen the fuzzy finder twice, for the left then the right side. The header tells you which one you are picking (1/2 branch to compare from, then2/2 branch to compare to). Candidates and previews are shared withgz branchandgz log. - Once the range is fixed, the list of changed files appears so you can narrow it down with Tab. The header shows the chosen range, and the preview is the coloured diff limited to the highlighted file.
-
On confirmation it runs
git diff <range> -- <pathspec>...with inherited stdio (pager and colour are left to git). Revision comparisons are passed as two arguments,git diff <a> <b>, not as<a>..<b>. -
--upstreamstops with a dedicated error when there is no upstream or on a detached HEAD. The right-hand side is the local remote-tracking ref (refs/remotes/<remote>/<branch>), so it uses no network. Rungz fetchfirst if you want to compare against the latest state. -
When the range contains no changed files it is not an
error: it exits with code 0.
$ gz diff There is no difference (Unstaged changes: index and work tree)
gz diff # 未ステージの変更(git diff と同じ)
gz diff --staged # ステージ済みの変更(git diff --staged と同じ)
gz diff --head # HEAD と作業ツリー(ステージ済みの変更も含む)
gz diff --upstream # HEAD と upstream(リモート追跡参照)
gz diff --branch # ブランチを 2 回選んで比較する
gz diff --commit # コミットを 2 回選んで比較する
| オプション | 説明 |
|---|---|
--staged | ステージ済みの変更を対象にする(git diff --staged と同じ) |
--head | HEAD と作業ツリーを比較する(ステージ済みの変更を含む) |
--upstream | HEAD と upstream を比較する |
--branch | ブランチを 2 回選択して比較する |
--commit | コミットを 2 回選択して比較する |
- 比較モードは相互排他です。フラグ名は git 本体の語彙に合わせています。
-
--branch/--commitは比較元・比較先の順に fuzzy finder を 2 回起動します。どちらを選んでいるかはヘッダー (1/2 比較元のブランチ/2/2 比較先のブランチ)で分かります。 候補・プレビューはそれぞれgz branch/gz logと共通です。 - 比較範囲が確定すると変更ファイル一覧が出るので、Tab で表示したいファイルを 絞り込めます。ヘッダーには確定した比較範囲を表示し、プレビューは選択中ファイルに 限定した色付き差分です。
-
決定すると
git diff <範囲> -- <pathspec>...を継承 stdio で 実行します(ページャ・色は git に委ねます)。リビジョン同士の比較は<a>..<b>ではなくgit diff <a> <b>の 2 引数で渡します。 -
--upstreamは upstream が設定されていない場合・detached HEAD の場合に 専用エラーで停止します。比較先はローカルのリモート追跡参照 (refs/remotes/<remote>/<branch>)であり、 ネットワークを使いません。最新の状態と比べたい場合は先にgz fetchを実行してください。 -
比較範囲に変更ファイルが 1 件も無い場合はエラーにせず、終了コード 0 で終わります。
$ gz diff 差分はありません(未ステージの変更: index と作業ツリー)
gz fetch — deciding what to fetch
gz fetch — fetch 対象の取得
#
gz fetch # decide what (which remote) to fetch and run git fetch
gz fetch --prune # also clean up tracking refs for branches deleted on the remote
gz fetch --siblings # pick repositories sitting next to this one and fetch them all
| Option | Description |
|---|---|
-p, --prune | Delete tracking refs for branches deleted on the remote (git fetch --prune) |
-s, --siblings | Also target repositories sitting at the same level as the current one (multi-select) |
The point of this command is not “pick a remote” but “decide what to fetch”. The fuzzy finder only opens when there is actually a choice.
Default (the current repository)
-
The finder only opens when there is more than one
remote. Candidates are the registered remote names plus
a fixed entry, all remotes, which
runs
git fetch --all. -
With exactly one remote the finder does not open and the
fetch runs immediately, because choosing between the only
remote and “all remotes” would contact the same place
either way. So that you can still tell what was contacted, one
line naming the target is printed to stderr before running
(
git fetchcan print nothing at all when there are no updates).$ gz fetch Fetching from the remote `origin` (only one remote is registered, so the selection was skipped) - The preview only shows local information (two sections: the remote URL and the known remote-tracking branches). A remote that has never been fetched has no tracking refs, so that section is omitted entirely. Not using the network in previews is a design rule — see Network operations.
- With no remotes registered at all it suggests
git remote addand exits.
--siblings — fetching the repositories next door
Every other fuzgit command touches only the current
repository. --siblings is the single
exception: only when the flag is given, it scans
the parent directory of the current worktree root, one level
deep only (no recursion) and offers the directories that
contain a .git.
$ gz fetch --siblings
The current repository is preselected. Tab: toggle the selection / Enter: fetch | 1 excluded (no remote / bare)
>> mike origin/main
alpha origin/main
zulu origin/main
-
A candidate line is
<directory name> <remote>/<current branch>, with one such pair per remote. Repositories whose HEAD does not point at a branch have no branch to pair and show<directory name> <remotes> detached HEAD. Directory names vary in length, so each column is padded to the widest value in the list and the column to its right starts at the same place on every line. Information that would need onegitprocess per repository (ahead/behind, for example) is kept out of the list and moved to the preview, to keep the first paint fast. - The current repository starts selected (Tab deselects it). The others start unselected.
-
The preview is local information only (the URL of
each remote, and the tracking state of each local branch via
git for-each-ref refs/heads). It runs with--no-optional-locksso it never takes a lock in somebody else’s repository.
The working tree state (── origin ── git@github.com:example/big-repo.git ── Branch tracking status ── develop → origin/develop [ahead 2] * main → origin/main [behind 4]git status) is deliberately not shown:git statuswalks the whole working tree (refreshing the index) before printing anything, which can take seconds per preview in a repository with many files and would stall every cursor move. The ahead/behind you need in order to decide about a fetch is in the tracking state above. - Repositories with no remote registered, and bare repositories, cannot be fetched, so they are excluded — and the number excluded is shown in the header (they are never dropped silently).
- Linked worktrees of the same repository sitting next door are deduplicated into one entry (so the same repository is not contacted twice). Symlinked directories are not followed.
-
When the only target is the current repository the finder
does not open; the reason is printed in one line and the
fetch runs.
$ gz fetch --siblings The current repository is the only target, so the selection was skipped [1/1] only 1 succeeded / 0 failed -
What runs in each repository is
git fetch [--prune] --all. They run one at a time, serially, in candidate order (never in parallel). Before each one,[<n>/<total>] <directory name>is printed to stderr; without that line you could not tell which repository the update table belongs to, since git writes it to stderr as well. -
A failing repository does not stop the run; the
rest still execute and a summary of successes, failures and the
names of the failed repositories is printed at the end. If even
one fails, the exit code is 1 (the reason was
already shown by git, so fuzgit does not repeat it).
$ gz fetch --siblings [1/3] mike [2/3] alpha [3/3] zulu fatal: '/path/to/does-not-exist.git' does not appear to be a git repository fatal: Could not read from remote repository. 2 succeeded / 1 failed (failed: zulu) error: Fetching failed for some repositories - If launching
gititself fails (git not installed, for example) the run stops there, because that is an environment problem rather than a per-repository failure. -
Combined with
--prune, the flag applies to every selected repository. The finder header says so:--prune: applies to every selected repository. -
If there is no repository that can be fetched at all, it stops
with a dedicated error. The same happens when the current
repository is bare, or when the parent directory of the worktree
root cannot be determined (a repository directly at the
filesystem root, for instance) — the scan range itself
cannot be decided. In none of these cases does it
silently fall back to just the current
repository, so the range you asked for and the place it
contacts can never diverge.
$ gz fetch --siblings error: There is no repository to fetch (a repository without a remote and a bare repository are not offered)
Common to both
git fetchruns with inherited stdio, so the list of updated refs, authentication prompts and progress output are git’s own.- Network and authentication failures are shown with git’s message as-is and exit non-zero (fuzgit adds no timeout and no retry).
gz fetch # fetch 対象(リモート)を決めて git fetch する
gz fetch --prune # リモートで削除されたブランチの追跡参照も掃除する
gz fetch --siblings # 隣に並ぶリポジトリを選んでまとめて fetch する
| オプション | 説明 |
|---|---|
-p, --prune | リモートで削除されたブランチの追跡参照を削除する(git fetch --prune) |
-s, --siblings | 現在のリポジトリと同じ階層に並ぶリポジトリも対象に含める(複数選択) |
このコマンドの主機能は「リモートを選ぶ」ことではなく 「fetch 対象の決定」です。 選択の余地がある場合にだけ fuzzy finder を起動します。
既定(現在のリポジトリ)
-
リモートが複数ある場合だけ finder を起動します。候補は登録済みの
リモート名に、固定候補「すべてのリモート」を加えたものです。「すべてのリモート」を
選ぶと
git fetch --allを実行します。 -
リモートが 1 つだけの場合は finder を起動せず、そのまま fetch します。
唯一のリモートと「すべてのリモート」の 2 択は、どちらを選んでも通信先が同じためです。
何に対して通信したのかが分かるよう、実行前に対象を 1 行だけ標準エラーへ示します
(
git fetchは更新が無ければ何も出力しないことがあるため)。$ gz fetch リモート `origin` から取得します(登録されているリモートが 1 つのため、選択を省略しました) - プレビューはローカル情報だけを表示します (「リモート URL」と「既知のリモート追跡ブランチ」の 2 セクション)。一度も fetch して いないリモートは追跡参照が無いため、そのセクションごと省略されます。 プレビューでネットワークを使わないのは設計上の原則です (ネットワーク操作について参照)。
- リモートが 1 つも登録されていない場合は
git remote addを促して終了します。
--siblings — 隣のリポジトリもまとめて取得
fuzgit の他のコマンドは現在のリポジトリだけを操作します。
--siblings はその唯一の例外で、フラグを明示したときに限り、
現在のリポジトリのワークツリー root の親ディレクトリ直下のみを走査して
(再帰しません)、.git を持つディレクトリを候補にします。
$ gz fetch --siblings
現在のリポジトリを選択済みにしています。Tab: 選択の切替 / Enter: 取得 | 除外 1 件(リモート未登録 / bare)
>> mike origin/main
alpha origin/main
zulu origin/main
-
候補行は
ディレクトリ名 リモート/現在のブランチです(リモートが複数あれば その数だけ並べます)。HEAD がブランチを指していないリポジトリは対にするブランチが無いため、ディレクトリ名 リモート detached HEADと表示します。 ディレクトリ名の長さはまちまちであるため、各列は候補一覧の中で最も長いものに合わせて 空白で埋め、右の列の開始位置をすべての行で揃えます。ahead / behind のように 1 リポジトリあたり git の起動が必要な情報は候補一覧に載せず、プレビューへ回しています (初期表示を速く保つため)。 - 現在のリポジトリは起動時から選択済みです(Tab で外せます)。他のリポジトリは未選択です。
-
プレビューはローカル情報だけです(リモートごとの URL と、
git for-each-ref refs/headsによるローカルブランチごとの追跡状況)。 他人のリポジトリでロックを取らないよう--no-optional-locksを付けて 実行します。
作業ツリーの状態(── origin ── git@github.com:example/big-repo.git ── ブランチの追跡状況 ── develop → origin/develop [ahead 2] * main → origin/main [behind 4]git status)は表示しません。git statusは 状態を出す前に作業ツリー全体を走査する(インデックスを refresh する)ため、 ファイル数の多いリポジトリではプレビュー 1 件の生成に数秒掛かることがあり、 カーソルを動かすたびに待たされるためです。fetch の判断に必要な ahead / behind は 上記の追跡状況で分かります。 - リモートが 1 つも登録されていないリポジトリと bare リポジトリは fetch できないため 候補から除外し、除外した件数をヘッダーに示します(黙って消しません)。
- 同じリポジトリの linked worktree が隣に並んでいる場合は1 件に重複排除します (同じリポジトリへ二重に通信しないため)。シンボリックリンクのディレクトリは辿りません。
-
対象が現在のリポジトリ 1 件だけの場合は finder を起動せず、
理由を 1 行示してそのまま実行します。
$ gz fetch --siblings 対象が現在のリポジトリ 1 件のため、選択を省略しました [1/1] only 成功 1 件 / 失敗 0 件 -
実行するのは各リポジトリでの
git fetch [--prune] --allです。 候補一覧の順序で 1 件ずつ直列に実行します(並列にしません)。 実行前に[<何番目>/<全体>] <ディレクトリ名>を標準エラーへ 表示します。git fetchの更新表も標準エラーに出るため、この 1 行が無いと どのリポジトリの出力なのか読み取れなくなります。 -
途中のリポジトリが失敗しても中断せず残りを実行し、最後に成功件数・
失敗件数と失敗したリポジトリ名を集計表示します。1 件でも失敗した場合は
終了コード 1 で終わります(失敗理由は git のメッセージがその場で
表示済みのため、fuzgit は再掲しません)。
$ gz fetch --siblings [1/3] mike [2/3] alpha [3/3] zulu fatal: '/path/to/does-not-exist.git' does not appear to be a git repository fatal: Could not read from remote repository. 成功 2 件 / 失敗 1 件(失敗: zulu) エラー: 一部のリポジトリで取得に失敗しました -
gitの起動そのものに失敗した場合(git 未インストール等)は、 その場で中断します。環境の問題でありリポジトリごとの失敗ではないためです。 -
--pruneと併用した場合は選択したすべてのリポジトリに適用されます。 その旨は finder のヘッダーに--prune: 選択したすべてのリポジトリに適用として表示します。 -
fetch できるリポジトリが 1 件も無い場合は専用エラーで停止します。また、現在のリポジトリが
bare の場合とワークツリー root の親ディレクトリを取得できない場合(リポジトリが
ファイルシステムの root 直下にある等)は、走査範囲そのものを決められないため専用エラーで
停止します。いずれも暗黙に現在のリポジトリだけへ倒すことはしません
(指定した範囲と通信先が食い違わないようにするため)。
$ gz fetch --siblings エラー: fetch できるリポジトリがありません(リモートが登録されていないリポジトリと bare リポジトリは対象になりません)
共通
git fetchは継承 stdio で実行するため、更新された参照の一覧・認証プロンプト・進捗表示は git のものがそのまま出ます。- ネットワーク・認証の失敗は git のメッセージをそのまま表示して非ゼロ終了します(fuzgit 側でのタイムアウト・リトライは行いません)。
gz pull — bringing several branches up to date
gz pull — 複数ブランチの一括取り込み
#
gz pull # pick the branches and fast-forward them onto their upstream
There are no options: no integration flags
(--rebase / --merge), no
--prune, and no positional branch name.
The only thing you pick is which branches should follow their upstream. The targets are several local branches of the current repository; you never pick a remote × branch combination, because the destination is fixed to each branch’s own upstream.
-
Integration is fixed to fast-forward only.
“Roll back to the state before the pull if a conflict
happens” is satisfied not by a rollback routine but
by never performing an operation that can break
anything. A fast-forward does not recreate existing
commits, and git refuses without changing anything
when it cannot fast-forward, when the change would clash with the
working tree, or when the branch is in use by another worktree.
A failure therefore leaves the pre-pull state intact and there is
nothing to roll back. (
git merge --abortcannot always reconstruct the original state when there are uncommitted changes, andgit reset --harddiscards uncommitted changes, so neither is used.) -
Candidates are local branches that have an upstream whose
branch.<name>.remoteis a registered remote name. Branches without an upstream, with an unregistered remote, or checked out in another worktree have no determinable destination, so they are excluded — and the number excluded is shown in the header (never dropped silently). -
The current branch is put first, marked with a leading
*(as ingz branch), and starts selected (Tab deselects it). On a detached HEAD there is simply no current branch, and the other branches are offered as usual (unlikegz sync, this is not an error).$ gz pull The current branch is preselected. Tab: toggle the selection / Enter: integrate with a fast-forward only | 2 excluded (no upstream / remote not registered / in use by another worktree) >> * main → origin/main feature-a → origin/feature-a -
A candidate line is
<mark><branch> → <short upstream name>. ahead / behind is not shown. At candidate generation time all that is known is the difference against the tracking refs from the last fetch, which does not match how much is about to be fetched and integrated (showing it would give the false impression of “not behind”; the actual amount appears in git’s own update table at run time). -
The preview is headed
── Commits not integrated yet (as of the last fetch) ──and shows the commits between the branch and its locally stored tracking ref (git log --oneline <branch>..<tracking ref>). The heading states that the information is as of the last fetch: the preview uses no network (see Network operations). -
With only one candidate the finder does not open;
the target and the reason are printed in one line and the run
starts.
$ gz pull Integrating `main` (there is only one candidate, so the selection was skipped) [1/1] main 1 succeeded / 0 failed -
With no candidates at all it stops and explains how to set an
upstream (
git push -u <remote> <branch>/git branch --set-upstream-to=<remote>/<branch>). -
Execution starts with
git fetch <remote>once per remote that the selected upstreams belong to (never once per branch). If one remote fails to fetch, every branch whose upstream lives on that remote is recorded as failed and skipped, while branches on other remotes continue — so nothing is ever integrated implicitly from a stale tracking ref. -
Integration then happens one branch at a time, serially,
in candidate order (never in parallel). Before each one,
[<n>/<total>] <branch>is printed to stderr (same format asgz fetch --siblings), because git’s update tables and rejection reasons also go to stderr. -
The currently checked out branch is integrated with
git merge --ff-only <tracking ref>(the working tree and index have to be updated), while every other branch usesgit fetch . <tracking ref>:refs/heads/<branch>(updating only the ref, never touching the working tree). The latter refspec deliberately omits the forcing+: with it, non-fast-forward updates would go through and commits that exist only on that branch would be lost. -
A failing branch does not stop the run; the rest
still execute and successes, failures and the failed branch names
are summarised at the end. If even one fails the exit code is
1 (git already printed the reason, so fuzgit does
not repeat it). Only when at least one branch could not
fast-forward is a one-line pointer to the next step added.
It only points at it —$ gz pull [1/4] main [2/4] alpha [3/4] diverged [4/4] zeta 3 succeeded / 1 failed (failed: diverged) A branch that could not fast-forward can be integrated with `gz sync --rebase` or `gz sync --merge` after switching to it error: Integrating failed for some branchesgz syncis never started automatically. How history is integrated (rebase or merge) stays an explicit user choice. - If launching
gititself fails (git not installed, for example) the run stops there, because that is an environment problem rather than a per-branch failure. -
There is no
[y/N]confirmation prompt. Making a multi-selection and pressing Enter is already an explicit decision, and a fast-forward loses neither existing commits nor working tree changes (the same judgement asgz fetch --siblings). - Run while a merge or rebase is in progress, it shows the recovery menu instead of the branch selection (same as
gz sync).
gz pull vs gz sync
| Aspect | gz pull | gz sync |
|---|---|---|
| Target | Several local branches that you pick | The current branch only (fixed to its upstream) |
| Integration | Fast-forward only (fixed) | Selectable with --rebase / --merge (default: fast-forward only) |
| Selection UI | Multi-select of branches | None |
| Confirmation prompt | No | Yes |
Use gz pull to bring several branches along at
once, and gz sync to integrate a single branch with a
method of your choice. A branch that gz pull
could not fast-forward is integrated by switching to it and running
gz sync --rebase / gz sync --merge.
gz pull # 取り込むブランチを選んで、upstream へ fast-forward で追随させる
オプションはありません。取り込み方式のフラグ(--rebase /
--merge)も --prune もブランチ名の位置引数も受け付けません。
選ばせるのは「どのブランチを upstream へ追随させるか」だけです。 対象は現在のリポジトリの複数のローカルブランチで、リモート × ブランチの組み合わせは 選ばせません(追随先は各ブランチの upstream に固定です)。
-
取り込みは fast-forward のみに固定です。「コンフリクトが起きたら
pull 前の状態に戻す」ことをロールバック処理ではなく、壊し得る操作を
行わないことで満たすためです。fast-forward は既存のコミットを作り直さず、
fast-forward できない場合・作業ツリーの変更と衝突する場合・他の worktree で
使用中の場合はいずれも git が何も変更せずに拒否します。そのため
失敗しても取り込み前の状態がそのまま残り、巻き戻す対象がありません
(
git merge --abortは未コミットの変更があると元の状態を再構成できない ことがあり、git reset --hardは未コミットの変更を破棄するため、 いずれも使いません)。 -
候補は upstream が設定され、その
branch.<name>.remoteが 登録済みのリモート名であるローカルブランチです。upstream が無いもの・ リモートが登録されていないもの・他の worktree でチェックアウト中のものは 取り込み先を決められないため候補から除外し、除外した件数をヘッダーに 示します(黙って消しません)。 -
現在のブランチは一覧の先頭に置き、行頭を
*(gz branchと同じ)でマークして、起動時から選択済みにします (Tab で外せます)。detached HEAD の場合は現在のブランチが無いだけで、 他のブランチは通常どおり候補になります(gz syncと 違いエラーにはしません)。$ gz pull 現在のブランチを選択済みにしています。Tab: 選択の切替 / Enter: fast-forward のみで取り込み | 除外 2 件(upstream 未設定 / リモート未登録 / 他の worktree で使用中) >> * main → origin/main feature-a → origin/feature-a -
候補行は
<マーク><ブランチ名> → <upstream の短縮名>です。 ahead / behind は表示しません。候補生成の時点で分かるのは前回の fetch までに取得済みの追跡参照との差であり、これから fetch して取り込む本数とは 一致しないためです(「遅れていない」という誤った印象を与えないため。取り込み量は 実行時に git 自身が出す更新表で分かります)。 -
プレビューは
── 未取り込みのコミット(前回の fetch 時点) ──の見出しを 付けて、ローカルに保存済みの追跡参照との差分コミット (git log --oneline <ブランチ>..<追跡参照>)を表示します。 それが前回の fetch 時点の情報であることを見出しで示しており、 プレビューではネットワークを使いません(ネットワーク操作について参照)。 -
候補が 1 件だけの場合は finder を起動せず、対象と省略の理由を
1 行示してそのまま実行します。
$ gz pull `main` を取り込みます(候補が 1 件のため、選択を省略しました) [1/1] main 成功 1 件 / 失敗 0 件 -
候補が 1 件も無い場合は、upstream の設定方法(
git push -u <remote> <branch>/git branch --set-upstream-to=<remote>/<branch>)を案内して停止します。 -
実行はまず、選択したブランチの upstream が属するリモートごとに 1 回だけ
git fetch <remote>します(ブランチごとに通信しません)。 あるリモートの取得に失敗した場合は、そのリモートを upstream に持つブランチをすべて 失敗として記録して飛ばし、他のリモートのブランチは続行します(古い追跡参照のまま 暗黙に取り込まないためです)。 -
取り込みは候補一覧の順序で 1 ブランチずつ直列に実行します
(並列にしません)。実行前に
[<何番目>/<全体>] <ブランチ名>を 標準エラーへ表示します(gz fetch --siblingsと同形式)。git 自身の更新表や 拒否の理由も標準エラーに出るため、この 1 行が無いとどのブランチの出力なのか 読み取れなくなります。 -
現在チェックアウト中のブランチは
git merge --ff-only <追跡参照>(作業ツリーと index を 更新する必要があるため)、それ以外のブランチはgit fetch . <追跡参照>:refs/heads/<ブランチ>(参照だけを更新し作業ツリーに触れない)で取り込みます。後者の refspec に強制更新の+は付けません。付けると非 fast-forward の更新が通り、 そのブランチにしか無いコミットを失わせるためです。 -
途中のブランチが失敗しても中断せず残りを実行し、最後に成功件数・
失敗件数と失敗したブランチ名を集計表示します。1 件でも失敗した場合は
終了コード 1 で終わります(失敗理由は git のメッセージがその場で
表示済みのため、fuzgit は再掲しません)。fast-forward できなかったブランチが
1 件以上あるときだけ、次の手段を 1 行案内します。
案内するだけで、$ gz pull [1/4] main [2/4] alpha [3/4] diverged [4/4] zeta 成功 3 件 / 失敗 1 件(失敗: diverged) fast-forward できなかったブランチは、そのブランチへ切り替えてから `gz sync --rebase` または `gz sync --merge` で取り込めます エラー: 一部のブランチで取り込みに失敗しましたgz syncを自動起動することはありません。 履歴の統合方法(rebase か merge か)はユーザーの明示指定に限ります。 -
gitの起動そのものに失敗した場合(git 未インストール等)は、 その場で中断します。環境の問題でありブランチごとの失敗ではないためです。 -
実行前の
[y/N]確認プロンプトはありません。 複数選択して Enter を押すこと自体が明示的な決定であり、fast-forward は 既存のコミットも作業ツリーの変更も失わせないためです (gz fetch --siblingsと同じ判断)。 -
merge / rebase が進行中の状態で実行した場合は、ブランチ選択ではなく
復帰メニューが表示されます(
gz syncと同じ)。
gz sync との使い分け
| 観点 | gz pull | gz sync |
|---|---|---|
| 対象 | 選んだ複数のローカルブランチ | 現在のブランチ 1 本(upstream 固定) |
| 取り込み方式 | fast-forward のみ(固定) | --rebase / --merge で選べる(既定は fast-forward のみ) |
| 選択 UI | ブランチの複数選択 | なし |
| 確認プロンプト | なし | あり |
まとめて追随させたいときは gz pull、方式を選んで 1 本だけ
取り込みたいときは gz sync です。gz pull で
fast-forward できなかったブランチは、そのブランチへ切り替えてから
gz sync --rebase / gz sync --merge で取り込みます。
gz sync — syncing with the upstream
gz sync — upstream との同期
#
gz sync # fetch, then fast-forward (default)
gz sync --rebase # fetch, then rebase onto the upstream (rewrites history)
gz sync --merge # fetch, then merge the upstream
| Option | Description |
|---|---|
-r, --rebase | Integrate by rebasing onto the upstream (rewrites history) |
--merge | Integrate by merging the upstream |
-
The target is fixed to the upstream of the current
branch. The fuzzy finder never opens, because there is
nothing to pick. (To integrate from an arbitrary remote or branch,
use
gz fetchfollowed bygz merge/gz rebase.) -
With no upstream, or on a detached HEAD, it stops with a dedicated
error before running
git fetch. The same happens — before any network access — when the upstream’sbranch.<name>.remoteis not a registered remote name. - The flow is
git fetch <remote>→ recompute ahead/behind (now that the tracking ref is updated) → confirmation prompt → integrate. - When behind is 0 it reports that you are up to date and exits with code 0.
-
The default is fast-forward only
(
git merge --ff-only). When it cannot fast-forward (diverged), git’sfatal: Not possible to fast-forward, aborting.is shown as-is and the command stops — it never silently falls back to merge or rebase. State the method explicitly with--rebase/--merge(the two are mutually exclusive). -
A confirmation prompt (
[y/N]) is shown before integrating, listing how many commits will come in and the exact command; with--rebaseit also states that history will be rewritten. - Run while a merge or rebase is in progress, it shows the recovery menu.
-
There is no
--prune. Deleting tracking refs is an explicit operation, done withgz fetch --prune, not a side effect of syncing.
gz sync # fetch → fast-forward(既定)
gz sync --rebase # fetch → upstream の上へ rebase(履歴改変)
gz sync --merge # fetch → upstream を merge
| オプション | 説明 |
|---|---|
-r, --rebase | upstream の上へ rebase して取り込む(履歴改変) |
--merge | upstream を merge して取り込む |
-
対象は現在ブランチの upstream に固定です。fuzzy finder は
起動しません(選ぶ対象が無いため。任意のリモート・ブランチから取り込みたい場合は
gz fetchのあとにgz merge/gz rebaseを使ってください)。 -
upstream が設定されていない場合・detached HEAD の場合は、
git fetchを実行する前に専用エラーで停止します。 upstream のbranch.<name>.remoteが登録済みのリモート名でない場合も 同様に、ネットワークへ出る前に停止します。 -
処理の流れは
git fetch <remote>→(追跡参照が更新された状態で) ahead / behind の再計算 → 確認プロンプト → 取り込みの実行です。 - behind が 0 の場合は「最新です」と表示して終了コード 0 で終わります。
-
既定は fast-forward のみ(
git merge --ff-only)です。 fast-forward できない(diverged)場合は git のfatal: Not possible to fast-forward, aborting.をそのまま表示して停止し、 暗黙に merge / rebase へ倒すことはありません。取り込み方法は--rebase/--mergeで明示してください(2 つは相互排他)。 -
取り込みの実行前に確認プロンプト(
[y/N])を表示します。 取り込まれるコミット数と実際に実行するコマンドを提示し、--rebaseの場合は 履歴改変になる旨も併記します。 - merge / rebase が進行中の状態で実行した場合は、復帰メニューが表示されます。
-
--pruneはありません。追跡参照の削除はgz fetch --pruneとして 明示的に行う操作であり、同期のついでには行いません。
gz worktree — listing and managing worktrees
gz worktree — worktree の一覧・管理
#
gz worktree # pick from the list and print the path to stdout
cd "$(gz worktree)" # shell integration (move to the picked worktree)
gz worktree add <path> # pick a branch and create a new worktree
gz worktree remove # pick a worktree and remove it (with confirmation)
gz worktree prune # tidy up bookkeeping for worktrees whose directory is gone (with confirmation)
No arguments (list, then print the path)
- A candidate line is
<path> main|linked <branch|detached|bare>[ locked][ prunable]. - The preview shows the commit log of the highlighted worktree’s HEAD (bare worktrees and worktrees without a single commit get no preview).
- On confirmation only the path of the picked worktree goes to stdout; messages go to stderr.
Note (known behaviour): if you redirect stdout to a file, skim’s drawing escapes end up in that file too (
gz worktree > out.txtandgz log > log.txtbehave the same). With pipes and command substitution ($(gz worktree)) the drawing goes to the terminal, socd "$(gz worktree)"works as expected.
gz worktree add <path>
| Argument | Description |
|---|---|
<PATH> | Path of the worktree to create (required positional argument) |
- What you pick in the fuzzy finder is the branch to check out. Candidates are limited to local branches not in use by another worktree (git cannot check out the same branch in two worktrees at once).
- It runs
git worktree add -- <path> <branch>. Directory names are never suggested automatically. - For a path starting with
-, writegz worktree add -- -dashy(that--is clap’s; fuzgit adds its own--when calling git).
gz worktree remove
- Candidates are linked worktrees only — the main worktree is not offered (git does not allow removing it).
- A confirmation prompt (
[y/N]) is shown first. - Locked worktrees and worktrees with uncommitted changes fail with git’s message as-is and a non-zero exit code (
--forceis not offered).
gz worktree prune
- It first runs
git worktree prune --dry-run --verboseand puts the worktrees that would be pruned, with the reason, into the confirmation prompt.git worktree pruneruns only if you approve. - With nothing to prune it reports so and exits with code 0.
gz worktree # 一覧から選んでパスを標準出力へ出す
cd "$(gz worktree)" # シェル連携(選んだ worktree へ移動する)
gz worktree add <path> # ブランチを選んで新しい worktree を作る
gz worktree remove # worktree を選んで削除する(確認あり)
gz worktree prune # 実体を失った worktree の管理情報を整理する(確認あり)
引数なし(一覧 → パス出力)
- 候補行は
<パス> main|linked <ブランチ|detached|bare>[ locked][ prunable]です。 - プレビューには選択中 worktree の HEAD のコミットログを表示します(bare とコミットが 1 件も無い worktree はプレビューを出しません)。
- 決定すると選んだ worktree のパスだけを標準出力へ出します。メッセージ類は標準エラーです。
注意(既知の挙動): 標準出力をファイルへリダイレクトすると、 skim の描画エスケープもそのファイルへ混ざります (
gz worktree > out.txt/gz log > log.txtのいずれも同じ)。 パイプ・コマンド置換($(gz worktree))では描画は端末側へ出るため、cd "$(gz worktree)"は期待どおり動作します。
gz worktree add <path>
| 引数 | 説明 |
|---|---|
<PATH> | 作成する worktree のパス(必須の位置引数) |
- fuzzy finder で選ぶのはチェックアウトするブランチです。候補は 他の worktree で使用中でないローカルブランチに限ります (git は同じブランチを複数の worktree で同時にチェックアウトできないため)。
- 実行するのは
git worktree add -- <path> <branch>です。ディレクトリ名の自動提案は行いません。 -
-で始まるパスを指定する場合はgz worktree add -- -dashyのように 書きます(clap 側の--であり、fuzgit は git へ渡す際にも別途--で保護します)。
gz worktree remove
- 候補は linked worktree のみで、main worktree は候補に含めません(git が削除を許可しないため)。
- 実行前に確認プロンプト(
[y/N])を表示します。 - locked な worktree・未コミット変更を含む worktree は、git のエラーをそのまま表示して非ゼロ終了します(
--forceは提供していません)。
gz worktree prune
-
先に
git worktree prune --dry-run --verboseを実行し、整理される worktree と 理由を確認プロンプトに提示します。承認された場合のみgit worktree pruneを 実行します。 - 対象が 1 件も無い場合は「整理する worktree はありません」と表示して終了コード 0 で終わります。
Network operationsネットワーク操作について #
-
The only commands that use the network are
gz fetch,gz pullandgz sync. Every other command works purely from local repository data (pushing is left to plaingit push). -
Candidate generation and previews never use the
network. This is a design rule. A preview is regenerated
every time the highlighted entry changes, so a network round trip
there (latency, timeouts, authentication prompts) would block the
display. Accordingly the
gz fetchpreview is limited to local data (git remote get-url/git for-each-ref refs/remotes/<remote>) and never runsgit fetch --dry-runinside a preview; the list of updated refs is printed bygit fetchitself when it runs. Thegz pullpreview (commits not yet integrated) likewise comes from reading locally stored tracking refs and is therefore as of the last fetch. -
The only thing
gz pullsends over the network is thegit fetch <remote>per remote, run after the targets are fixed. Branches sharing an upstream remote are handled together, so there is one round trip per remote and never one per branch. Updating a branch that is not checked out (git fetch . <tracking ref>:refs/heads/<branch>) fetches from the repository itself and never goes out to the network. -
The ahead/behind in
gz statusand the right-hand side ofgz diff --upstreamboth come from reading local remote-tracking refs. Rungz fetchfirst if you want to compare against the latest state. -
Authentication is left to git.
git fetch/git pushrun with inherited stdio, so credential entry, credential helpers and progress output are all git’s own. fuzgit performs no timeouts, no retries and no direct socket handling whatsoever. -
gz fetch --siblingsandgz pullrun the selected targets one at a time, serially (never in parallel). git itself also fetches multiple remotes sequentially by default (seeman git-fetch). Running them in parallel would interleave the inherited stdio, and with several SSH passphrase or credential helper prompts running at once you could not tell which remote you were typing into. Ctrl-C during a run is not handled specially: the SIGINT delivered to the foreground process group terminates fuzgit along with it (the remaining targets are not run). -
Without
--siblings, neighbouring repositories are not even offered as candidates. To prevent a mere change of directory from firing traffic at many repositories, the scan origin is always derived from the current repository and cannot be given as a path.
-
ネットワークを使うのは
gz fetchとgz pullとgz syncだけです。ほかのコマンドはすべてローカルのリポジトリ情報だけで 動作します(push は素のgit pushに委ねます)。 -
候補一覧の生成とプレビューではネットワークを使いません。
これは設計上の原則です。プレビューは選択項目が変わるたびに生成されるため、
そこでネットワーク往復(遅延・タイムアウト・認証プロンプト)が発生すると描画が
ブロックされてしまいます。したがって
gz fetchのプレビューは ローカル情報(git remote get-url/git for-each-ref refs/remotes/<remote>)に限定しており、git fetch --dry-runをプレビュー内で実行することはしません。 更新される参照の一覧はgit fetch自身が実行時に表示します。gz pullのプレビュー(未取り込みのコミット)も同様に、ローカルに 保存済みの追跡参照を読んだ結果であり、前回の fetch 時点の情報です。 -
gz pullが通信するのは、対象を確定したあとに実行する リモートごとのgit fetch <remote>だけです。 同じリモートを upstream に持つブランチをまとめて扱うため、通信は 1 リモートにつき 1 回で、ブランチごとには通信しません。チェックアウトしていないブランチの更新 (git fetch . <追跡参照>:refs/heads/<ブランチ>)は取得元が 自分自身のリポジトリであり、ネットワークへは出ません。 -
gz statusの ahead / behind とgz diff --upstreamの比較先は、いずれもローカルのリモート追跡参照を 読んだ結果です。最新の状態と比べたい場合は先にgz fetchを実行してください。 -
認証は git に委ねます。
git fetch/git pushは継承 stdio で実行するため、認証情報の入力・credential helper・ 進捗表示はすべて git のものがそのまま動きます。fuzgit 側でのタイムアウト・リトライ・ ソケットの直接操作は一切行いません。 -
gz fetch --siblingsとgz pullは選択した対象を 1 件ずつ直列に実行します(並列にしません)。git 自身も複数リモートの fetch を 既定で逐次実行します(man git-fetch)。並列にすると継承 stdio の出力が混ざるうえ、 SSH パスフレーズや credential helper のプロンプトが同時に複数走るとどのリモートへ 入力しているのか判別できなくなるためです。実行中の Ctrl-C は独自に処理せず、 前面プロセスグループへ届いた SIGINT で fuzgit ごと終了します(残りは実行されません)。 -
--siblingsを指定しない限り、隣のリポジトリは候補にすら なりません。ディレクトリを移動しただけで多数のリポジトリへ通信が飛ぶことを 防ぐため、探索の起点は常に現在のリポジトリから導出し、パスで指定することもできません。
Key bindingsキー操作 #
The fuzzy finder uses skim’s default key bindings as they are.
| Key | Action |
|---|---|
| Typing | Filter incrementally |
| ↑ / ↓, Ctrl-p / Ctrl-n, Ctrl-k / Ctrl-j | Move between candidates |
| Tab / Shift-Tab | Toggle the selection of a candidate (multi-select mode only) |
| Enter | Confirm |
| Shift-↑ / Shift-↓ | Scroll the preview |
| Esc / Ctrl-C | Abort |
-
Multi-select is available in
cherry-pick/restore/add/stash push/commit/revert/status(file selection) /diff(file selection) /branch delete/branch cleanup/fetch --siblings/pull, and in the “inspect the conflicted files and mark them resolved” entry of the recovery menu. Pressing Enter without selecting anything with Tab targets the candidate under the cursor. -
Entries that start out selected:
gz commit(staged files),gz branch cleanup(every merged branch),gz fetch --siblings(the current repository) andgz pull(the current branch). All of them can be deselected with Tab. -
The selection is always reordered to follow the candidate list
before it is handed to git (the order skim returns is the order you
picked, which is not necessarily the list order). Commands where
the order matters each get their own direction:
gz cherry-pickoldest first,gz revertnewest first. - Aborting with Esc / Ctrl-C performs no git operation at all and exits with code 130.
fuzzy finder は skim の既定キーバインドをそのまま使います。
| キー | 動作 |
|---|---|
| 文字入力 | インクリメンタルに絞り込む |
| ↑ / ↓、Ctrl-p / Ctrl-n、Ctrl-k / Ctrl-j | 候補を移動する |
| Tab / Shift-Tab | 候補の選択を切り替える(複数選択モードのみ) |
| Enter | 決定する |
| Shift-↑ / Shift-↓ | プレビューをスクロールする |
| Esc / Ctrl-C | 中断する |
-
複数選択に対応するのは
cherry-pick/restore/add/stash push/commit/revert/status(ファイル選択)/diff(ファイル選択)/branch delete/branch cleanup/fetch --siblings/pull、および復帰メニューの 「コンフリクトファイルを確認して解決済みにする」です。Tab で 1 件も 選ばずに Enter を押した場合は、カーソル位置の候補が対象になります。 -
起動時から選択済みになるのは
gz commit(ステージ済みのファイル)、gz branch cleanup(merged なブランチ全件)、gz fetch --siblings(現在のリポジトリ)、gz pull(現在のブランチ)です。いずれも Tab で外せます。 -
選択結果は常に候補一覧を基準に並べ直してから git へ渡します
(skim が返す順序は選んだ順であり、候補の並び順とは限らないため)。
gz cherry-pickは古い順、gz revertは新しい順というように、 順序が意味を持つコマンドはそれぞれの向きへ揃えます。 - Esc / Ctrl-C で中断した場合、git 操作は一切実行せず 終了コード 130 で終了します。
Exit codes終了コード #
| Code | Meaning |
|---|---|
0 |
Success (including gz status with no changes, gz diff with no differences, gz sync with behind 0 and gz worktree prune with nothing to prune) |
1 |
Error (running outside a repository, zero candidates, a failing git command, and so on; the message goes to stderr).
gz fetch --siblings returns 1 if even one repository fails to fetch (the remaining repositories still run to the end and are then summarised).
gz pull likewise returns 1 if even one branch fails to integrate (the remaining branches still run to the end and are summarised; a failed branch is left in its pre-integration state).
|
2 |
Invalid command line (including bare gz and bare gz stash, where clap prints the help) |
130 |
The fuzzy finder was aborted (Esc / Ctrl-C), or a confirmation prompt was declined. No git operation is performed |
Run outside a git repository, fuzgit prints “Not a git repository. Run this command inside a git repository” and exits non-zero.
| コード | 意味 |
|---|---|
0 |
正常終了(gz status の変更ゼロ、gz diff の差分ゼロ、gz sync の behind ゼロ、gz worktree prune の対象ゼロを含む) |
1 |
エラー(リポジトリ外での実行、候補が 0 件、git コマンドの失敗など。メッセージは標準エラーへ)。
gz fetch --siblings は 1 件でも取得に失敗すると 1 になります
(残りのリポジトリは最後まで実行したうえで集計します)。
gz pull も 1 件でも取り込みに失敗すると 1 になります
(残りのブランチは最後まで実行したうえで集計します。失敗したブランチは取り込み前の状態のままです)
|
2 |
コマンドライン引数が不正(引数なしの gz / gz stash を含む。clap がヘルプを表示) |
130 |
fuzzy finder の中断(Esc / Ctrl-C)、または確認プロンプトでの否認。git 操作は実行されない |
git リポジトリ外で実行した場合は「git リポジトリではありません」と表示して非ゼロ終了します。
Out of scope / unsupportedスコープ外・非対応 #
Features deliberately left unimplemented. All of them can be done with plain git.
| Item | Reason |
|---|---|
--rebase / --merge for gz pull (integration other than fast-forward) |
gz pull (fast-forwarding several branches at once) is implemented; what is not offered is the choice of method. Rebasing or merging a branch that is not checked out would require temporarily switching the working tree or creating a temporary worktree, both of which introduce risks that contradict the “never lose the user’s work” policy. Also, if the k-th of N branches conflicts, truly returning to the pre-pull state would mean rolling back the k-1 that already succeeded, which cannot be done without something as dangerous as git reset --hard. Integrating a single branch with an arbitrary method is covered by gz sync --rebase / --merge
|
--siblings / --prune / a positional branch name for gz pull |
--siblings would explode the number of selection combinations, and the “pick a branch per repository” model does not hold (pull is a write operation that advances local refs in somebody else’s repository, unlike gz fetch --siblings). --prune follows the policy that deleting tracking refs is stated explicitly via gz fetch --prune (same as gz sync). A positional argument is not provided because if you can type the name, plain git already suffices (the existing rule of skipping the finder when there is a single candidate already gives a near-non-interactive experience)
|
Pushing (gz push) |
There is nothing worth picking. The branch is fixed to the current one, and a repository almost always has a single remote, so the finder would open with one candidate every time. Plain git push already does the job. Force push is out of scope on top of that: destroying remote history cannot be guaranteed safe by a confirmation prompt alone |
Reverting a merge commit (git revert -m) |
Picking the mainline requires understanding the history structure, and a fuzzy finder adds no value to that choice. When one is selected, fuzgit stops before running and points at plain git revert -m 1 <hash> |
Running --dry-run inside the gz fetch preview |
A preview runs anew for every highlighted entry, so a network round trip would block the display. Updated refs are printed by git fetch itself when it runs |
Recursive scanning, or a depth option (--depth etc.), for gz fetch --siblings |
One level below the parent directory already covers the use case; recursion would increase both the scan cost and the blast radius of network traffic. Repositories in deeper levels are not targeted |
An option to specify the scan origin of gz fetch --siblings as a path |
Accepting an arbitrary path would break the assumption shared by every command that the current repository is the origin, and would let traffic be aimed at unintended directories. The origin is fixed to the parent of the worktree root |
Per-repository remote selection in gz fetch --siblings |
It would mean repeating the finder once per repository, which breaks the operation model. Guessing a single remote implicitly is also avoided, in favour of the deterministic rule --all (every registered remote). Excluding a specific remote can be done on the git side with remote.<name>.skipFetchAll |
| Fetching sibling repositories in parallel | git itself fetches multiple remotes sequentially by default. With inherited stdio the output would interleave and the destination of an authentication prompt would become unidentifiable (see Network operations) |
Including bare repositories in the --siblings candidates |
There is no working tree for the fetched refs to land in. A bare repository such as foo.git falls outside the scan condition (the existence of <directory>/.git) and is never a candidate; a repository that has <directory>/.git but is configured bare is excluded and counted in the exclusion count shown in the header. This is a feature for the repositories you work in day to day |
| Following symlinked sibling directories | The scan range is limited to real entries directly under the parent directory, preventing the set of contacted hosts from expanding unexpectedly |
A [y/N] confirmation before gz fetch --siblings runs |
Making a multi-selection and pressing Enter is already an explicit decision, and a second confirmation is redundant. A fetch also does not damage local history (the scope of --prune is shown in the finder header) |
| Bulk operations other than fetch across sibling repositories (bulk status, bulk pull, etc.) | fetch is the one operation suited to bulk execution: read-direction, non-destructive and safe to re-run. Extending this to other operations would need its own requirements |
Custom signal handling during --siblings (e.g. Ctrl-C to skip the rest) |
With inherited stdio, SIGINT reaching the process group and terminating fuzgit with it is the expected behaviour. Custom control would be excessive |
| Automatic retry of failed repositories | The existing policy of adding no timeouts and no retries continues. The names of failed repositories appear in the summary line, so the user can decide about re-running |
tag vs tag in gz diff |
Rarely needed; tag vs HEAD is available as gz tag --diff |
gz worktree move / lock / unlock / repair, and remove --force |
Rarely needed day to day, and each is a single plain git command. Discarding uncommitted changes is hard to justify behind a confirmation prompt alone |
| A text input UI for branch names and worktree paths | skim has no text input UI. Names and paths are positional arguments (gz branch create <name> / gz worktree add <path>) and the fuzzy selection is limited to the starting point / the branch. gz worktree add also never suggests a directory name automatically |
| Hunk-level partial commit / stage | File-level selection covers the use case. Hunk selection does not fit skim’s candidate model (one line = one item) |
Running the autosquash rebase automatically after gz fixup |
History rewriting is never run automatically; the steps are printed to stderr and nothing more |
| A recovery menu for cherry-pick / revert / fetch | The recovery menu is limited to merge / rebase. Conflicts in cherry-pick / revert are left to git’s standard message and its --continue / --abort guidance |
| “Open the conflicted file in an editor” | That would launch $EDITOR directly without going through git, which needs a separate design decision to stay consistent with the no-shell policy |
意図的に実装していない機能です。いずれも素の git で実行できます。
| 項目 | 理由 |
|---|---|
gz pull の --rebase / --merge(fast-forward 以外の取り込み方式) |
gz pull(複数ブランチを fast-forward で一括取り込み)は実装済み。
方式を選べるようにしないのは、チェックアウトしていないブランチを rebase / merge するには
作業ツリーを一時的に切り替えるか一時 worktree を作るしかなく、いずれも
「ユーザーの作業を失わせない」方針に反するリスクを持ち込むため。また N 本中 k 本目で
コンフリクトした場合、真に「pull 前」へ戻すには成功済みの k-1 本も巻き戻す必要があり、
git reset --hard 相当の危険な操作なしには成立しない。単一ブランチを任意の
方式で取り込む用途は gz sync --rebase / --merge が満たす
|
gz pull の --siblings / --prune / ブランチ名の位置引数 |
--siblings は選択の組み合わせが爆発し、リポジトリごとにブランチを選ぶ
操作モデルが成立しない(pull は他人のリポジトリのローカル参照を進める書き込み操作であり、
gz fetch --siblings と性質が異なる)。--prune は追跡参照の削除を
gz fetch --prune として明示指定する方針(gz sync と同じ)。
位置引数は、名前を打てるなら素の git で足りるため設けない(候補が 1 件なら finder を
省略する既存原則で非対話に近い使い勝手は確保される)
|
push(gz push) |
選ぶ価値のある軸が無い。対象ブランチは現在のブランチに固定され、リモートは 1 つだけのリポジトリがほとんどであるため、候補 1 件の finder が毎回開くだけになる。素の git push で足りる。加えて force push は、リモート履歴の破壊を確認プロンプトだけでは担保できないためスコープ外 |
マージコミットの revert(git revert -m) |
mainline の選択は履歴構造の理解を要し、fuzzy finder で「選ぶ」価値が乗らない。
選択された場合は実行前に停止し、素の git revert -m 1 <hash> を案内する
|
gz fetch のプレビューでの --dry-run 実行 |
プレビューは選択項目ごとに都度実行されるため、ネットワーク往復が描画をブロックする。更新された参照は git fetch 自身が実行時に表示する |
gz fetch --siblings の再帰探索・探索深度の指定(--depth 等) |
親ディレクトリ直下の 1 階層で用途を満たせており、再帰は走査コストとネットワークの影響範囲を同時に増やす。深い階層のリポジトリは対象にしない |
gz fetch --siblings の探索起点をパスで指定するオプション |
任意パスを受け取ると「現在のリポジトリを起点にする」という全コマンド共通の前提が崩れ、意図しないディレクトリへ通信を飛ばせてしまう。起点はワークツリー root の親に固定する |
gz fetch --siblings でのリポジトリごとのリモート選択 |
リポジトリ数だけ finder を繰り返すことになり操作モデルが成立しない。暗黙に 1 つのリモートを
推測するのも避け、--all(登録済みの全リモート)という決定的な規則を採る。
特定リモートの除外は git 側の remote.<name>.skipFetchAll で行える
|
| 兄弟リポジトリの並列 fetch | git 自身も複数リモートの fetch を既定で逐次実行する。継承 stdio では出力が混ざり、認証プロンプトの宛先も判別できなくなる(ネットワーク操作について参照) |
bare リポジトリを --siblings の候補に含めること |
fetch した参照の反映先となる作業ツリーが無い。foo.git のような bare は
走査条件(<ディレクトリ>/.git の存在)から外れて候補にならず、
<ディレクトリ>/.git を持つが bare 設定のリポジトリは除外件数に数えて
ヘッダーへ示す。日常的に作業するリポジトリを対象とする機能である
|
| シンボリックリンクの兄弟ディレクトリを辿ること | 走査範囲を「親ディレクトリ直下の実体」に限定し、通信先が予期せず広がることを防ぐ |
gz fetch --siblings 実行前の [y/N] 確認プロンプト |
複数選択して Enter を押すこと自体が明示的な決定であり、二重確認は冗長。fetch はローカル履歴を壊さない操作でもある(--prune の適用範囲は finder のヘッダーで示す) |
| 兄弟リポジトリへの fetch 以外の一括操作(一括 status / 一括 pull 等) | fetch は「読み取り方向・非破壊・失敗しても再実行できる」唯一の一括実行に適した操作である。他の操作へ広げるのは別途要件から起こす |
--siblings 実行中の独自シグナルハンドリング(Ctrl-C で残りをスキップ等) |
継承 stdio のままプロセスグループへ SIGINT が届き fuzgit ごと終了するのが期待挙動。独自制御は過剰 |
| 失敗したリポジトリの自動リトライ | fuzgit 側でタイムアウト・リトライを行わない既存方針を継続する。失敗したリポジトリ名は集計行に出るため、再実行の判断はユーザーが行える |
gz diff の tag vs tag |
使用頻度が低く、tag vs HEAD は gz tag --diff で行える |
gz worktree の move / lock / unlock / repair、remove --force |
日常頻度が低く、いずれも素の git で 1 コマンドで済む。未コミット変更の破棄は確認プロンプトだけでは担保しにくい |
| ブランチ名・worktree パスのテキスト入力 UI |
skim にテキスト入力 UI は無い。名前・パスは位置引数
(gz branch create <name> / gz worktree add <path>)とし、
fuzzy 選択は作成元・ブランチに限定する。gz worktree add のディレクトリ名の
自動提案も行わない
|
| hunk 単位の部分 commit / stage | ファイル単位の選択で用途を満たす。hunk 選択は skim の候補モデル(行=項目)に乗らない |
gz fixup 後の autosquash rebase の自動実行 |
履歴改変の自動実行は行わない。手順を標準エラーへ表示するに留める |
| cherry-pick / revert / fetch の復帰メニュー | 復帰メニューは merge / rebase に限定する。cherry-pick / revert のコンフリクトは git の標準メッセージと --continue / --abort の案内に委ねる |
| コンフリクトファイルを「エディタで開く」 | git を介さず $EDITOR を直接起動する経路になり、シェル非経由方針との整合に別途設計判断が必要 |
Debuggingデバッグ #
$ FUZGIT_DEBUG=1 gz branch
[fuzgit] (B) git log --color=always --oneline --decorate -n 50 feature -- [LANGUAGE=en]
[fuzgit] (B) git switch feature [LANGUAGE=en]
$ FUZGIT_DEBUG=1 gz status
[fuzgit] (A) (cwd: .) git status --porcelain -z --untracked-files=all [LC_MESSAGES=C]
Setting the environment variable FUZGIT_DEBUG=1 prints
every git command fuzgit runs to stderr.
- It is enabled only when the value is exactly
1. Unset, empty,0,trueand anything else are all disabled. - The destination is always stderr (stdout is kept free for piping hashes, tag names and paths).
- The log lists the argument array as-is. Because it is printed on every preview generation, it can visibly mix with the drawing while the fuzzy finder is on screen.
- Commands that target another directory are printed as
[fuzgit] (A|B) (cwd: <directory>) git .... -
(A)marks a call whose output fuzgit parses: it always runs withLC_MESSAGES=Cso parsing cannot depend on the environment.(B)marks a call whose output you read (inherited stdio, previews, reports passed through): the resolved display language is propagated asLANGUAGE=<ja|en>. The variables that were set or removed are listed in brackets at the end of the line, so the log answers “which language did this git speak?” directly. See Language.
環境変数 FUZGIT_DEBUG=1 を指定すると、fuzgit が実行した git コマンドを
標準エラーへ出力します。
- 有効になるのは値が厳密に
1の場合だけです。未設定・空文字・0・trueなどはすべて無効です。 - 出力先は必ず標準エラーです(標準出力はハッシュ・タグ名・パスのパイプ用途のために空けてあります)。
- ログにはコマンドの引数配列がそのまま並びます。プレビュー生成のたびに出力されるため、fuzzy finder の表示中は画面の描画と混ざって見えることがあります。
- 別ディレクトリを対象に実行するコマンドは
[fuzgit] (A|B) (cwd: <ディレクトリ>) git ...の形式で出力します。 -
(A)はfuzgit が出力をパースする呼び出しで、実行環境に よってパースが壊れないよう常にLC_MESSAGES=Cで実行します。(B)はユーザーが出力を読む呼び出し(継承 stdio・プレビュー・ そのまま提示する報告)で、解決された表示言語をLANGUAGE=<ja|en>として伝播します。設定・削除した環境変数は 行末の角括弧に併記されるため、「この git は何語で話したのか」がログから直接 分かります。表示言語も参照してください。
Development開発 #
Quality gate品質ゲート
Confirm that all of these succeed, in this order, on every change.
以下の順にすべて成功することを、変更のたびに確認してください。
cargo build
cargo clippy --all-targets -- -D warnings
cargo fmt --check
cargo test
Testing policyテスト方針
- Interactive paths that take over the terminal (the TUI) are outside the scope of automated tests and are verified manually.
-
Automated tests cover pure logic (formatting candidates, assembling
git arguments, parsing
git status/git stash list/git worktree list) as unit tests, and non-interactive paths (--help, running outside a repository, zero candidates) as integration tests withassert_cmd. -
Paths involving the network (
gz fetch/gz pull/gz sync) are not automated; only their non-interactive paths (no remotes, no upstream, zero candidates and similar errors) are verified. Real-world checks use a local bare repository as the remote and never connect to an external network.
- 端末(TUI)を占有する対話パスは自動テストの対象外とし、手動確認とします。
-
自動テストの対象は、候補の整形・git 引数の組み立て・
git status/git stash list/git worktree listのパースなどの純ロジック (単体テスト)と、--help・リポジトリ外実行・候補 0 件などの非対話パス (assert_cmdによる統合テスト)です。 -
ネットワークを伴う経路(
gz fetch/gz pull/gz sync)は自動テスト化せず、非対話パス(リモートゼロ・upstream 未設定・ 候補ゼロなどのエラー)のみを検証します。実機確認はローカルの bare リポジトリを remote に設定して行い、外部ネットワークへは接続しません。
Design principles設計方針
-
Read with gix, write by shelling out to
git. gix does not provide the write operations for switch / cherry-pick / restore / add / stash, so they are delegated to the system git in order to keep behavioural compatibility. The worktree listing is read withgit worktree list --porcelain -zrather than gix (gix cannot handle the main worktree or the checked-out branch). -
External commands always run as
Command::new("git").args([...]), i.e. with an argument array, never through a shell. Paths that come from the user are passed after--as the pathspec:(top,literal)<path>, removing any room for them to be interpreted as options or wildcards. - Previews do not hand skim a shell command string; git is executed from Rust and the result is displayed, which structurally prevents injection through candidate strings.
-
Positional arguments that cannot be protected with
--, such as branch names and commit hashes (switch/merge/rebase/push/fixup/revert/diff), are passed to git only after checking that the selection is present in the candidate list. The only values that get through originate from real refs enumerated by gix.gz syncandgz pullverify thatbranch.<name>.remoteis a registered remote name before runninggit fetch(the configuration can hold a URL directly, so without the check they could connect to something that was never enumerated). The refspecgz pulluses for branches that are not checked out carries no forcing+, so git rejects non-fast-forward updates and local commits cannot be lost. - No network access during candidate generation or previews.
-
The only command that touches anything outside the current
repository is
gz fetch --siblings. The scan origin is always derived from the current repository’s worktree root (no path argument is accepted) and is limited to one level under the parent directory. Sibling repositories are opened withgix::open, notgix::discover(discoverwalks upwards, so a directory without a.gitwould grab a repository above the scan range). The selection is checked for an exact match against the candidate list, using normalised absolute paths, before it becomes a target. -
Destructive operations (discarding changes with
restore,stash drop,branch delete/cleanup, history rewriting withrebase, the integration performed bysync,worktree remove/prune, and aborting a merge / rebase) are confirmed first.mergeis confirmed too, showing how many commits will come in and the conflict prediction. - History rewriting is never run automatically (
gz fixuponly prints the autosquash steps; it does not rebase). - Pushing is not provided at all, so neither is force push. Use plain
git push.
-
読み取りは gix、書き込みは
gitへのシェルアウト。 gix は switch / cherry-pick / restore / add / stash の書き込み操作を提供していないため、 挙動互換性を優先してシステムの git に委譲しています。worktree の一覧だけは gix ではなくgit worktree list --porcelain -zを読みます(gix は main worktree と チェックアウト中のブランチを扱えないため)。 -
外部コマンドは常に
Command::new("git").args([...])の引数配列渡しで 実行し、シェルを一切経由しません。ユーザー由来のパスは--の後ろに:(top,literal)<path>のパススペックとして渡し、オプションや ワイルドカードとして解釈される余地を排除しています。 - プレビューは skim にシェルコマンド文字列を渡す方式ではなく、Rust 側で git を実行した 結果を表示する方式を採り、候補文字列由来のインジェクションを構造的に防いでいます。
-
ブランチ名・コミットハッシュのように
--で保護できない位置引数 (switch/merge/rebase/push/fixup/revert/diff)は、 選択結果が候補一覧に含まれることを確かめてから git へ渡します。 渡る値は gix が列挙した実在の参照に由来するものだけです。gz syncとgz pullはbranch.<name>.remoteが登録済みのリモート名で あることを検証してからgit fetchします(設定には URL を直接書けるため、 検証しないと列挙していない対象へ接続することになります)。gz pullが チェックアウトしていないブランチを更新する refspec には、強制更新の+を 付けません(非 fast-forward の更新を git に拒否させ、ローカルのコミットを 失わせないためです)。 - 候補生成・プレビューでネットワークアクセスを行いません。
-
現在のリポジトリ以外に触れるのは
gz fetch --siblingsだけです。 走査の起点は常に現在のリポジトリのワークツリー root から導出し(パス引数を受け取りません)、 親ディレクトリ直下の 1 階層に限定します。兄弟のリポジトリを開くのはgix::openでありgix::discoverではありません (discoverは上位へ遡るため、.gitを持たないディレクトリから 走査範囲より上のリポジトリを掴んでしまいます)。選択結果は正規化済みの絶対パスで 候補一覧と完全一致することを確かめてから実行対象にします。 -
破壊的操作(
restoreによる変更破棄、stash drop、branch delete/cleanup、rebaseによる履歴改変、syncの取り込み、worktree remove/prune、 merge / rebase のabort)は実行前に確認を挟みます。mergeにも 確認を設け、取り込まれるコミット数とコンフリクト予測を提示します。 - 履歴改変の自動実行は行いません(
gz fixupは autosquash の手順を表示するだけで rebase しません)。 - push 自体を提供しないため、force push も提供しません。素の
git pushを使ってください。
Module layoutモジュール構成
src/
├── main.rs # entry point (parse the CLI, dispatch, exit code)
├── lib.rs
├── cli.rs # command definitions via clap derive
├── error.rs # domain errors via thiserror
├── finder.rs # skim wrapper (candidates, preview, abort detection)
├── git/
│ ├── repo.rs # opening the repository with gix
│ ├── read.rs # reading candidate data via gix / git
│ ├── siblings.rs # scanning repositories under the parent directory (gz fetch --siblings only)
│ └── exec.rs # running git (run_git / capture_git) and the debug log
└── commands/ # the use case implementation of each subcommand
src/
├── main.rs # エントリポイント(CLI パース → dispatch → 終了コード)
├── lib.rs
├── cli.rs # clap derive によるコマンド定義
├── error.rs # thiserror によるドメインエラー
├── finder.rs # skim ラッパー(候補・プレビュー・中断判定)
├── git/
│ ├── repo.rs # gix によるリポジトリのオープン
│ ├── read.rs # gix / git による候補データの読み取り
│ ├── siblings.rs # 親ディレクトリ直下のリポジトリ探索(gz fetch --siblings 専用)
│ └── exec.rs # git の実行(run_git / capture_git)とデバッグログ
└── commands/ # 各サブコマンドのユースケース実装
Licenseライセンス #
MIT License. The full text is in LICENSE.
MIT License. 全文は LICENSE を参照してください。