# 画面設計書 35-ブランチ一覧

## 概要

本ドキュメントは、GitLabのリポジトリ内のブランチを一覧表示する画面（ブランチ一覧画面）の設計を記述したものである。

### 本画面の処理概要

本画面は、リポジトリ内のすべてのブランチを一覧表示し、ブランチの管理操作を提供する。アクティブなブランチ、古いブランチ（stale）、マージ済みブランチなどの状態別フィルタリング、およびブランチの作成・削除機能を提供する。

**業務上の目的・背景**：Git開発フローにおいて、ブランチ管理は重要な作業である。本画面は、プロジェクト内のすべてのブランチを把握し、不要になったブランチの整理、アクティブな開発状況の確認、マージ済みブランチのクリーンアップなどを効率的に行えるようにする。また、保護ブランチの状態確認やブランチルールの管理へのナビゲーションも提供する。

**画面へのアクセス方法**：
- プロジェクトナビゲーションの「Repository > Branches」
- ファイルツリー画面のブランチセレクターから「View all branches」
- URL直接入力: `/{namespace}/{project}/-/branches`

**主要な操作・処理内容**：
1. ブランチ一覧の表示（概要/アクティブ/古い/すべて）
2. ブランチのソート（名前順、更新日順）
3. ブランチの検索
4. 新規ブランチの作成
5. ブランチの削除
6. マージ済みブランチの一括削除
7. ブランチルール設定への遷移

**画面遷移**：
- 遷移元: プロジェクト概要画面、ファイルツリー画面、マージリクエスト画面
- 遷移先: ブランチ新規作成画面、ファイルツリー画面、コミット一覧画面、マージリクエスト作成画面

**権限による表示制御**：
- リポジトリ読み取り権限がない場合はアクセス拒否
- プッシュ権限がない場合は作成・削除ボタンが非表示
- 保護ブランチの削除は権限による制限

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | ブランチ管理 | 主機能 | リポジトリのブランチ一覧表示 |
| 25 | 保護ブランチ | 補助機能 | 保護ブランチ設定表示 |
| 28 | マージリクエスト作成 | 遷移先機能 | MR作成画面への遷移 |

## 画面種別

一覧

## URL/ルーティング

```
GET /{namespace}/{project}/-/branches
GET /{namespace}/{project}/-/branches/:state  (active|stale|all)
DELETE /{namespace}/{project}/-/branches/:id
DELETE /{namespace}/{project}/-/branches/merged_branches
```

**ルート定義**: `config/routes/repository.rb`
```ruby
get '/branches/:state', to: 'branches#index', as: :branches_filtered, constraints: { state: /active|stale|all/ }
resources :branches, only: [:index, :new, :create, :destroy] do
  get :diverging_commit_counts, on: :collection
end
delete :merged_branches, controller: 'branches', action: :destroy_all_merged
```

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| namespace | 入力 | String | Yes | プロジェクトの名前空間 |
| project | 入力 | String | Yes | プロジェクト名 |
| state | 入力 | String | No | 表示モード（overview/active/stale/all） |
| sort | 入力 | String | No | ソート順（name_asc/updated_asc/updated_desc） |
| search | 入力 | String | No | 検索キーワード |
| page | 入力 | Integer | No | ページ番号 |

## 表示項目

| 項目名 | 説明 | データソース |
|--------|------|-------------|
| タブ（Overview/Active/Stale/All） | 表示モード切り替え | @mode |
| ソートドロップダウン | ソート順の選択 | @sort |
| ブランチ名 | ブランチの名前 | branch.name |
| 最終コミットメッセージ | ブランチの最新コミット | branch.dereferenced_target |
| 最終更新日時 | 最終コミット日時 | branch.commit.committed_date |
| 著者アバター | 最終コミットの著者 | branch.commit.author |
| パイプラインステータス | CIパイプラインの状態 | @branch_pipeline_statuses |
| マージ済みバッジ | マージ済みかどうか | @merged_branch_names |
| 保護バッジ | 保護ブランチかどうか | branch.protected |
| デフォルトバッジ | デフォルトブランチかどうか | @project.default_branch |
| 差分コミット数 | デフォルトブランチとの差分 | diverging_commit_counts |

