「楽しさと利益のためのジュージ・メガマージ」

2026/04/21 6:32

「楽しさと利益のためのジュージ・メガマージ」

RSS: https://news.ycombinator.com/rss

要約

日本語訳:

記事は、JUJUTSU で導入される簡素化されたバージョン管理ワークフロー「megamerge」について紹介しています。これは、オクトパス合併(3 つ以上の親を持つ合併)を用いて、複数の開発ブランチを単一のローカルのベースコミットに統合します。不安定なブランチの先頭に直接作業を行う代わりに、開発者は関連する上流ブランチ(機能追加、バグ修正、設定など)を親とする空の megamerge コミットを作成し、作業コピーが常にすべての変更を統合してコンパイル可能になるように確保するとともに、タスクを変更する際に予期せぬリモート合併競合を排除します。

megamerge を開始するには、

jj new x y z
を実行した後に
jj commit --message "megamerge"
を実行し、指定されたブランチを親とする空のコミットを作成します。すべての書き込みは、このベース(WIP ス tack)の上で実施され、megamerge がローカルに留まることで安定性を保ちます。個々の機能ブランチは遠隔リポジトリへ通常通り公開し続けますが、megamerge 自体はプッシュされません。

jj absorb
を用いて上流の変更を自動的に統合するワークフローでは、約 90% の更新を後続的可変コミットに圧縮して同定します。新しい作業で独自のコミットが必要になる場合は、bookmark を更新しながら WIP を megamerge の下に移動するために
jj rebase --revision y --after x --before megamerge
を使用します。並列ス tack の管理には revset アリヤス(例:
"closest_merge(to)" = "heads(::to & merges())"
)および
stack
コマンドを用い、
stage = ["stack", "closest_merge(@).. ~ empty()"]
というようにのアリヤスで一度にステージリングし、その後
jj stage
を実行します。

メインブランチ(

trunk()
)との同期を維持するには
jj rebase --onto trunk()
を使用でき、これは自分が所有するコミットに対して動作し、他者によるブランチは保護されます。Mutable コミットのみを安全に trunk へ rebase するための場合は、
restack = ["rebase", "--onto", "trunk()", "--source", "roots(trunk()..) & mutable()"]
というようなアリヤスを使用します。全体として、このアプローチは合併による面倒を大幅に削減し、新しい作業が堅牢な統合された基盤の上に自然と構築されるような円滑で協力的なサイクルをサポートします。

本文

この記事は、中途半端な Juju ツーザー(Jujutsu ユーザー)向けだけでなく、Juju ツーザーとして Git に興味を持っている方々にも読んでもらいたく執筆しました。私自身、重度の Juju ツーザーでございまして、毎日の開発ワークフローにおいて、コミュニティでは俗に「メガマージ(Megamerge)」と呼んでいる作業手順への依存度を日に日に高めています。残念ながら、この手法は数人のパワーユーザーを除けばあまり議論されることはなく、それをどのように行うのか、そしてなぜそれが特に複雑な開発環境や、小規模な PR を多くリリースする際にもたらす恩恵なのかについて共有したいと思いまして。急がれる場合、最後のセクションまでスキップしてクイックヒントをチェックしてくださいませ。

メージコミットとは思っているようなものではありません

平均的な Git ユーザー(あるいは、より高度なワークフローにまだ触れていない Juju ツーザー)の場合、「メージコミット」には何ら特別なものがあるとは驚かれます。それは特別なケースであり独自のルールを持つものではありません。単に親が複数ある通常のコミットに過ぎず、内容が空である必要さえありません!

@ myzpxsys イサク・コーブレイ 12 秒前 634e82e2 │ (empty) (説明未設定) ○ mllmtkmv イサク・コーブレイ 12 秒前 git_head() 947a52fd ├─╮ (empty) ものをつなぐ │ ○ vqsqmtlu イサク・コーブレイ 19 秒前 f41c796e │ │ deps: クアンタム マニフォールド リゾルバーを固定化 ○ │ tqqymrkn イサク・コーブレイ 19 秒前 0426baba ├─╯ storage: 一時的キャッシュのマニフォールドを整列化 ◆ zzzzzzzz root() 00000000 すべてを組み合わせてやるべし!

