π¨ Easy Checkpoint Merger
Merge Two Checkpoints Without Summoning a Tensor-Math PhD
- checkpoint_data_a
- checkpoint_data_b
- checkpoint_data_c
- model
- clip
- vae
- checkpoint_data
- output_path
- forensic_report
If you've been around Stable Diffusion long enough, you know that most of the "new models" on CivitAI aren't trained from scratch - they're merges of existing checkpoints, averaged weight by weight. The Easy Checkpoint Merger brings that old workflow into ComfyUI properly: pick two or three checkpoints, pick a method, and get a working MODEL, CLIP and VAE out the other side without touching a command line.
That's the appeal. Merging checkpoints has historically lived in separate scripts and GUIs, not in the graph. This node does it in-graph with 15 merge methods, and it keeps the whole thing on your terms - preview first, save when you're happy.
How it works
You feed it checkpoints in one of two ways: dropdowns (checkpoint_a, checkpoint_b, and optionally checkpoint_c), or the raw state-dict inputs (checkpoint_data_a/b/c) chained from another merge. It then combines every weight tensor using the method you pick and streams the work through in batches so peak RAM stays manageable.
The merge methods are the same family the LoRA side uses: linear, magnitude, feature_mix, slerp, the TIES variants, DARE dropout, subtract, svd_preserve, and a few experimental ones like block_swap and noise_aware. If you're not sure, start with linear - it's the weighted average everyone understands, and the README says so too.
The interesting part is the "Weight Block Map." Global weights (weight_a, weight_b, weight_c) multiply per-component weights (weight_unet, weight_clip, weight_vae, weight_te), so you can blend two UNets 50/50 while keeping all of checkpoint A's VAE. That's the kind of control that used to require manually editing weight files.
The inputs that matter
method- start atlinear, explore once you've got a baseline.weight_a/weight_b- the trap is here: forlinear, weights should sum close to 1.0 (0.5 + 0.5, or 0.7 + 0.3). Leave it at 1.0 + 1.0 and you're computing A + B, doubling magnitudes, which comes out as noise. The tooltip warns you about this, and it's worth reading.density- leave at 1.0. The tooltip is blunt: values below 1.0 sparsify checkpoint weights and degrade quality. This knob exists for the DARE methods; checkpoints mostly shouldn't go there.save_trigger- the big one.False(default) is preview mode: you get live MODEL/CLIP/VAE outputs to wire into a sampler and nothing touches your disk. Flip toTrueonly when the result is right, and it writes a.safetensorsto your checkpoints folder (auto-incrementing the filename if it exists).
Outputs: model, clip, vae (wire straight into a sampler), plus checkpoint_data to chain into another merge, output_path (the saved file, empty in preview mode), and a forensic_report string - alignment stats, layer-by-layer energy, warnings about mismatched trainers. Feed that into Easy Text Display instead of scrolling the console.
Installing it
ComfyUI Manager (search "Easy LoRA Merger"), or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/Terpentinas/EasyLoRAMerger
Restart ComfyUI. No model downloads - it works on whatever checkpoints you already have. The only extra dependency (gguf) installs automatically and isn't needed here anyway.
Common issues
The classic beginner failure is the 1.0 + 1.0 linear merge producing garbage - that's the weights, not the node. Also: don't merge across architectures. Flux keys don't match SDXL keys, the alignment report will scream about it, and the result is noise. Use preview mode first every time; a bad checkpoint merge takes up disk space and then stares at you from the model list.
Inputs (28)
| Name | Type | Default | Description |
|---|---|---|---|
| method | COMBO | linear | Choose merging method |
| density | FLOAT | 1.000.1β1 | Keep top % of weights after merging. WARNING: Values < 1.0 sparsify checkpoint weights, which may degrade quality. Only reduce if you understand the risk. |
| checkpoint_aopt | COMBO | 1 options: None | |
| checkpoint_bopt | COMBO | 1 options: None | |
| checkpoint_copt | COMBO | 1 options: None | |
| checkpoint_data_aopt | CHECKPOINT | β | |
| checkpoint_data_bopt | CHECKPOINT | β | |
| checkpoint_data_copt | CHECKPOINT | β | |
| weight_aopt | FLOAT | 1.00-5β5 | Global strength of first checkpoint. For linear method: weights should sum close to 1.0 (e.g., 0.5+0.5) to avoid doubling magnitudes β 1.0+1.0 produces noise. |
| weight_bopt | FLOAT | 1.00-5β5 | Global strength of second checkpoint. For linear method: weights should sum close to 1.0 (e.g., 0.5+0.5) to avoid doubling magnitudes β 1.0+1.0 produces noise. |
| weight_copt | FLOAT | 1.00-5β5 | Global strength of third checkpoint. For linear method: weights should sum close to 1.0 (e.g., 0.5+0.5) to avoid doubling magnitudes β 1.0+1.0 produces noise. |
| weight_unetopt | FLOAT | 1.000β2 | Component scaling for UNET weights |
| weight_clipopt | FLOAT | 1.000β2 | Component scaling for CLIP visual encoder |
| weight_vaeopt | FLOAT | 1.000β2 | Component scaling for VAE |
| weight_teopt | FLOAT | 1.000β2 | Component scaling for Text Encoder |
| blend_modeopt | COMBO | auto | auto: Smart choice based on trainer metadata (match β dense, mismatch β active) | dense: Traditional weighted sum |
| balancing_modeopt | COMBO | disabled | disabled: Use weights as given (no equalization) | safe: Subtle equalization for cross-architecture merges | creative: Looser equalization (experimental) |
| magnitude_scalingopt | COMBO | none | Signal magnitude scaling before merging β scales checkpoint B and C to match A's energy using RMS or topβX% percentile. |
| uniquenessopt | FLOAT | 0.700.1β1 | For feature_mix: higher = preserve more unique features |
| thresholdopt | FLOAT | 0.000β1 | For subtract: minimum magnitude to subtract |
| blendopt | FLOAT | 0.500β1 | For magnitude: 0=strict, 1=blended |
| deviceopt | COMBO | auto | 3 options: auto, cuda, cpu |
| precisionopt | COMBO | auto | 6 options: auto, float32, bfloat16, float16, fp8_e4m3fn, fp8_e5m2 |
| batch_sizeopt | INT | 641β256 | Number of keys to process per batch. DeviceManager.suggest_batch_size() can auto-tune based on VRAM. |
| save_triggeropt | BOOLEAN | false | β |
| filenameopt | STRING | merged_checkpoint | β |
| save_folderopt | STRING | /tmp/ComfyUI/models/checkpoints | β |
| metadata_modeopt | COMBO | merge_basic | How to handle metadata from source checkpoints |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| model | MODEL | β |
| clip | CLIP | β |
| vae | VAE | β |
| checkpoint_data | CHECKPOINT | β |
| output_path | STRING | β |
| forensic_report | STRING | β |