## イベント仕様

### 1-ページ読み込み

ブランチ一覧を取得し表示する。

**処理フロー**:
1. 表示モード（overview/active/stale/all）の決定
2. ソート順の決定
3. BranchesFinderでブランチ一覧を取得
4. マージ済みブランチ名の取得
5. パイプラインステータスの取得
6. ブランチごとのコミット情報をプリロード

### 2-タブ切り替え

表示モードを切り替える。

**処理**:
- Overview: アクティブ5件 + 古い5件を表示
- Active: 最近更新されたブランチを表示
- Stale: 長期間更新のないブランチを表示
- All: 全ブランチを表示

### 3-New branchボタン押下

ブランチ新規作成画面へ遷移する。

**遷移先**: `/{namespace}/{project}/-/branches/new`

### 4-Delete merged branchesボタン押下

マージ済みブランチを一括削除する。

**処理フロー**:
1. 確認モーダル表示
2. Branches::DeleteMergedServiceを非同期実行
3. 成功メッセージ表示

### 5-ブランチ削除ボタン押下

個別のブランチを削除する。

**処理フロー**:
1. 確認モーダル表示
2. Branches::DeleteServiceを実行
3. 成功/エラーメッセージ表示

### 6-ブランチ名クリック

ブランチのファイルツリー画面へ遷移する。

**遷移先**: `/{namespace}/{project}/-/tree/{branch_name}`

### 7-View branch rulesボタン押下

ブランチルール設定画面へ遷移する。

**遷移先**: `/{namespace}/{project}/-/settings/repository#js-branch-rules`

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ブランチ削除 | events | INSERT | ブランチ削除イベントの記録 |
| ブランチ削除 | push_event_payloads | INSERT | 削除イベント詳細 |
| マージ済み一括削除 | events | INSERT | 複数削除イベントの記録 |

### テーブル別更新項目詳細

#### events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | action | 5 (PUSHED) | プッシュアクション |
| INSERT | author_id | current_user.id | 実行ユーザー |
| INSERT | project_id | @project.id | 対象プロジェクト |

#### push_event_payloads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | action | 3 (REMOVED) | ブランチ削除 |
| INSERT | ref_type | 1 (BRANCH) | ブランチ参照 |
| INSERT | ref | 削除ブランチ名 | ブランチ名 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|---------------|----------|
| M001 | 成功 | "Branch was deleted." | ブランチ削除成功 |
| M002 | 成功 | "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes." | マージ済み一括削除開始 |
| M003 | エラー | "Failed to delete branch '...' " | ブランチ削除失敗 |
| M004 | エラー | "Cannot delete protected branch '...'" | 保護ブランチ削除試行 |
| M005 | 警告 | "Unsupported sort value." | 不正なソートパラメータ |
| M006 | 警告 | "Update your bookmarked URLs as filtered/sorted branches URL has been changed." | 旧URLリダイレクト時 |

## 例外処理

| 例外 | 発生条件 | 処理内容 |
|------|---------|---------|
| 403 Forbidden | 読み取り権限なし | アクセス拒否画面表示 |
| Gitlab::Git::CommandError | Gitalyエラー | サービス利用不可表示 |
| 404 Not Found | 不正なモード | 404エラー表示 |

## 備考

- Overviewモードでは最大5件ずつのアクティブ/古いブランチを表示
- マージ済みブランチの判定はinclude_identical: trueで同一コミットも含む
- パイプラインステータスは各ブランチの最新コミットから取得
- 差分コミット数は非同期で取得（diverging_commit_counts API）
- ページネーションはKeyset paginationを使用（Feature flag依存）

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ブランチ取得とフィルタリングの仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | branches_finder.rb | `app/finders/branches_finder.rb` | ブランチ検索・ソートロジック |
| 1-2 | branches_by_mode_service.rb | `app/services/projects/branches_by_mode_service.rb` | モード別取得ロジック |

