【ITニュース解説】A guide to using Graphite's stacked PRs for GitHub users
2025年09月19日に「Dev.to」が公開したITニュース「A guide to using Graphite's stacked PRs for GitHub users」について初心者にもわかりやすく解説しています。
ITニュース概要
Graphiteは、GitHubでの開発を効率化するツールだ。複数の変更を積み重ねた「スタックされたPR」で、大きな新機能を段階的に開発できる。コミットを簡単に修正・追加でき、過去の変更も柔軟に編集可能。これにより、Gitコンフリクトを削減し、レビューしやすいPRを実現する。
ITニュース解説
Graphiteは、GitHubを使ったソフトウェア開発において、複数の変更を効率的に管理し、プルリクエスト(PR)のワークフローを改善するためのツールである。システムエンジニアを目指す初心者にとって、GitとGitHubの基本的な操作を習得した上で、より複雑な機能開発やチーム開発で役立つ概念とツールの一つとなるだろう。
Graphiteが提唱する「Stacked PRs(積み重ねられたプルリクエスト)」という考え方は、名前から連想される「プルリクエストが積み重なっている」というよりも、「一連の変更が積み重なっている」と理解するのが適切だ。これは、一つの大きな新機能を実装するために必要な複数の小さな変更を、それぞれ独立したGitコミットとして扱い、それらを順番に積み重ねていく開発手法を指す。結果的に、スタック内の各変更がそれぞれGitHubのプルリクエストに対応するが、機能的にはこれら全ての変更が一つにまとまって、大きな機能を実現するためのプロセスを表現している。Graphiteの基本的な方針は、各変更を単一のGitコミットとして保持し、そのコミットを必要に応じて何度も修正しながら完成させていくことにある。
具体的なワークフローは次のように進む。
まず、新しい開発を始める際には、通常のGitワークフローと同様に、git checkout mainコマンドでリポジトリのメインブランチを最新の状態にする。その後、コードに最初の変更を加え、それをコミットする準備ができた段階で、gt createコマンドを使用する。このコマンドは、変更内容をコミットし、その変更に対応する新しいGitブランチを自動的に作成する。-aオプションですべての変更ファイルをステージングしたり、-mオプションでコミットメッセージを指定したりできる。
一度コミットした変更について、後日作業を再開し、さらに修正や追加を行いたい場合、新しいコミットを別に作成するのではなく、前回のコミットを修正する形で変更を統合する。これにはgt modify -aコマンドを使う。この操作により、一つの論理的な変更が常に単一のGitコミットとして保たれるため、履歴がすっきりし、後からの管理やレビューが容易になる。
最初の変更が一段落し、その変更の上にさらに別の変更、つまり論理的に次のステップとなる変更を追加したい場合は、再びgt create -a -m '次の変更のメッセージ'コマンドを使う。これにより、新しいコミットとそれに紐づくブランチが、現在の変更の上に積み重ねられる形で作成される。このプロセスを繰り返すことで、最終的な機能を実現するための複数の変更が、整然と積み重なったスタックが形成される。
Graphiteの大きな利点の一つは、スタック内の過去の任意の変更を簡単に編集できる柔軟性である。作業の途中で、以前に行った変更に修正が必要になった場合でも、gt lsコマンドでスタックの現在の状態と自分の位置を確認し、gt upやgt downといったコマンドを使って、修正したい過去の変更(コミット)に対応するブランチに移動できる。目的の変更に移動したら、コードを修正し、前述のgt modify -aコマンドでそのコミットを更新する。Graphiteは、この変更によって生じるGitの履歴の調整を、内部でgit rebaseを実行することで自動的に処理し、後続の変更も適切に更新してくれる。これにより、開発者はGitの複雑な履歴操作を直接行わずに、過去の変更を修正できる。
定期的に作業内容をGitHubに保存するためには、gt submitコマンドを使用する。このコマンドは、スタック内のすべての変更(コミット)に対応するプルリクエストを一括でGitHub上に作成し、プッシュする。これらのプルリクエストは、すぐにレビューに出す必要はなく、GraphiteのウェブインターフェースやGitHubのドラフト機能を利用して、まだ準備ができていないことを示すことが可能だ。
スタックとして作成された変更は、個々のプルリクエストとしてレビューされる。レビュー担当者は、一つ一つの小さな変更を順番に確認できるため、レビューの負担が軽減され、コードの品質向上に繋がる。GitHub上では、下位の依存するプルリクエストがマージされていないと、上位のプルリクエストのCIチェックが失敗するように設定することも可能で、誤った順序でのマージを防ぐ仕組みも導入できる。
開発中にメインブランチに他の開発者からの変更がマージされた場合、自分のスタックをメインブランチの最新の状態に同期させる必要がある。これにはgt syncコマンドを使用する。このコマンドは、スタック内の各変更に対してGitのrebase操作を自動的に実行するのと同等だ。もし競合が発生した場合は、通常のGitワークフローと同様に、指示に従って手動で競合を解決する必要がある。各変更が単一のコミットとして保たれているため、競合解決も比較的容易になることが多い。
Graphiteを使用している間も、git logのような読み取り専用のGitコマンドは引き続き利用可能で、履歴の確認などに役立つ。しかし、git commitやgit push、git rebase、git merge、git pullといった、履歴を書き換えたり、ブランチを統合したりする一部のGitコマンドは、Graphiteのワークフローと競合する可能性があるため、gt create、gt modify、gt submit、gt syncといったGraphiteの専用コマンドを使用することが推奨される。これにより、スタックの一貫性が保たれ、意図しない問題の発生を防ぐことができる。Graphiteは、マージされたブランチを自動的に削除する機能も提供し、クリーンアップの手間を省く。
このGraphiteを使ったアプローチの主な利点は、事前に全ての開発計画を完璧に立てる必要がないことだ。コードが機能するまでgt modifyを使って最後のコミットを何度も修正し、満足したら次の変更をスタックに追加するという柔軟な開発が可能となる。そして、いつでもgt up/gt downとgt modifyを使って過去の変更に戻って修正できるため、Gitの履歴を積極的に編集するという考え方を受け入れることが重要だ。各論理的な変更を単一のコミットとして保つことで、競合解決が容易になり、レビュー担当者も理解しやすい小さなプルリクエストとして作業を進められるという大きなメリットが得られる。これは、システム開発における変更管理とコードレビューの効率を大幅に向上させる実践的なアプローチだと言えるだろう。