さらに驚かれるのは、メージコミットが必ずしも親が二つとは限らないという点です。私達はこの三つ以上の親を持つメージコミットを公式には呼びませんが「オクトパス・メージ(Octopus merges)」と呼びます。「いったい誰がもっと多くのブランチをつなぐ必要があるだろうか」と思われるかもしれませんが、これは実は非常に強力なアイデアであり、オクトパス・メージは全体となるメガマージワークフローの心臓部となります!

そもそも「メガマージ」というのは一体何なのか?

基本的には、メガマージワークフローでは、ブランチの先頭(ティップ)に直接作業を行うことは滅多にありません。代わりに、ケアするすべてのワーキングブランチの子として、オクトパス・メージコミット(以下、「メガマージ」と呼ぶ)を作成します。つまり、バグフィックス、機能ブランチ、PR を待機中のブランチ、コードを連携させる必要がある他人のブランチ、ローカル環境設定用ブランチ、あるいは特定のブランチに属さない個人的なコミットなど、あなたが关心するすべてのものがメガマージに含まれます。重要なのは、メガマージそのものをプッシュしないことではなく、それを構成しているブランチのみをプッシュする点です。

@ mnrxpywt イサク・コーブレイ 25 秒前 f1eb374e │ (empty) (説明未設定) ○ wuxuwlox イサク・コーブレイ 25 秒前 git_head() c40c2d9c ├─┬─╮ (empty) megamerge │ │ ○ ttnyuntn イサク・コーブレイ 57 秒前 7d656676 │ │ │ storage: 一時的キャッシュのマニフォールドを整列化 │ ○ │ ptpvnsnx イサク・コーブレイ 25 秒前 897d21c7 │ │ │ parser: fleem トークンを脱マスキュライズ化 │ ○ │ zwpzvxmv イサク・コーブレイ 37 秒前 14971267 │ │ │ infra: ブロブ アロケイターを再構築 │ ○ │ tqxoxrwq イサク・コーブレイ 57 秒前 90bf43e4 │ ├─╯ io: ポラリティーバルブの詰まりを解消 ○ │ moslkvzr イサク・コーブレイ 50 秒前 753ef2e7 │ │ deps: クアンタム マニフォールド リゾルバーを固定化 ○ │ qupprxtz イサク・コーブレイ 57 秒前 5332c1fd ├─╯ ui: レイアウトのヒューリスティクスを脱ブロブナイズ化 ○ wwtmlyss イサク・コーブレイ 57 秒前 5804d1fd │ test: ハイパーフロブニケーション スートを追加 ◆ zzzzzzzz root() 00000000 おそらき!マージが多すぎる!

これが少し複雑に聞こえても構いません。畢竟、古い PR を振り返ってレビューを求めるなどの場合、コンテキストスイッチングにどれほどの努力を払う必要があるかはご存知でしょうしね。しかしながら、これにより数点非常に貴重なメリットが得られます:

  • あなたは常に、すべての作業の合計体上で働いています。つまり、ワーキングコピーが問題なくコンパイルされ実行できれば、あなたの作業同士も問題なく相互作用することが保証されます。
  • メージ競合を気にする必要はほとんどありません。すでに Juju ツーザーであれば競合は 1 次概念として扱われ心配しなくてよいわけですが、文字通り常に自分の変更をつなげるため、フォージ側での驚きのメージ競合に襲われることはありません。
  • 貢献者の変更に関する稀な問題が発生することはありますが、私の経験ではこれが主要な問題になったことはほとんどありませんでした。
  • タスク間を切り替える際の摩擦が劇的に軽減されます。常にメガマージの上に作業しているため、VCS(バージョン管理システム)にアクセスしてタスクを切り替える必要はなく、必要なところだけ編集できます。さらに言えば、ドライブバイ・リファクタリングやバグフィックスのための小規模な PR を作成するのも格段に容易になります。
  • ブランチを最新状態に保ちやすくします。ちょっとした魔法があれば、単一のリベースコマンドですべてのメガマージをトランクブランチと同期できます。後ほどその方法を教えます。

それをどう作るのか?

メガマージを開始するのは超簡単です:メガマージに含まれる各ブランチを親とする新しいコミットを作成するだけです。私は通常、そのコミットに名前を与えながら内容を持たないようにします(以下のように):

