---
title: "Merging"
description: "Combine changes from branches with conflict resolution and merge strategies"
---

# Merging

Merging combines changes from one branch into another. TraceRTM provides multiple merge strategies and conflict resolution tools to handle complex merge scenarios.

## Basic Merging

### Merge a Branch

```python
from tracertm import TraceRTMClient

client = TraceRTMClient()

# Merge feature branch into main
result = client.merge_branch(
    source="feature/oauth2",
    target="main"
)

print(f"Merged: {result.merged_count} items")
print(f"Conflicts: {result.conflict_count}")
```

### CLI Merge

```bash
# Merge branch
tracertm branch merge feature/oauth2 --to main

# Output:
# Merging feature/oauth2 → main
# ════════════════════════════════════════
# Merged: 5 items
# Conflicts: 0
# Status: Success

# Merge completed
```

## Merge Strategies

### Fast-Forward Merge

When target branch has no new changes:

```python
result = client.merge_branch(
    source="feature/oauth2",
    target="main",
    strategy="fast_forward"
)

# Source changes are directly applied
# No merge commit created
```

```
Before:
main:      A---B
                \
feature:         C---D---E

After (fast-forward):
main:      A---B---C---D---E
```

### Three-Way Merge

When both branches have changes:

```python
result = client.merge_branch(
    source="feature/oauth2",
    target="main",
    strategy="three_way",
    message="Merge OAuth2 feature"
)

# Creates a merge commit combining both branches
```

```
Before:
main:      A---B---F---G
                \
feature:         C---D---E

After (three-way):
main:      A---B---F---G---M (merge commit)
                \       /
feature:         C---D---E
```

### Squash Merge

Combine all source changes into a single change:

```python
result = client.merge_branch(
    source="feature/oauth2",
    target="main",
    strategy="squash",
    message="Add OAuth2 authentication support"
)

# All feature branch changes become one change in main
```

```
Before:
main:      A---B
                \
feature:         C---D---E (3 changes)

After (squash):
main:      A---B---S (single squashed change)
```

### Rebase

Apply source changes on top of target:

```python
result = client.rebase_branch(
    branch="feature/oauth2",
    onto="main"
)

# Feature changes are replayed on top of main
```

```
Before:
main:      A---B---F---G
                \
feature:         C---D---E

After (rebase):
main:      A---B---F---G
                        \
feature:                 C'---D'---E' (rebased)
```

## Conflict Resolution

### Detecting Conflicts

```python
# Check for conflicts before merging
conflicts = client.check_merge_conflicts(
    source="feature/oauth2",
    target="main"
)

if conflicts:
    print("Conflicts detected:")
    for conflict in conflicts:
        print(f"  {conflict.item_id}: {conflict.field}")
        print(f"    Source: {conflict.source_value}")
        print(f"    Target: {conflict.target_value}")
```

### Conflict Types

| Type | Description | Example |
|------|-------------|---------|
| Field conflict | Same field changed differently | Description edited in both branches |
| Delete conflict | Item deleted in one, modified in other | Feature deleted vs updated |
| Link conflict | Same link modified differently | Link type changed |

### Resolving Conflicts

```python
# Start merge with conflicts
merge = client.start_merge(
    source="feature/oauth2",
    target="main"
)

if merge.has_conflicts:
    for conflict in merge.conflicts:
        # Resolve each conflict
        if conflict.item_id == "FEAT-001":
            # Keep source version
            client.resolve_conflict(
                merge_id=merge.id,
                item_id=conflict.item_id,
                resolution="source"
            )
        else:
            # Keep target version
            client.resolve_conflict(
                merge_id=merge.id,
                item_id=conflict.item_id,
                resolution="target"
            )

    # Complete merge after resolving all conflicts
    result = client.complete_merge(merge.id)
```

### Resolution Options

```python
# Keep source branch version
client.resolve_conflict(merge_id, item_id, resolution="source")

# Keep target branch version
client.resolve_conflict(merge_id, item_id, resolution="target")

# Merge both (for compatible changes)
client.resolve_conflict(merge_id, item_id, resolution="both")

# Custom resolution
client.resolve_conflict(
    merge_id,
    item_id,
    resolution="custom",
    custom_value={"description": "Merged description text"}
)
```

### CLI Conflict Resolution

```bash
# Attempt merge
tracertm branch merge feature/oauth2 --to main

# Output:
# Merging feature/oauth2 → main
# ════════════════════════════════════════
# Conflicts detected (2):
#   FEAT-001: description
#   CODE-005: status
#
# Use 'tracertm merge resolve' to fix conflicts

# Interactive resolution
tracertm merge resolve

# Output:
# Conflict 1/2: FEAT-001 (description)
# ────────────────────────────────────────
# SOURCE (feature/oauth2):
#   OAuth2 authentication with Google SSO
#
# TARGET (main):
#   OAuth2 authentication with enterprise support
#
# Resolution:
#   [s] Keep source
#   [t] Keep target
#   [b] Keep both
#   [c] Custom
#   [q] Quit
#
# Choice: c
# Enter custom value: OAuth2 authentication with Google SSO and enterprise support
# ✓ Resolved FEAT-001

# Resolve using strategy
tracertm merge resolve --strategy source  # All conflicts use source
tracertm merge resolve --strategy target  # All conflicts use target
```

