# mehr finish

Complete the task by creating a pull request or merging locally.

## Synopsis

```bash
mehr finish [flags]
```

**Aliases:** `fi`, `done`

## Description

The `finish` command completes the current task by:

1. Running quality checks (if available)
2. Creating a pull request (if provider supports it), OR merging locally
3. Keeping the task branch by default (use `--delete` to remove)
4. Keeping the work directory by default (use `--delete-work` to remove, or configure `workflow.delete_work_on_finish` in `config.yaml`)

**Default behavior**:
- For `github:` or `gitlab:` tasks → Creates PR/MR automatically
- For `file:`/`directory:` tasks on GitHub/GitLab-hosted projects → Creates PR automatically (uses git remote)
- For other tasks (no git remote, or unsupported hosts) → Prompts to choose (merge / mark done / cancel)
- Use `--merge` flag to force local merge (skips PR creation)

**Configuration:**

To make local merge the default (skip PR creation):

```yaml
workflow:
  prefer_local_merge: true
```

With this setting, `mehr finish` behaves like `mehr finish --merge`. The `--merge` flag is still respected when passed explicitly.

## Flags

| Flag               | Short | Type   | Default | Description                              |
|--------------------|-------|--------|---------|------------------------------------------|
| `--merge`          |       | bool   | false   | Force local merge instead of creating PR |
| `--delete`         |       | bool   | false   | Delete task branch after merge           |
| `--push`           |       | bool   | false   | Push to remote after local merge         |
| `--squash`         |       | bool   | false   | Squash merge (single commit)             |
| `--target`         | `-t`  | string | auto    | Target branch to merge into              |
| `--no-quality`     |       | bool   | false   | Skip quality checks                      |
| `--quality-target` |       | string | quality | Make target for quality checks           |
| `--delete-work`    |       | bool   | false   | Delete work directory after finishing    |
| `--draft`          |       | bool   | false   | Create PR as draft                       |
| `--pr-title`       |       | string | auto    | Custom PR title                          |
| `--pr-body`        |       | string | auto    | Custom PR body                           |

## Examples

### Basic Finish (GitHub task)

```bash
mehr finish
```

For `github:` tasks, automatically creates a PR:

```
Finishing task a1b2c3d4...
Running quality checks...
  make quality: PASSED
Pushing branch to origin...
Creating pull request...
  PR #42: [#5] Add authentication feature
  https://github.com/owner/repo/pull/42
Task completed!
```

### Basic Finish (file task on GitHub project)

```bash
mehr finish
```

For `file:`/`directory:` tasks on a GitHub-hosted project, automatically creates a PR using the git remote:

```
Finishing task a1b2c3d4...
Running quality checks...
  make quality: PASSED
Pushing branch to origin...
Creating pull request...
  PR #42: Implementation
  https://github.com/owner/repo/pull/42
Task completed!
```

### Basic Finish (file task without git remote)

```bash
mehr finish
```

For `file:`/`directory:` tasks without a supported git remote, prompts for action:

```
The provider for this task does not support pull requests.
What would you like to do?
  1. Merge changes to target branch locally
  2. Mark task as done (no merge)
  3. Cancel

Enter choice (1-3):
```

### Force Local Merge

```bash
mehr finish --merge
```

Perform local merge instead of creating PR (works for any provider).

### Merge and Delete Branch

```bash
mehr finish --merge --delete
```

Merge locally and clean up the task branch.

### Merge and Push

```bash
mehr finish --merge --push --delete
```

Full local workflow: merge, push to remote, delete branch.

### Create Draft PR

```bash
mehr finish --draft
```

Creates a draft PR for early feedback (GitHub tasks only).

### Custom PR Title and Body

```bash
mehr finish --pr-title "Fix: Authentication bug" --pr-body "Resolves login flow issue"
```

Override the auto-generated PR title and body.

### Squash Merge

```bash
mehr finish --merge --squash
```