jj new x y z
jj commit --message "megamerge"

メガマージの作成。実はそれほど難しくはないのです!

すると、この全体を頂上に空のコミットが残ります。ここが本格的な作業場所です!メガマージ・コミットの上位にあるものはすべて WIP(未完)とみなされます。必要な分だけ分割したり、そのメガマージ・コミットに基づいて複数のブランチを作成したり、何でもご自由にお好みで行ってください。あなたが記述するすべての内容は、メガマージ内の全要素の総和に基づいたものとなり、それがまさに我々が望んだ通りの状態となります!

もちろん、ある時点で「さて、今の成果はどういう形で作成すればよいのだろうか」と思われる日が来ます:

どうやって実際に変更を提出すればよいのか?

WIP(未完)の変更点をメガマージに統合する方法は、その変更点がどこに属すべきかによって異なります。既存の変更点に属すべき場合なら、

--to
フラグを使って
squash
コマンドを使用し、適切以下のコミットへシャッフルして送ることができます。コミット内に複数のコミット分の変換を含む場合、それらを圧縮する前に複数のコミットに分割するか(私が好む方法)、または
squash --interactive
を使用してインタラクティブに圧縮し、移動すべき特定の箇所だけを指定する方法もあります。

# 全 WIP コミットを圧縮する(デフォルトは `--from @`)
jj squash --to x --from y

# WIP コミットの一部分をインタラクティブに圧縮する(デフォルトは `--from @`)
jj squash --to x --from y --interactive

ハンク、あなたを選んだわ!

もちろん、Juju ツーザーは美しいソフトウェアであり、この用途のための自動化機能も備えています!

absorb
コマンドは、あなたの現在のコミット内の各行またはヘンダがどの下流の変異コミットに属するかを特定し、自動的にそれらを圧縮する機能を持っています。これを使うたびには「魔法」のように感じます(理解不能な悪の黒い箱の黒魔術ではなく)、これはメガマージワークフローがこれほどシームレスなものとなることを可能にする Juju ツーザーの中核機能の一つです。

# 変更点を自動的に圧縮する(デフォルトは `--from @`)
jj absorb --from x

おっと、それは早すぎたな。

absorb
はあなたのコミット内のすべてを捉えるとは限りませんが、通常は少なくとも 90% の変更点はキャッチしてくれます。残りの部分は、下流で簡単に圧縮可能なものか、どの以前のコミットとも無関係なものになります。

便利なことに、私が所属する新コミットに必要な変更点を持っている場合でもそれほど複雑にはなりません。もしそのコミットが私が作業中のブランチの一つに属するなら、自分でリベースしてブックマークを移動させれば済みます。

jj commit
jj rebase --revision x --after y --before megamerge
jj bookmark move --from y --to x

このリベースの仕組みを詳しく理解するために分解してみましょう:

いくつかのコミットを移動します!

jj rebase # WIP コミット x... を移動しましょう --revision x # 彼らが y(例えば trunk())の後に来るように --after y # そしてメガマージの子となるように --before megamerge

少しロケット手術のようなもの、お楽しみください。

もし完全に新しい機能に取り組んだり、無関係なバグを修正したりしている場合、それはさらに簡単です!いくつかのエイリアスを使うと、メガマージに新しい変更点を非常に簡単に含めることができます:

テンプレート・エイリアスもあれば、テミング言語を使って Juju ツーザーがターミナルへログ出力する方法を変更できるものもありますし、ファイルセット・エイリアスもあります。これは revset エイリアスに似ていますが、revise ではなくファイルに対してアクションするもので、ファイルセット言語を使用します。

[revset-aliases]
# `to` に最も近いメージコミットを返す
"closest_merge(to)" = "heads(::to & merges())"

[aliases]
# 指定された revset をメガマージ下の新しいブランチとして挿入する
stack = ["rebase", "--after", "trunk()", "--before", "closest_merge(@)", "--revision"]

closest_merge(to)
が実際に何を行っているかについての簡単な説明:

heads(                 # トップロジカルなティップであるコミットのみを返す...
      ::to             # `to` の祖先の集合内において...
           & merges()) # ...そしてメージコミットでもあるもの。

この revset エイリアスを使って、

stack
は任意の revset をターゲットにして、trunk()(あなたの主要開発ブランチ)とメガマージ・コミットの間に挿入できます:

