標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

`git tag -d` を行った後、jj でコミットの破棄が行われてしまう動作に対する傾向と対策

そういう仕様動作であって、不具合というわけではないようです。

Git互換の分散バージョン管理システム jj には Git との共存機能があり、git init したディレクトリにて jj git init --colocate を行うと、そのレポジトリでは git とjj を併用できるようになります。

jj には git tag のようなコマンドがないので、タグ付けには git tag を用います。逆に一度付けたタグを外すのも git tag -d を使うのですが、ここで予想外の動作がありました。

git tag -d した直後の jj log で、未push のコミットの幾つかが破棄されてしまいました。

issue での回答によると、jj の外で git のタグ・ブランチに変更が行われた時、git の変更を jj へ反映させるプロセスの中で、git から見えないコミットは破棄するという処理が行われた結果のようです。

ちょっと分かりにくいのですが、jj でGitブランチの先頭を明示的にカレントブランチ前後まで移動していない場合1、カレントブランチまでのコミットは Git からはヘッドのない見えないコミット群に見えるから…ですね。

ファイル破棄を伴う動作は危険なので、デフォルトで抑制すべきだと個人的には思うのですが、そういう動作仕様・ポリシーならば仕方ありません。対策しましょう。

復旧方法

破棄されても復旧方法はあります。jj op undo を使えば、破棄そのものをロールバックできます。

$ git tag -d v0.2.0
Deleted tag 'v0.2.0' (was 501e5a4)

$ jj log -r all()
Abandoned 1 commits that are no longer reachable.
Rebased 1 descendant commits off of commits rewritten from git
Working copy now at: tqqprwln 43b4f09c (empty) (no description set)
Parent commit      : towklztv dda1932c step1
Added 0 files, modified 0 files, removed 1 files
Done importing changes from the underlying Git repo.
@  tqqprwln iyahaya@nifty.com 2024-11-12 22:04:55 43b4f09c
│  (empty) (no description set)
◆  towklztv iyahaya@nifty.com 2024-11-12 21:55:55 v0.1.0 git_head() dda1932c
│  step1
◆  zzzzzzzz root() 00000000

$ jj op log
@  72c4b9e7f699 hymkor@DESKTOP-NPOTG52 7 seconds ago, lasted 45 milliseconds
│  import git refs
│  args: jj log -r 'all()'
○  3b050db536e2 hymkor@DESKTOP-NPOTG52 8 minutes ago, lasted 16 milliseconds
│  import git refs
│  args: jj log

: (略)

$ jj op undo 72c4b9e7f699
Undid operation: 72c4b9e7f699 (2024-11-12 22:04:55) import git refs
Working copy now at: tqqprwln 40e91386 (empty) (no description set)
Parent commit      : nxnkplvz 501e5a44 step2
Added 1 files, modified 0 files, removed 0 files

$ git log
commit 501e5a44447f270d79157a35274403f49e66713e (HEAD)
Author: HAYAMA_Kaoru <iyahaya@nifty.com>
Date:   Tue Nov 12 21:56:07 2024 +0900

    step2

commit dda1932c6b6e36f24eb427463ec19ccf59ee6145 (tag: v0.1.0)
Author: HAYAMA_Kaoru <iyahaya@nifty.com>
Date:   Tue Nov 12 21:55:55 2024 +0900

    step1

でも、この後、jj のコマンドを発行すると、また同じコミットが破棄されてしまいます。

そうならないように git が認識できるようにすれば Ok ですので、とりあえず適当なタグを git で打ちましょう(なんか変な話ですが)

$ git tag tmptag

$ git log
commit 501e5a44447f270d79157a35274403f49e66713e (HEAD, tag: tmptag)
Author: HAYAMA_Kaoru <iyahaya@nifty.com>
Date:   Tue Nov 12 21:56:07 2024 +0900

    step2

commit dda1932c6b6e36f24eb427463ec19ccf59ee6145 (tag: v0.1.0)
Author: HAYAMA_Kaoru <iyahaya@nifty.com>
Date:   Tue Nov 12 21:55:55 2024 +0900

    step1

$ jj log
Done importing changes from the underlying Git repo.
@  tqqprwln iyahaya@nifty.com 2024-11-12 21:56:42 40e91386
│  (empty) (no description set)
◆  nxnkplvz iyahaya@nifty.com 2024-11-12 21:56:07 tmptag git_head() 501e5a44
│  step2
~  (elided revisions)
◆  zzzzzzzz root() 00000000

予防策

設定で abandon する動作を抑制させることもできるようです。

jj config set --user git.abandon-unreachable-commits false

これをやっておくと、git tag -d を行った後でも、破棄される動作はなくなりました。

$ jj log -r all()
@  tqqprwln iyahaya@nifty.com 2024-11-12 21:56:42 40e91386
│  (empty) (no description set)
◆  nxnkplvz iyahaya@nifty.com 2024-11-12 21:56:07 v0.2.0 git_head() 501e5a44
│  step2
◆  towklztv iyahaya@nifty.com 2024-11-12 21:55:55 v0.1.0 dda1932c
│  step1
◆  zzzzzzzz root() 00000000

$ git tag -d v0.2.0
Deleted tag 'v0.2.0' (was 501e5a4)

$ jj log -r all()
Done importing changes from the underlying Git repo.
@  tqqprwln iyahaya@nifty.com 2024-11-12 21:56:42 40e91386
│  (empty) (no description set)
○  nxnkplvz iyahaya@nifty.com 2024-11-12 21:56:07 git_head() 501e5a44
│  step2
◆  towklztv iyahaya@nifty.com 2024-11-12 21:55:55 v0.1.0 dda1932c
│  step1
◆  zzzzzzzz root() 00000000

ただ、これを設定しておくと、ゴミコミットがずっと残り続ける可能性があるということは留意しておく必要はありそうです。デフォルトになっていないということは、もしかしたら他にも何か弊害があるのかもしれません。

そういうのを避けるならば、git.abandon-unreachable-commits は true のままにしておいて、git tag -d を行う前には jj bookmark move master -r "@-" を実行して、操作を同期させておいたほうがよさそうです(まぁ、うっかり、しくじっても比較的簡単に undo できるのが jj のよいところですが)


  1. jj bookmark move master --to "@-" で、Git のブランチの先頭を jj にカレントコミットに同期させることができる