**読解のコツ**: BranchesFinderはGitリポジトリから直接ブランチを取得し、ソート・フィルタリングを行う。モード（active/stale）はブランチの最終更新日で判定される。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | branches_controller.rb | `app/controllers/projects/branches_controller.rb` | indexアクション、destroy |

**主要処理フロー**:
1. **19-53行目**: `def index` - メインアクション
2. **22-23行目**: モードとソートの決定
3. **29行目**: `fetch_branches_by_mode` - ブランチ取得
4. **30行目**: `fetch_merge_requests_for_branches` - 関連MR取得
5. **36-38行目**: マージ済み判定とパイプラインステータス取得
6. **76-119行目**: `def create` - ブランチ作成
7. **122-136行目**: `def destroy` - ブランチ削除

#### Step 3: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.haml | `app/views/projects/branches/index.html.haml` | メインテンプレート構造 |
| 3-2 | _branch.html.haml | `app/views/projects/branches/_branch.html.haml` | ブランチ行パーシャル |
| 3-3 | _panel.html.haml | `app/views/projects/branches/_panel.html.haml` | Overviewパネルパーシャル |

**主要処理フロー**:
- **13-18行目**: タブナビゲーション（Overview/Active/Stale/All）
- **20-31行目**: アクションボタン群（View branch rules, New branch, Delete merged）
- **32-38行目**: ソートドロップダウン
- **50-52行目**: Overviewモード時のパネル表示
- **54-61行目**: 通常モード時のブランチリスト表示

#### Step 4: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | create_service.rb | `app/services/branches/create_service.rb` | ブランチ作成 |
| 4-2 | delete_service.rb | `app/services/branches/delete_service.rb` | ブランチ削除 |
| 4-3 | delete_merged_service.rb | `app/services/branches/delete_merged_service.rb` | マージ済み一括削除 |

### プログラム呼び出し階層図

```
Projects::BranchesController#index
    │
    ├─ fetch_mode
    │      └─ params[:state] の検証
    │
    ├─ fetch_branches_by_mode
    │      ├─ fetch_branches_for_overview (if overview)
    │      │      ├─ BranchesFinder (active)
    │      │      └─ BranchesFinder (stale)
    │      │
    │      └─ Projects::BranchesByModeService (other modes)
    │             └─ BranchesFinder
    │
    ├─ fetch_merge_requests_for_branches
    │
    ├─ repository.merged_branch_names
    │
    └─ Ci::CommitStatusesFinder
           └─ Pipeline status for each branch
```

### データフロー図

```
[入力]               [処理]                    [出力]

URL Parameters ───▶ BranchesController#index ───▶ HTML Response
  - state             │
  - sort              ├─▶ BranchesFinder ───▶ Branch List
  - search            │      │
  - page              │      └─▶ Git Repository
                      │
                      ├─▶ MergedBranchNames ───▶ Merge Status
                      │
                      └─▶ CommitStatusesFinder ───▶ Pipeline Status
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| branches_controller.rb | `app/controllers/projects/branches_controller.rb` | コントローラー | リクエスト処理 |
| index.html.haml | `app/views/projects/branches/index.html.haml` | テンプレート | メインビュー |
| _branch.html.haml | `app/views/projects/branches/_branch.html.haml` | パーシャル | ブランチ行表示 |
| _panel.html.haml | `app/views/projects/branches/_panel.html.haml` | パーシャル | Overviewパネル |
| branches_finder.rb | `app/finders/branches_finder.rb` | ファインダー | ブランチ検索 |
| create_service.rb | `app/services/branches/create_service.rb` | サービス | ブランチ作成 |
| delete_service.rb | `app/services/branches/delete_service.rb` | サービス | ブランチ削除 |
| delete_merged_service.rb | `app/services/branches/delete_merged_service.rb` | サービス | 一括削除 |
| repository.rb | `config/routes/repository.rb` | ルーティング | URL定義 |