jj stack x::y

わあ、それはすてきですね!

もし複数の変更点スタックを並行して含める必要がある場合はより有用ですが、一つだけならもう一つのエイリアスを使ってメガマージ以降の全変更点スタックを取得することもできます:

[aliases]
stage = ["stack", "closest_merge(@).. ~ empty()"]

closest_merge(@).. # メガマージ・コミットに近い最も近い子孫を返す...

~ empty() # ...空のコミットなし。

こちらは入力がいらない!コミットを用意して「ステージ」してください:

jj stage

待った、どうやって?それができるんだな?

メガマージパズルの最後の欠落部分は(残念ながら)他の人の現実に対処することです:

こういうのをすべて最新の状態に保つにはどうすればよいか?

素晴らしい質問で、私自身も数ヶ月かけて一般的な意味合いで答えようとしていました。Juju ツーザーはワークツリー全体をメインブランチにリベースする非常に簡単な方法を持っています:

jj rebase --onto trunk()

すばらしい。

しかしながら、これはワークツリー全体が変更点の場合にのみ機能します。あなたが持っていないコミット(例えば追跡されていないブックマークや他人のブランチなど)を参照しようとすると、それらが書き換えられるのを防ぐため、Juju ツーザーは早めて停止します。

待てよ、そんなにすてきな話ではないな。どうすればいいんだ?

実際制御できるコミットのみを対象としてリベースすることで解決しましょう。これはしばらく苦戦しましたが、幸いにも Juju ツーザーコミュニティは素晴らしいものです。スティーブン・ジェニングズがこの素晴らしい revset を考案したことに拍手を送ります:

[aliases]
restack = ["rebase", "--onto", "trunk()", "--source", "roots(trunk()..) & mutable()"]

roots(
# 最も上流のコミットを取得...
trunk()..)             # ...trunk() のすべての子孫集合内において...                    & mutable() # ...そして変更を許可されているもののみを返す。

ワークツリー全体をリベースしようとする(例えば

jj rebase --onto trunk()
が試みるように)のではなく、実際に移動が許可されるコミットのみをターゲットにします。これにより、制御できないブランチや他人のブランチの上にスタックされた作業も残り続けます。これまでに失敗したことはなく、怪獣級の 9 倍のマルチコントリビュータ・メガマージであっても同様です!(それを早く 5 回言ってください。)

それでおしまい、これで良いよ!

TL;DR(長い目)

Juju ツーザーのメガマージは超クールで、多数の異なるワークストリームを同時に作業することを可能にします。それらがどのように機能するかの詳細な説明は全記事を読んでください。非常に使いやすく設定する場合は、以下の設定を

jj config edit --user
で追加してください:

[revset-aliases]
"closest_merge(to)" = "heads(::to & merges())"

[aliases]
# `jj stack <revset>` で特定の revs を含む
stack = ["rebase", "--after", "trunk()", "--before", "closest_merge(@)", "--revision"]

# `jj stage` でメガマージ後の全スタックを変更点へ含める
stage = ["stack", "closest_merge(@).. ~ empty()"]

# `jj restack` で変更点を trunk() にリベースする
restack = ["rebase", "--onto", "trunk()", "--source", "roots(trunk()..) & mutable()"]

absorb
と/または
squash --interactive
を使用して既存コミットへの新しい変更点を取得し、
commit
rebase
を使用してメガマージ下に新しいコミットを作成し、
stack
または
stage
で全ブランチをメガマージに移動させます。

  • 既存コミットへの変更点

    jj absorb
    jj squash --to x --interactive
    
  • 新しいコミットへの変更点

    jj rebase --revision y --after x
    
  • メガマージ上にスタックしたものをメガマージに含む

    jj stage
    
  • スタックされた revset をメガマージに含む

    jj stack w::z
    

メガマージは遠隔リポジトリへプッシュするためのものではありません;それらは単に表示用に全体の画像を見せるための便利な手段です。通常通りブランチを個別に公開することをお勧めします。

私はこれに常駐しており、あなたも同様できます。

メガマージはすべての方にとってのお茶の杯ではないかもしれません(私のワーキングツリーを見せて数人が恐怖した様子を見たことがあります)が、一度試せば、タスク間で移動するのにほとんど努力を要しないという恩恵を受ける可能性が高いでしょう。ぜひ試してみてください!


