Merge Checkpoints (2 Models)
Blend two full checkpoints with actual controls
- output_filename
- documentation
Checkpoint merging is one of the oldest tricks in this community - it's literally how a big chunk of CivitAI got built, before anyone there trained a single step. You take two full checkpoints, blend the weights, and out comes a third model that (hopefully) inherits a bit of both. Most tools that do this give you one slider called "ratio" and call it a day. Checkpoint Two Merger gives you a whole console: an algorithm picker, six separate weight knobs, and a pile of settings for what happens when the two files don't quite line up.
What "checkpoint" means here
This pack ships three parallel merger families, and the naming is precise, not marketing: Checkpoint mergers work on complete, all-in-one model files - UNet, CLIP, and VAE bundled together, the kind of file you load with a plain checkpoint loader. If you're merging separate UNet-only files (the way Flux-style workflows load things), that's ModelTwoMerger. If you're merging standalone text encoders, that's TextEncoderTwoMerger. Keep them straight - pointing this node at a UNet-only file isn't what it's built for.
How it works
model_a and model_b are your two source checkpoints, picked from a dropdown of whatever's in your checkpoints folder. calc_mode selects the merge algorithm; the dropdown's exact option list isn't documented in the node metadata, so open it in the canvas to see what your installed version ships - the classic weighted-average blend is the one nearly everyone reaches for first. Six numeric knobs - alpha, beta, gamma, delta, epsilon, zeta - feed into whichever algorithm you picked. None of them carry a tooltip explaining exactly what each one bends, which is a real gap, but the defaults tell you something: alpha and beta both default to 0.5 (a straight 50/50 split is the obvious reading for a basic two-model blend), while gamma defaults to a suspiciously precise 0.99 with a 0.001 step - a different kind of knob for a more advanced algorithm. If you're just doing a simple blend, alpha is almost certainly the one you actually touch; leave the rest at default until you know what you're tuning.
Because you're merging two full checkpoints, their internal tensors won't always line up perfectly - different fine-tunes sometimes carry extra or renamed layers. mismatch_mode (default skip) decides what happens to a tensor that only exists in one file, and alignment_mode (default pad/crop) decides how to reconcile tensors that exist in both but at different shapes. The fact that both exist as first-class settings is the node quietly telling you: shape mismatches are expected, not an edge case.
The rest is housekeeping. exclude_patterns and discard_patterns let you keep certain layers out of the merge (regex by default, glob syntax if you flip glob_patterns). lazy_load streams tensors from disk instead of loading both checkpoints fully into memory - leave it on unless you have a reason not to. force_clear_cache clears CUDA memory after every layer, trading a bit of speed for headroom. save_dtype and override_dtype control output precision; process_device picks where the math runs. seed exists too - the huge INT range suggests at least one available calc_mode uses randomness (some merge techniques randomly drop and rescale a slice of parameters), so if reproducibility matters, pin it. Output is output_filename (defaults to merged_2_checkpoint) plus a documentation string.
Installing it
ComfyUI Manager: search Model Utility Toolkit, install, restart. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/silveroxides/ComfyUI-ModelUtils
Restart ComfyUI. No extra model downloads for this node - it's pure tensor math against files you already have.
Where people get burned
The honest failure mode isn't a crash, it's a bad output that runs fine. The community's own hard-won lesson on checkpoint merging is that averaging two well-trained models rarely gives you the best of both - it usually gives you something weaker at both, because the two target distributions don't agree. Merge a realistic checkpoint with an anime one and you get neither convincingly; merge two fine-tunes from unrelated base architectures and you're not merging, you're mashing incompatible weight spaces together and hoping mismatch_mode/alignment_mode paper over it. They can't, structurally - pad/crop keeps shapes compatible, it doesn't make the merge coherent.
More mundane: two full checkpoints in memory at once is a real VRAM ask, especially on SDXL-class or larger models. If you're getting OOM errors, that's what lazy_load and force_clear_cache are for - and if it's still too much, drop process_device to CPU and accept the slower run.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| execution_mode | COMBO | 2 options: MERGE, DOCUMENTATION ONLY | |
| model_a | COMBO | 1 options: None | |
| model_b | COMBO | 1 options: None | |
| calc_mode | COMBO | 10 options: Weight-Sum, Comparative-Interpolation, Power-Up (DARE), Power-Up (DARE+TIES), SVD LoRA Extraction, Enhanced Man Interp, +4 | |
| mismatch_mode | COMBO | skip | 3 options: skip, zeros, error |
| alignment_mode | COMBO | pad/crop | 2 options: pad/crop, interpolate |
| alpha | FLOAT | 0.50-10–10 | — |
| beta | FLOAT | 0.50-10–10 | — |
| gamma | FLOAT | 0.990-10–10 | — |
| delta | FLOAT | 2.00-10–10 | — |
| epsilon | FLOAT | 0.01-10–10 | — |
| zeta | FLOAT | 0.00-10–10 | — |
| seed | INT | 00–18446744073709550000 | — |
| output_filename | STRING | merged_2_checkpoint | — |
| save_dtype | COMBO | 3 options: fp32, fp16, bf16 | |
| process_device | COMBO | 2 options: cuda, cpu | |
| exclude_patterns | STRING | — | |
| discard_patterns | STRING | — | |
| glob_patterns | BOOLEAN | false | When True, exclude/discard patterns use glob syntax (* = any sequence, dots are literal). When False (default), patterns are Python regex matched as substrings. |
| lazy_load | BOOLEAN | true | Low memory mode: load tensors from disk on demand |
| force_clear_cache | BOOLEAN | true | Clear CUDA cache after each layer |
| override_dtype | BOOLEAN | false | Force the entire model to be saved as the selected save_dtype. If False (default), higher precision dtypes are preserved. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| output_filename | STRING | — |
| documentation | STRING | — |