## Merge Policies

### Required Reviews

```yaml
# .tracertm/config.yaml
merging:
  policies:
    main:
      require_review: true
      min_reviewers: 1

    release/*:
      require_review: true
      min_reviewers: 2
      require_approval: ["lead", "qa"]
```

### Merge Checks

```yaml
merging:
  checks:
    # Require all tests pass
    require_tests: true

    # Require validation pass
    require_validation: true

    # Require no broken links
    require_link_integrity: true

    # Custom checks
    custom_checks:
      - name: "coverage_check"
        command: "tracertm coverage --check --min 80"
```

### Auto-Merge

```yaml
merging:
  auto_merge:
    enabled: true

    conditions:
      - no_conflicts: true
      - all_checks_pass: true
      - approved: true

    branches:
      - pattern: "dependabot/*"
        require_checks: true
```

## Merge Previews

### Preview Changes

```python
# Preview merge without applying
preview = client.preview_merge(
    source="feature/oauth2",
    target="main"
)

print(f"Items to merge: {preview.total_changes}")
print(f"Potential conflicts: {preview.potential_conflicts}")

for change in preview.changes:
    print(f"{change.item_id}: {change.change_type}")
    print(f"  Fields: {change.affected_fields}")
```

### CLI Preview

```bash
# Preview merge
tracertm branch merge feature/oauth2 --to main --dry-run

# Output:
# Merge Preview: feature/oauth2 → main
# ════════════════════════════════════════
#
# Changes (5):
#   FEAT-001: description, metadata.story_points
#   CODE-001: status
#   CODE-015: new item
#   TEST-022: new item
#   LINK-042: new link
#
# Potential Conflicts (1):
#   FEAT-001.description: Modified in both branches
#
# This is a dry-run. No changes were made.
```

## Merge History

### View Merge History

```python
# Get merge history
history = client.get_merge_history(branch="main")

for merge in history:
    print(f"{merge.timestamp}: {merge.source} → {merge.target}")
    print(f"  By: {merge.merged_by}")
    print(f"  Items: {merge.item_count}")
    print(f"  Strategy: {merge.strategy}")
```

```bash
# CLI merge history
tracertm merge history --branch main

# Output:
# Merge History for main
# ════════════════════════════════════════
# 2024-12-10 14:30  feature/oauth2 → main
#   By: developer@example.com
#   Items: 5, Strategy: three_way
#
# 2024-12-08 09:15  hotfix/security → main
#   By: admin@example.com
#   Items: 2, Strategy: fast_forward
```

### Revert Merge

```python
# Revert a merge
client.revert_merge(
    merge_id="merge-123",
    reason="Feature not ready for release"
)
```

```bash
# CLI revert
tracertm merge revert merge-123 --reason "Feature not ready"
```

## Advanced Scenarios

### Cherry-Pick Changes

Apply specific changes without full merge:

```python
# Cherry-pick specific items
client.cherry_pick(
    source_branch="feature/oauth2",
    target_branch="main",
    items=["CODE-015", "TEST-022"]  # Only these items
)
```

```bash
# CLI cherry-pick
tracertm cherry-pick CODE-015 TEST-022 --from feature/oauth2 --to main
```

### Merge Multiple Branches

```python
# Octopus merge
result = client.merge_branches(
    sources=["feature/auth", "feature/ui", "feature/api"],
    target="main"
)
```

### Partial Merge

```python
# Merge only certain types
result = client.merge_branch(
    source="feature/oauth2",
    target="main",
    include_types=["feature", "code"],  # Exclude tests
    exclude_items=["FEAT-999"]  # Exclude specific items
)
```

## Best Practices

### 1. Always Preview First

```bash
# Good: Preview before merge
tracertm branch merge feature/x --to main --dry-run
tracertm branch merge feature/x --to main

# Avoid: Direct merge without preview
```

### 2. Resolve Conflicts Promptly

```python
# Good: Handle conflicts immediately
merge = client.start_merge(source, target)
if merge.has_conflicts:
    resolve_all_conflicts(merge)
    client.complete_merge(merge.id)

# Avoid: Leaving merges in conflict state
```

### 3. Use Appropriate Strategy

```python
# Fast-forward for simple changes
client.merge_branch(source, target, strategy="fast_forward")

# Squash for feature branches
client.merge_branch(source, target, strategy="squash")

# Three-way for complex merges
client.merge_branch(source, target, strategy="three_way")
```

### 4. Document Merge Decisions

```python
# Good: Include meaningful message
client.merge_branch(
    source="feature/oauth2",
    target="main",
    message="Add OAuth2 support for Google and enterprise SSO"
)
```

## Related Topics

- [Branching](/docs/wiki/concepts/versioning/branching) - Branch workflows
- [Strategies](/docs/wiki/concepts/versioning/strategies) - Versioning approaches
- [History](/docs/wiki/concepts/versioning/history) - Change tracking
- [Rollback](/docs/wiki/concepts/versioning/rollback) - Reverting changes