Git における競合解決以外の新しい変更点を含んだメージコミットは「悪魔のメージ(Evil merge)」と呼ばれます。しかし Juju ツーザーでは「悪魔」ではありません;Git より一貫性のあるモデルを持つためです。

コミット ID: b976b2a9c6ebbaada7fcd9d112a8390f2cb75b54
変更 ID: tqxoxrwqqqtmxvywmzmspstupqqkskqk
著者: イサク・コーブレイ isaac@isaaccorbrey.com(28 分前)
コミッター: イサク・コーブレイ isaac@isaaccorbrey.com(24 分前)
親: ttnyuntn storage: 一時的キャッシュのマニフォールドを整列化
親: qupprxtz ui: レイアウトのヒューリスティクスを脱ブロブナイズ化

io: ポラリティーバルブの詰まりを解消

regualr ファイル two.txt を追加:

1: # 黒い石英のスパフィン、私の誓いを裁け
泡立ち、泡立ち、苦労と災厄。

1 エイリアスは Juju ツーザーの非常に強力な部分です。確認すべき二つのタイプがあります:revset エイリアス(revset 言語を使用して一つ以上のコミットを返すカスタム関数を作成可能)、およびコマンドエイリアス(Juju ツーザーのデフォルト機能拡張し、独自の機能を追加可能)。

2 Juju ツーザーには変異コミットと不変コミットの概念があり、基本的にあなたが通常の基盤で変更できるコミットを決定します。これは主にリントであり、

--ignore-immutable
で上書きできるためですが、トラブルから身を守り続けてくれる良い機能です。
mutable()
immutable()
のエイリアスを使用して、それぞれ変異と不変のコミットのみを選択できます。

3

restack
が思った通りに動作しない場合、Austin Seipp からのこの設定を取り入れてください。私のデフォルト設定はレポ内の全可変コミットを restack しており、過去の可変ブランチが多数あり、まだ片付ける時間がなかった場合に悪く振る舞います。

[revset-aliases]
'stack()' = 'stack(@)'
'stack(x)' = 'stack(x, 2)'
'stack(x, n)' = 'ancestors(reachable(x, mutable()), n)'

[aliases]
restack = ["rebase", "--onto", "trunk()", "--source", "roots(trunk()..) & stack()"]

チップありがとう、コレ!

4 Andrew Hoog に Astro でフッターを調整してもらい感謝しています。フッターから他のフッターへの参照が可能であることを知っておられましたか?

同じ日のほかのニュース

一覧に戻る →

2026/04/21 5:39

ジョン・テルナス氏、次期アップル CEO に就任

## Japanese Translation: 欠落している要素は、キーポイントリストからの具体的なデータポイントおよび製品の詳細を組み込んだ改良されたバージョンを採用する価値があり、ソース資料の包括的な反映を確保するためには十分な重大さがあります。 **改善されたサマリー:** Apple は、John Ternus が 2026 年 9 月 1 日に CEO に就任し、Tim Cook を後継することを含む大規模なリーダーシップ移行を公式に確認しました。取締役会はこの計画を全会一致で承認し、Cook が 2011 年に CEO に就任してから歴史的な業績を認識しています。彼は社員の市場価値を約 3500 億ドルから 4 兆ドルへと成長させ、収益を 2011 会計年度の 1080 億ドルから 2025 会計年度の 4160 億ドル以上までほぼ四倍に拡大しました。Cook は日常業務から退き、執行議長として務める一方で、夏の間は CEO を辞任せず、円滑な引き継ぎを確保します。彼の指導の下、Apple は Apple Watch、AirPods、Vision Pro という象徴的な新カテゴリーを導入し、自社設計のシリコンに移行し、200 カ国以上および地域に店舗を持つ 500 店以上の小売網を拡大しました。また、チームメンバーが 100,000 名以上増加し、現在稼働している 25 億台超のデバイスベースを支援しています。 John Ternus は、2001 年に製品設計チームの一員として Apple に加入し、2021 年にハードウェアエンジニアリング担当副社長となり、2026 年 9 月 1 日に CEO の役職を引き継ぎ、取締役会に就任します。彼の指導の下、MacBook Neo、iPhone Air、フルモデルの iPhone 17 シリーズ、アクティブノイズキャンセレーション搭載のアバンスド AirPods、Apple Watch Ultra 3 に用いられた再生アルミニウムや 3D プリンティング钛など、重要なハードウェア革新を監督しました。さらに、Arthur Levinson は 2026 年 9 月 1 日に非執行会長からリードインディペンデントダイレクターへ移行します。この戦略的なシフトは、Apple の長期的なビジョンを固めるものであり、ハードウェア革新と持続可能性への深いコミットメントを持つ内部人材へのリーダーシップの引継ぎによって実現され、新鮮でありながら親しみのあるリーダーシップの下での継続性を確保します。

