# Git History Visualization Specification

## Requirements

### Functional Requirements

1. **View Commit History**: Display all commits in a repository
2. **Graph Visualization**: Show commits as nodes with branch/merge lines
3. **List View**: Alternative linear view of commits
4. **Commit Details**: Click to view full commit info and diff
5. **Branch Display**: Show branch names on commits
6. **Tag Display**: Show tags on commits
7. **View Toggle**: Switch between graph and list views

### Non-Functional Requirements

1. **Performance**: Load first 100 commits in < 2 seconds
2. **Responsiveness**: Graph should render smoothly up to 500 commits
3. **Compatibility**: Work with bare repositories and mirror clones
4. **Read-only**: No write operations to repository

## API Specification

### GET /projects/{project_id}/repositories/{repo_id}/history

Retrieve commit history for a repository.

**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| view | string | "graph" | "graph" or "list" |
| branch | string | null | Filter by branch name |
| limit | integer | 100 | Max commits to return |
| offset | integer | 0 | Skip first N commits |

**Response 200:**
```json
{
  "commits": [
    {
      "hash": "full-sha-hash",
      "short_hash": "abc1234",
      "parents": ["parent-hash-1", "parent-hash-2"],
      "author": "John Doe",
      "email": "john@example.com",
      "date": "2026-05-19",
      "timestamp": 1716123456,
      "message": "feat: add new feature",
      "branches": ["main"],
      "tags": []
    }
  ],
  "branches": ["main", "develop", "feature/x"],
  "total_commits": 250,
  "graph_data": {
    "nodes": [
      {
        "hash": "abc1234",
        "x": 0,
        "y": 0,
        "column": 0
      }
    ],
    "edges": [
      {
        "from_hash": "abc1234",
        "to_hash": "def5678",
        "type": "parent"
      }
    ]
  }
}
```

### GET /projects/{project_id}/repositories/{repo_id}/commits/{commit_hash}

Get detailed information about a specific commit.

**Response 200:**
```json
{
  "hash": "full-sha-hash",
  "short_hash": "abc1234",
  "parents": ["parent-hash"],
  "author": "John Doe",
  "email": "john@example.com",
  "date": "2026-05-19",
  "timestamp": 1716123456,
  "message": "feat: add new feature",
  "body": "Detailed description here",
  "stats": {
    "files_changed": 3,
    "insertions": 45,
    "deletions": 12
  },
  "files": [
    {
      "path": "src/main.py",
      "change_type": "modified",
      "insertions": 20,
      "deletions": 5,
      "diff": "diff content here"
    }
  ]
}
```

## Frontend Components

### GitHistoryPage
Main page component that orchestrates the view.

### GraphView
SVG-based commit graph visualization.

**Props:**
- `commits`: Commit[]
- `graphData`: GraphData
- `selectedCommit`: string | null
- `onCommitSelect`: (hash: string) => void

### ListView
Linear commit list.

**Props:**
- `commits`: Commit[]
- `selectedCommit`: string | null
- `onCommitSelect`: (hash: string) => void

### CommitDetails
Panel showing commit details and diff.

**Props:**
- `commit`: CommitDetail | null

### DiffViewer
Component to display git diff with syntax highlighting.

**Props:**
- `files`: FileChange[]

## Data Models

### Commit
```typescript
interface Commit {
  hash: string;
  short_hash: string;
  parents: string[];
  author: string;
  email: string;
  date: string;
  timestamp: number;
  message: string;
  branches: string[];
  tags: string[];
}
```

### CommitDetail
```typescript
interface CommitDetail extends Commit {
  body: string;
  stats: {
    files_changed: number;
    insertions: number;
    deletions: number;
  };
  files: FileChange[];
}
```

### FileChange
```typescript
interface FileChange {
  path: string;
  change_type: "added" | "modified" | "deleted" | "renamed";
  insertions: number;
  deletions: number;
  diff: string;
}
```

## URL Structure

```
/projects/:projectId/repositories/:repoId/history
```

## Error Codes

| Error Code | Description | User Message |
|------------|-------------|--------------|
| REPO_EMPTY | Repository has no commits | "This repository has no commits yet" |
| GIT_ERROR | Git command failed | "Failed to load repository history" |
| COMMIT_NOT_FOUND | Commit hash not found | "Commit not found" |
| INVALID_BRANCH | Branch doesn't exist | "Branch not found" |

## Testing Strategy

### Backend Tests
- Test git log parsing with various repo structures
- Test commit detail extraction
- Test error handling for empty repos

### Frontend Tests
- Test graph rendering with sample data
- Test list view rendering
- Test commit selection and details display
- Test view toggle

### Integration Tests
- End-to-end flow: load history → select commit → view details
