# How to Handle Merge Conflicts in the AI Engineering from Scratch Curriculum

> Learn to resolve merge conflicts in AI Engineering from Scratch. Preserve markdown syntax, regenerate data.js, and validate changes for seamless project integration.

- Repository: [Rohit Ghumare/ai-engineering-from-scratch](https://github.com/rohitg00/ai-engineering-from-scratch)
- Tags: how-to-guide
- Published: 2026-06-08

---

**Resolve merge conflicts in the AI Engineering from Scratch curriculum by preserving exact markdown table syntax in [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) and [`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md), regenerating [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js) via `node site/build.js`, and validating changes with [`scripts/check_readme_counts.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/check_readme_counts.py) and [`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py) before committing.**

The AI Engineering from Scratch curriculum maintains a tightly-coupled structure where lesson tables directly feed an automated site generator. Because the parser in [`site/build.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/build.js) relies on precise markdown structures—including phase headers and lesson rows—to produce [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js), merge conflicts must be resolved carefully to prevent breaking the automatic site build and CI pipeline.

## Core Principles for Conflict Resolution

The repository enforces strict structural contracts to ensure the generated website remains functional. Understanding these constraints prevents merge conflicts from corrupting the curriculum’s metadata.

- **One-commit-per-lesson** – Each lesson lives in its own folder under `phases/`. This isolation prevents large, tangled pull requests that generate simultaneous conflicts across multiple files.
- **Exact markdown syntax** – Phase headers must follow the format `### Phase N: …` and lesson rows must use the pipe-delimited structure `| # | Lesson | Type | Lang |`. The [`site/build.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/build.js) parser expects these patterns to generate valid [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js).

- **CI-driven regeneration** – Files like [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js) and lesson count badges in [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) are automatically rebuilt on the `main` branch. Manual edits to generated files are overwritten during the next CI run.
- **Do not edit generated files** – Both [`catalog.json`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/catalog.json) and [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js) are git-ignored and machine-generated. Always modify source markdown and regenerate rather than editing output directly.
- **Validate before merging** – The repository provides [`scripts/check_readme_counts.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/check_readme_counts.py) and [`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py) to catch structural issues before CI blocks your pull request.

## Step-by-Step Conflict Resolution Process

When Git flags a conflict during a merge or rebase, follow this workflow to restore structural integrity while incorporating your changes.

### 1. Fetch the Latest Main Branch

Bring your feature branch up to date with the remote to materialize conflicts locally:

```bash
git fetch origin main
git merge --no-edit origin/main

```

This creates a merge commit and inserts conflict markers (`<<<<<<< HEAD`) into any contested files.

### 2. Identify Conflicted Files

Run `git status` to locate files with unresolved conflicts. In this curriculum, typical conflict locations include:

- [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) – Lesson table rows and phase headers
- [`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md) – Status glyphs and lesson progress indicators
- [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js) – Generated JavaScript data structures

### 3. Resolve Structural Content

Edit each conflicted file while preserving the exact syntax required by the build system:

**[`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md)** – Maintain the markdown table structure and lesson links. A valid row must follow this pattern:

```markdown
| 01 | [Dev Environment](phases/00-setup-and-tooling/01-dev-environment/) | Build | Python |

```

Remove all conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) and ensure no duplicate rows remain.

**[`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md)** – Preserve status glyphs exactly as Unicode characters (`✅` for complete, `🚧` for in-progress, `⬚` for not started). Do not replace these with words like "Done" or "Pending".

**[`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js)** – Do not resolve this file manually. Instead, fix the source markdown files first, then regenerate:

```bash
node site/build.js

```

This script parses the corrected [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) and [`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md) to produce a fresh [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js).

### 4. Run Local Validation

Before committing, execute the audit scripts to verify repository health:

```bash
python3 scripts/audit_lessons.py
python3 scripts/check_readme_counts.py --fix

```

The [`audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/audit_lessons.py) script checks for missing lesson files and malformed front-matter, while `check_readme_counts.py --fix` synchronizes the lesson-count badges in [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) with the actual directory structure.

### 5. Commit the Resolution

Stage only the resolved source files and the regenerated output:

```bash
git add README.md ROADMAP.md site/data.js
git commit --no-edit

```

The `--no-edit` flag preserves the default merge commit message.

### 6. Push and Verify

Push the branch without force (unless there are no pending review comments):

```bash
git push origin <your-branch>

```

Wait for the CI pipeline to complete. The `audit`, `readme-counts-sync`, and `site-rebuild` jobs must pass. If any job fails, return to step 4 and address the validation errors.

## Common Pitfalls and Solutions

| Symptom | Cause | Fix |
|---------|-------|-----|
| `grep -c 'tree/main/phases/NN-' site/data.js` returns `0` | Lesson rows in [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) lost their markdown link syntax (`[Title](…)`). | Restore the proper link format and regenerate [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js). |
| Status glyphs appear as plain text ("Done") in [`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md) | Manual editing replaced Unicode glyphs with ASCII words. | Replace with exact glyphs: `✅`, `🚧`, or `⬚`. |
| CI fails on `readme-counts-sync` | Lesson count badge in [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) is out of sync with actual lessons. | Run `python3 scripts/check_readme_counts.py --fix` before committing. |
| [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js) contains stale or missing lessons | Manual edits were made directly to the generated file. | Delete the modified file (`git checkout --theirs site/data.js`) and run `node site/build.js`. |

## Automating Conflict Resolution

For frequent contributors, wrap the resolution workflow in a Python script to ensure consistency. Save this as [`scripts/resolve_merge.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/resolve_merge.py):

```python
#!/usr/bin/env python3
import subprocess, sys

def run(cmd):
    subprocess.check_call(cmd, shell=True)

def main():
    # Pull latest main and attempt merge

    run("git fetch origin main")
    run("git merge --no-edit origin/main")
    
    # Fix structural metadata

    run("python3 scripts/check_readme_counts.py --fix")
    run("node site/build.js")
    
    # Validate repository health

    run("python3 scripts/audit_lessons.py")
    
    # Stage and commit

    run("git add README.md ROADMAP.md site/data.js")
    run("git commit --no-edit")

if __name__ == "__main__":
    main()

```

Execute with `python3 scripts/resolve_merge.py` after Git notifies you of conflicts.

## Essential Reference Files

For detailed specifications, consult these canonical sources in the repository:

- **[`AGENTS.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/AGENTS.md)** – Official conflict-resolution guide and agent instructions
- **[`CONTRIBUTING.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/CONTRIBUTING.md)** – Requirements for README and ROADMAP structure
- **[`site/build.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/build.js)** – The parser that generates [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js) from markdown
- **[`scripts/check_readme_counts.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/check_readme_counts.py)** – Badge synchronization logic
- **[`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py)** – Lesson directory validation

## Summary

- Preserve exact markdown table syntax in [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) and status glyphs in [`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md) to keep [`site/build.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/build.js) functional.
- Never manually edit [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js); always regenerate it using `node site/build.js` after resolving source conflicts.
- Validate all changes locally with `scripts/check_readme_counts.py --fix` and [`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py) before pushing.
- Follow the one-commit-per-lesson principle to minimize future conflict complexity.
- Reference [`AGENTS.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/AGENTS.md) and [`CONTRIBUTING.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/CONTRIBUTING.md) for authoritative structural requirements.

## Frequently Asked Questions

### What should I do if site/data.js appears in the conflict list?

Do not manually edit [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js). According to the repository’s CI-driven regeneration policy, this file is machine-generated from [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) and [`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md). Discard your local changes with `git checkout --theirs site/data.js`, resolve the markdown source files instead, then run `node site/build.js` to produce a fresh, correct version.

### Why does the README.md use specific Unicode glyphs instead of text labels?

The [`site/build.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/build.js) parser relies on exact Unicode characters (`✅`, `🚧`, `⬚`) in [`ROADMAP.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/ROADMAP.md) to determine lesson status for the generated website. Replacing these with words like "Done" or emojis breaks the parsing logic, causing lessons to display incorrectly or disappear from the generated [`site/data.js`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/site/data.js) entirely.

### How can I prevent merge conflicts when adding new lessons?

Follow the **one-commit-per-lesson** rule by placing each lesson in its own isolated directory under `phases/`. Make minimal, focused changes to [`README.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/README.md) that add exactly one table row per lesson. Run `python3 scripts/check_readme_counts.py` and `python3 scripts/audit_lessons.py` before committing to catch structural violations early.

### What happens if I commit resolved files but CI still fails?

The CI pipeline runs `audit`, `readme-counts-sync`, and `site-rebuild` jobs. If validation fails after your merge, return to your local environment and re-run `python3 scripts/check_readme_counts.py --fix` followed by `python3 scripts/audit_lessons.py`. These scripts identify the specific structural mismatch—such as malformed table rows or missing lesson directories—that caused the CI failure.