2026/04/21 4:51

『Soul Player C64 ―1MHz のコモドール64で動作する本物のトランスフォーマー』

## Japanese Translation: Soul Player C64 は、未修正の Commodore 64 でネイティブ速度(約 1MHz)で完全動作する縮小版变压器モデルを実行し、画期的な成果を達成しました。このシステムは、2 レイヤーのdecoder-only アーキテクチャを実装するため、手書きの 6502/6510 アセンブリ言語を使用しており、リアルなマルチヘッド因果的自己注意機構、RMSNorm、および ソフトマックス(128 エントリのルックアップテーブル経由で)を備えており、すべてが 1 つのフロッピーディスクに収まります。主要な技術的突破口としては、6502 プロセッサの精度限界を克服しつつ有意義な重みを保つために、標準の 17 ビットではなく 14 ビットのみで注意スコアをシフトすることなどが挙げられます。 ChatGPT のような現代の巨人と並んでモデルは動作しますが、約 25,000 int8 パラメータという厳格な制約下にあります:単語書式は 128 トークン(大文字を未知として扱う)、埋め込み次元は 32、最大トレーニングコンテキストウィンドウは 20 トークンです。推論にはトークンあたり約 60 秒かかりつつも、レガシーハードウェアでのローカル機械学習の探求へのアクセシブルなパスを提供します。 このプロジェクトには、ユーザーがカスタムモデルをトレーニングするための包括的なツールが含まれています:`train.py` は Quantization-Aware Training (QAT)、FakeQuantI8、およびラベルスムージングをサポートし、重みをコンパクトなバイナリ形式にエクスポートします;`build.py` は C64 バイナリをコンパイルします;`test.py` はほぼ 90 の厳密な検証テストにより安定性を確保します。リリースパッケージにはソースファイルと即座に実行可能なビルドの両方が含まれており、高度な AI コンセプトがハードウェア変更なしでビンテージシステム上で機能することを示しています。

2026/04/21 3:39

Kimí ベンダー検証ツール:推論プロバイダーの精度を検証します

## Japanese Translation: アリババ・クラウドは、オープンソース AI に関連する重要な信頼性課題に対処するため、推論精度を検証するためのツールである Kimi ベンダー verifier(KVV)とともに、Kimi K2.6 モデルを発表しました。この取り組みは、初期のベンチマークテストで識別された異常に対応しており、予期しないモデル振る舞いは、実際のモデル欠陥ではなく、サードパーティ製プラットフォーム間で不整合なデコードパラメータやインフラストラクチャの違いによって引き起こされていることが明らかになっていました。これらの課題を解決するため、アリババは単なる症状の検出から退き、vLLM、SGLang、KTransformers などの技術を用いて、デプロイメントスタック内の根本原因へ修正シフトしています。戦略には、思考モードにおいて厳格な API セット(Temperature=1.0、TopP=0.95)を適用し、6 つの主要ベンチマーク(Pre-Verification、OCRBench、MMMU Pro、AIME2025、K2VV ToolCall、SWE-Bench)を提供し、推論精度を速度よりも優先する公開リーダーボードの設立が含まれます。さらに、H20 GPU 上のインフラストラクチャ検証への早期アクセスや長時間タスク用の最適化済みスクリプトにより、ベンダーがパフォーマンスの崩壊を防ぐことができます。究極的には、この包括的なアプローチは、ユーザーがモデルの本質的な能力と技術的偏りを明確に区別でき、ホスティングプラットフォームに関わらず信頼できる AI サービスを受けられるような、信頼性の高いエコシステムの創出を目指しています。