Back to Blog
Douwe van der Meij

The Branch-Based Regeneration Pattern

How Fractal Forge handles the fundamental tension between generated code and custom modifications through Git branching.

TechnicalArchitectureDeep Dive

Code generators face a fundamental tension: the code needs to be regenerated when the model changes, but developers need to customize that code. How do you regenerate without destroying customizations?

Most generators solve this poorly. Either they forbid modifications (“don’t touch the generated code”), or they use fragile markers to identify safe zones, or they require complex merge tooling. All of these approaches create friction and often fail at the worst possible moments.

Fractal Forge takes a different approach: branch-based regeneration. Every regeneration creates a new Git branch. Your customizations on main are never touched. Standard Git merge resolves conflicts.

The Problem in Detail

Let’s say you’ve generated an application and made these customizations:

  1. Added validation logic to a command handler
  2. Extended a frontend component with custom styling
  3. Created a new service that integrates with an external API
  4. Modified how a query filters results

Now your model changes. You’ve added a new entity, modified an existing one, and added new commands. You need to regenerate.

With traditional approaches, you have several bad options:

Option A: Regenerate and manually reapply changes

You lose your customizations and have to manually redo them. This is error-prone and time-consuming. It gets worse as the codebase grows.

Option B: Mark “safe zones” in the code

Some generators use comment markers to identify sections that won’t be overwritten. This is fragile: markers get accidentally deleted, and the safe zones impose artificial constraints on where you can make changes.

Option C: Generate into separate files and manually integrate

You maintain two parallel codebases and manually copy relevant parts. This is unsustainable at scale.

The Branch-Based Solution

Fractal Forge sidesteps these problems entirely by leveraging something developers already know: Git branching.

Here’s how it works:

Initial Generation

When you first generate, the code goes to a branch (let’s call it fractal/initial). You review it, merge to main, and start customizing.

# Generated code appears on fractal/initial
git checkout main
git merge fractal/initial
# Now customize on main

Custom Code Organization

Your customizations go in specific places:

  • Custom handlers live in custom/ directories
  • Overrides follow a predictable pattern
  • New code can go anywhere since it’s your codebase

The generated code is designed to look for custom implementations first. If you’ve created custom/commands/create_order_handler.py, the framework uses that instead of the default.

Regeneration

When the model changes, you regenerate. The new code goes to a new branch (fractal/regenerate-v2):

# Regeneration creates a new branch
git checkout fractal/regenerate-v2

# Compare with main to see what changed
git diff main

# When ready, merge to main
git checkout main
git merge fractal/regenerate-v2

Conflict Resolution

Sometimes the merge will have conflicts. This happens when:

  • Generated code changed in the same place you customized
  • File structure changed significantly
  • New generated code interacts with custom code

These are standard Git conflicts. You resolve them the same way you resolve any merge conflict. Your IDE’s merge tools work. Your team’s code review process works. Nothing special required.

Why This Works

Familiarity

Every developer knows Git. Every team has merge workflows. By using standard Git branching, we eliminate the need for specialized tooling or training.

Visibility

You can see exactly what changed between regenerations. git diff shows every modification. Code review catches issues before they reach production.

Reversibility

Don’t like a regeneration? Don’t merge it. The branch exists independently. You can cherry-pick specific changes, modify the generated code before merging, or abandon the branch entirely.

Flexibility

Because the generated code is standard Python and Svelte, you can modify anything. There are no protected files, no magic markers, no forbidden zones. The pattern encourages customization rather than preventing it.

The Custom Directory Convention

While you can customize any file, the custom/ directory convention keeps things organized:

backend/
  app/
    commands/
      create_order.py      # Generated
    custom/
      commands/
        create_order.py    # Your override

Files in custom/ are never touched by regeneration. The framework automatically prefers custom implementations over generated ones.

This means:

  • Simple changes override generated code with minimal risk
  • Complex customizations are clearly separated
  • Regeneration is safe because custom code is architecturally protected

Practical Example

Let’s walk through a real scenario:

Day 1: Generate initial application with Order and Customer entities.

Day 5: Add custom validation to CreateOrder command.

# custom/commands/create_order_handler.py
class CreateOrderHandler:
    def handle(self, command):
        self.validate_stock_available(command)
        self.validate_customer_credit(command)
        # ... rest of implementation

Day 20: Model changes: add new fields to Order, new ShippingAddress entity.

Day 21: Regenerate to branch fractal/v2.

git diff main fractal/v2
# Shows: new entity files, modified Order model, updated tests
# Your custom/commands/create_order_handler.py is untouched

Day 22: Merge after review.

git checkout main
git merge fractal/v2
# Resolves cleanly, custom directory preserved

Day 25: Another model change conflicts with your customization.

git merge fractal/v3
# CONFLICT in app/commands/create_order.py
# The generated file changed where your custom code references it

Day 26: Resolve conflict.

# Standard merge resolution
# Update your custom code to work with new generated interfaces
git add .
git commit -m "Merge fractal/v3 with updated custom handlers"

Key Takeaways

Branch-based regeneration isn’t revolutionary technology. It’s the application of a familiar tool (Git branching) to a specific problem (generated code evolution).

The pattern succeeds because it:

  1. Uses tools developers already know
  2. Preserves all the flexibility of manual coding
  3. Makes changes visible and reviewable
  4. Keeps custom code architecturally protected
  5. Fails gracefully when conflicts occur

When your code generator works with Git rather than around it, you get the best of both worlds: the speed of generation and the flexibility of handwritten code.