Create a single commit instead of preserving individual commits.

### Different Target Branch

```bash
mehr finish --merge --target develop
```

Merge to `develop` instead of auto-detected base branch.

### Skip Quality Checks

```bash
mehr finish --no-quality
```

Skip running `make quality`.

### Custom Quality Target

```bash
mehr finish --quality-target lint
```

### Delete Work Directory

```bash
mehr finish --delete-work
```

Delete the work directory after finishing. By default, the work directory is kept for reference. Configure the default behavior in `config.yaml`:

```yaml
workflow:
  delete_work_on_finish: true   # Auto-delete on finish
```

**Precedence:** CLI flag (`--delete-work`) > config (`delete_work_on_finish`) > default (`false`)

## Quality Checks

If your project has a Makefile with a `quality` target, it runs automatically:

```makefile
quality:
	go fmt ./...
	golangci-lint run
	go test ./...
```

If quality checks modify files (e.g., auto-formatting), you'll be prompted:

```
Quality checks modified files:
  - src/api/handler.go (formatted)

Continue with modified files? [y/N]
```

## What Happens

### With PR Creation (default for GitHub/GitLab tasks or git remotes)

1. **Quality Checks** (unless skipped)
2. **Push branch** to remote
3. **Create PR** via provider API (uses task provider or git remote as fallback)
4. **Task marked done** (branch preserved)

> **Note**: For `file:` or `directory:` tasks, Mehrhof automatically detects if your project is hosted on GitHub/GitLab from the git remote and creates a PR there. No additional configuration needed.

### With Local Merge (`--merge` flag)

1. **Quality Checks** (unless skipped)
2. **Switch** to target branch
3. **Merge** (regular merge with `--no-ff` by default, use `--squash` for squash merge)
4. **Push** (if `--push` flag used)
5. **Cleanup** (if `--delete` flag used)
6. **Task marked done**

## Pull Request Contents

The PR is automatically populated with:

- **Title**: `[#123] Task title` or `Task title`
- **Body**:
  - Task description
  - Specifications summary
  - Changed files (diff stat)
  - Test plan checklist

Example:

```markdown
## Summary

Implementation for: Add authentication feature

Closes #123

## Implementation Details

### Specification 1
[First 500 chars of spec...]

## Changes

```
 src/auth/jwt.go       | 45 +++++++++++++++++++
 src/auth/middleware.go | 89 +++++++++++++++++++++++++++++++++++
 src/api/routes.go      | 12 +++++
```

## Test Plan

- [ ] Manual testing
- [ ] Unit tests pass
- [ ] Code review

---
*Generated by [Mehrhof](https://github.com/valksor/go-mehrhof)*
```

## Merge Commit

When using local merge with `--squash`, creates a single commit:

```
[#123] Complete: Add authentication feature

Implemented JWT-based authentication with:
- Login endpoint
- Logout endpoint
- Token refresh

Task: a1b2c3d4
```

**Default behavior** (without `--squash`): Creates a merge commit that preserves the full branch history using `git merge --no-ff`.

## Error Handling

### Merge Conflicts

```
Error: Merge conflict detected
Files with conflicts:
  - src/api/routes.go

Resolve conflicts and run:
  git add .
  mehr finish
```

### Quality Check Failures

```
Error: Quality checks failed
  golangci-lint: 2 issues found

Fix issues and retry:
  mehr finish
```

### Dirty Working Directory

```
Error: Working directory has uncommitted changes
Commit or stash changes before finishing.
```

## Aborting Finish

If finish is interrupted, recover with:

```bash
git status

git merge --abort

git checkout task/a1b2c3d4
```

## Web UI

Prefer a visual interface? See [Web UI: Finishing](/web-ui/finishing.md).

## See Also

- [abandon](/cli/abandon.md) - Abandon without merging
- [review](/cli/review.md) - Review before finishing
- [Workflow](/concepts/workflow.md) - Task lifecycle
