PJR-199G develop から main への昇格時にコミットをまとめる方式を確定する
1. 概要
PJR-T7ZQ の決定により、遷移時の commit policy は変更せず、雑音の削減は develop から main への昇格境界で行うこととした。まとめ方の具体は検証を伴うため本項目で確定する。squash merge は祖先関係が記録されず、次回の昇格で develop の過去コミットが未マージ扱いとなり競合が繰り返される。main から develop への逆マージも履歴にあるため、双方向のマージが成立する方式を選ぶ必要がある。push 済み履歴の書き換えは行わない。PJR-TPY9 の完了後に有効となる。
2. 完了条件
develop → mainの昇格でコミットをまとめる方式が決まり、理由が記録されている。squash merge、昇格前の一時ブランチでの整理、遷移コミットのみの除外などを比較する。- 祖先関係の扱いが明確である。squash merge を採る場合、次回の昇格で過去コミットが未マージ扱いになる問題への対処を含める。
mainからdevelopへの逆マージが引き続き成立する。現在の履歴には双方向のマージがあり、これを壊さない。- push 済み履歴を書き換えない。force-push を伴う方式は採らない。
- 手順が文書化され、リポジトリ管理者が実施できる。
git-branching-standard.mdへ反映する。 - 実リポジトリの使い捨て clone で方式を検証する。実際の
develop → main昇格そのものは行わない。mainは branch protection の対象であり、push は人の操作だからである。clone 上で昇格を再現し、mainの履歴が意図した粒度になること、その後のmain → develop逆マージが成立すること、さらに次回の昇格で過去コミットが未マージ扱いにならないことを確認する。検証の手順と結果を記録する。 - まとめた後も
register historyが全項目を復元できることを確認する。移行済みの individual event は個票内にあるため commit 粒度に依存しないが、実際に確認する。 - PJR-TPY9 の完了後に実施する。完了前にまとめると
register historyの再構成が壊れる(PJR-TPY9 は完了済み、移行も実施済みである)。
本項目で行わないこと
- 実際の
develop → main昇格。方式が決まった後、リポジトリ管理者が実施する。 - push および force-push。
- 過去に push 済みの履歴の書き換え。
調査済みの事実
mainは現在--no-ffマージで develop の全コミットを取り込んでおり、遷移コミットもそのまま載っている。1つの項目でstart/wait/review/closeの4件前後が並ぶ。- 全コミット2,935件のうち register の遷移コミットは305件で約10%を占める。
- PJR-TPY9 の完了と移行により、検証時点の
register historyは770件中766件を個票内の event から読む。Git 履歴へのフォールバックは PJR-TPY9 自身の4件だけである。この4件を復元するには、該当 commit が現在の履歴から到達可能でなければならない。 Merge remote-tracking branch 'origin/main'という main から develop への逆マージが履歴にある。双方向のマージが行われている。- squash merge は祖先関係を記録しないため、long-lived branch 同士では次回のマージで競合が繰り返される。
git-branching-standard.mdはdevelop → main昇格を承認ゲートの境界と定めており、mainには branch protection と CODEOWNERS を要求している(PJR-BJ97 で整備済み)。
3. 作業内容
3.1. 候補比較
| 方式 | main の見え方 | 祖先関係・次回昇格 | register history | 判断 |
|---|---|---|---|---|
--no-ff merge と first-parent 表示 | first-parent では昇格 merge commit 1件 | develop の全 commit が main の祖先になり、逆マージと次回昇格を通常の merge で扱える | Git fallback を含む全履歴を復元できる | 採用 |
| squash merge | main には集約 commit 1件だけ | develop の commit が祖先にならず、次回も未マージとして残る | PJR-TPY9 の Git fallback 4件を失う | 却下 |
| 一時ブランチで rebase / cherry-pick | 選別後の commit だけを main に置ける | commit ID を作り直し、元の develop との祖先関係を記録しない | squash と同じく Git fallback を失う | 却下 |
| register 遷移 commit だけを除外して再構成 | プロダクト commit だけを並べられる | 選別した commit を作り直す必要があり、双方向 merge の基準にならない | 遷移 commit にある個票の現在値も欠落する | 却下 |
採用方式では commit を物理的に削除しない。develop → main の昇格を必ず --no-ff の merge commit で記録し、プロダクト変更を追うときは main の first-parent 履歴を正規の表示とする。これにより、細かな commit は監査可能な DAG に保持しながら、昇格単位を1行で追える。通常の git log には develop の詳細 commit も表示されるため、「まとめる」とは first-parent 上での論理的な集約を意味する。
3.2. 使い捨て clone での検証
実リポジトリをローカルの一時ディレクトリへ clone し、main の b4203fc0 と project/prj-0001/develop の 50374a66 を起点に再現した。実リポジトリの branch、commit、設定は変更せず、push も行っていない。
| 確認項目 | 結果 |
|---|---|
1回目の --no-ff 昇格 | tree は develop と一致した。main から増えた278 commitのうち first-parent は昇格 merge commit 1件だった |
| 祖先関係 | 昇格前の develop について git rev-list <develop> --not <main> は0件となった |
main → develop と2回目の昇格 | main 側と develop 側へ各1変更を追加して逆マージ後に再昇格し、競合なく成功した。merge-base は2回目の develop 先端と一致した |
| 2回目の tree と祖先関係 | tree は develop と一致し、2回目の develop についても未マージ commit は0件だった |
register history | 昇格前後のJSONが一致した。770 event・261項目を復元し、内訳は個票 event 766件、PJR-TPY9 の Git fallback 4件だった |
| squash merge の対照実験 | tree は一致したが277 commitが未マージで、merge-base は昇格前の main のままだった。履歴は766件となり、PJR-TPY9 の fallback 4件を失った |
3.3. 実施状況
| No | 作業 | 担当 | 状態 | メモ |
|---|---|---|---|---|
| 1 | まとめ方の候補を比較し、方式を決めて理由を記録する | ARC | done | --no-ff merge と first-parent 表示を採用 |
| 2 | 手順を git-branching-standard.md へ反映する | ARC | done | 管理者向けの確認条件と禁止方式を明記 |
| 3 | 使い捨て clone で昇格を再現し粒度と逆マージを確認する | ARC | done | 実昇格・push・push済み履歴の書き換えは未実施 |
4. 対応結果
develop → mainは squash / rebase で commit を作り直さず、merge commit を必ず作る方式に確定した。昇格単位の履歴はgit log --first-parentで参照する。- Gitブランチ標準へ、昇格方式、祖先関係の完了確認、first-parent の位置付け、squash / rebase merge の禁止を反映した。
- ブランチワークフローガイドへ、管理者が実施する事前同期、PR の merge 方式、昇格後の祖先確認、
main → develop同期、次回差分確認の手順を反映した。 - 使い捨て clone で2回の昇格と逆マージを再現し、意図した first-parent 粒度、tree の一致、祖先関係、
register history770件の完全一致を確認した。対照実験により squash merge では完了条件を満たさないことも確認した。 - 実際の昇格、push、force-push、push済み履歴の書き換えは行っていない。実昇格はリポジトリ管理者が規約とガイドに従って実施する。
レビューで判明した適用範囲の制約(追記):
- 本方式は次回の昇格から有効になる。実リポジトリの現在の
mainに対してgit log --first-parent mainを実行すると2,675件中2,289件が表示され、exec(register ...)の遷移 commit がそのまま並ぶ。集約は効いていない。 - 原因は
mainの現在の先端b4203fc0にある。この merge は第1 parent がdevelop側のce4132f4、第2 parent がmain側の5ccd851bであり、develop上で実行してmainを fast-forward した形である。確定した方式とは親子関係が逆向きのため、mainの first-parent 系列がdevelopの詳細履歴へ潜り込んでいる。 - 既存の first-parent 系列を集約するには push 済み履歴の書き換えが必要であり、本規約が禁止する。過去区間はそのまま残す。
- 検証は使い捨て clone 上の合成シナリオで行っており、実リポジトリの first-parent 系列がすでに汚れている事実は確認されていなかった。この制約を Gitブランチ標準 の「適用範囲」と ブランチワークフローガイド の確認手順へ追記した。
- 昇格担当者への注意として、merge の向きが逆にならないこと(
mainを checkout してdevelopを merge する、または PR の base をmain・head をdevelopとする)を規約へ明記した。
5. 関連ドキュメント
- 根拠となる決定: PJR-T7ZQ Registerの状態遷移に対するcommit policyを選定する
- 前提となる第1段: PJR-TPY9 Register履歴をGitコミット粒度から分離する
- 反映先の規約: Gitブランチ標準
- 承認ゲートの整備: PJR-BJ97 CODEOWNERS 未整備によりPR承認の職務分離が強制されていない