Migrating from Legacy Systems

LVCompare and LVMerge: What They Cannot Do

Learn what LVCompare and LVMerge do, how to wire them into Git, the failure modes you'll hit, and the four things neither tool can do for a review.

JJulien Buteau
intermediate8 min readSeptember 23, 2026

LVCompare and LVMerge both work. LVCompare shows a node-by-node diff of two VIs, and LVMerge performs a real three-way merge into a new VI. Both need a LabVIEW Professional seat with every dependency resolvable on the machine that runs them, and neither runs where reviews happen: in a pull request on the web, or on a colleague's laptop without Professional.

What Each Tool Does

ToolInputOutputNeeds
LVCompareTwo VIs (two files, or two revisions of one)A window listing each difference in front panel, block diagram, attributes and connector pane, with both VIs open side by sideLabVIEW Professional, same version as the VIs, all subVIs and classes resolvable
LVMergeBase VI, Theirs VI, Yours VIA merged VI you accept or reject difference by difference, then saveSame as LVCompare, and both branches must load without a missing-dependency dialog

Both tools open the VIs in a real LabVIEW instance. That's why the dependency rule exists: if Power Rails.vi calls DMM Read.vi from a library the diff machine doesn't have, LabVIEW searches, and the compare either stalls on a dialog or runs against a broken VI.

Setting Them Up with Git

Git runs whatever you name as a difftool or mergetool, so wiring them in is a few config lines. The lines below are for a 64-bit LabVIEW on Windows, run from Git Bash. Change the install path for your LabVIEW version; the path, the tool version and the VIs all have to match.

.gitconfig
# LabVIEW difftool and mergetool. Paths are per LabVIEW version and bitness.# LVMerge argument order is Base, Theirs, Yours, Merged, and all four must be absolute.[difftool "lvcompare"]    cmd = \"C:/Program Files/National Instruments/Shared/LabVIEW Compare/LVCompare.exe\" \"$(cygpath -aw \"$LOCAL\")\" \"$(cygpath -aw \"$REMOTE\")\" -nobdcosm -nofppos[mergetool "lvmerge"]    cmd = \"C:/Program Files/National Instruments/Shared/LabVIEW Merge/LVMerge.exe\" \"$(cygpath -aw \"$BASE\")\" \"$(cygpath -aw \"$REMOTE\")\" \"$(cygpath -aw \"$LOCAL\")\" \"$(cygpath -aw \"$MERGED\")\"    trustExitCode = false[diff]    tool = lvcompare[merge]    tool = lvmerge

Three details carry the whole setup.

The argument order. Git exposes the three merge inputs as $BASE, $LOCAL (yours) and $REMOTE (theirs), and the output as $MERGED. LVMerge wants Base, Theirs, Yours, Merged, so $REMOTE goes before $LOCAL. Swap them and the tool runs, opens, and merges the wrong way round.

The absolute paths. Git hands the tools relative paths into a temporary directory. LVCompare and LVMerge want absolute Windows paths, which is what cygpath -aw produces. Without it the tool reports a missing file or opens nothing.

The version. The executable path contains the LabVIEW install, and the tool inside it only opens VIs from a compatible version. A team on LabVIEW 2019 and 2024 keeps two sets of lines and switches by machine.

Tell Git the files are binary as well, so it never tries a text merge or line-ending conversion on them.

.gitattributes
# Never treat these as text. Git stores and reverts them; the tools above diff them.*.vi binary*.ctl binary*.seq binary

Then git difftool -- "FCT/Power Rails.vi" opens LVCompare on the working copy against HEAD, and git mergetool -- "FCT/Power Rails.vi" opens LVMerge during a conflicted merge.

The Failure Modes

These are the ones that show up in practice and have a known cause.

SymptomCauseWorkaround
LVCompare refuses to open the second file, or opens it as a copyLabVIEW can't hold two VIs with the same name in memory, so one copy has to be renamed, and a renamed class member no longer belongs to its classCompare a plain VI, or check the other revision out into a second folder and compare from there; for class members, accept that the class context is lost
A search dialog appears and the compare stallsA subVI, typedef or class the VI depends on isn't on the diff machine, or isn't at the path the VI expectsRun the compare from the project's own development machine with the .lvproj open, never from a bare checkout
The merged VI contains a node twiceLVMerge duplicates a node that was deleted and re-added in one branchInspect the merged block diagram before saving, remove the duplicate, run the VI once
The tool opens the wrong revisions, or nothing happensArgument order is wrong (LVMerge wants Base, Theirs, Yours, Merged), or a path is relativeCheck the order in .gitconfig, wrap every path in cygpath -aw
The config works on one PC and fails on anotherThe install path and the tool version are per LabVIEW version and bitnessKeep one config block per LabVIEW version in the repository README and copy the matching one
LVCompare.exe isn't there at allThe seat is Base or Full, not ProfessionalNone inside LabVIEW; the review moves to a machine with Professional

What They Cannot Do

Four gaps, and none of them is a bug. They follow from the tools being LabVIEW instances.

Review in a pull request on the web. GitHub, GitLab and Bitbucket render a diff of text. For a .vi they show "Binary file changed". The reviewer downloads both revisions, opens LVCompare locally, and writes the review from memory. Nobody comments on line 27 of a block diagram.

Run on a machine without Professional. Base and Full seats don't ship the tools. On a team where one person has Professional, that person is the only reviewer, whatever the org chart says.

Merge a class or a typedef reliably. The rename problem above breaks class membership during a compare, and a typedef change ripples into every VI that uses it, which LVMerge handles one VI at a time. Most teams merge classes by picking one side and redoing the other by hand, which fix LabVIEW merge conflicts on binary VIs walks through.

Diff a .seq. TestStand sequences aren't VIs. Saved as XML they diff a little better in plain Git, but they still aren't something you'd merge by hand, and LVCompare and LVMerge don't open them.

When They Are Still the Right Tool

If you stay on LabVIEW, use them. LVCompare on the development machine before every commit is the closest thing to reading your own diff, and it catches the accidental wire and the constant you didn't mean to change. LVMerge is worth the argument-order fiddling when two engineers have both made real diagram changes to the same VI and neither wants to redo a day's work.

They're the right tool for the machine that has them. They were never meant to be the review process for a team, and treating them as one is where the pain in why LabVIEW version control is so painful comes from. Where they stop, the honest options are a convention (one person per VI at a time), a second Professional seat, or moving limits out of the diagram into a file Git can read. Code review for LabVIEW tests: why it fails covers the team side.

The Contrast

A TofuPilot Framework station is text: procedure.yaml, phases/*.py, plugs/*.py. The same conflict on the same limit, when two branches both changed the 3.3 V floor, looks like this in the file.

procedure.yaml
- name: rail_3v3         unit: V         validators:           - operator: ">="<<<<<<< HEAD             expected_value: 3.15=======             expected_value: 3.1>>>>>>> widen-3v3-limit           - operator: "<="             expected_value: 3.4

You read both values, pick one or ask the two authors, delete the markers, git add, commit. A minute, on any machine, with no licence. Everything else in the two branches merged on its own, because Git could read it. The reviewer on the pull request saw the two candidate values before the merge, and after the push a station pulls the deployment and every run it uploads to TofuPilot carries that deployment's id.

Start With One Station

When you move a station, pick the one whose VIs conflict most often. Rebuild it as a procedure.yaml with phases and plugs in Python with the TofuPilot Framework, keep the limits identical, and run it side by side with the LabVIEW version on the same units for two weeks.

install-and-run.sh
# Install the CLI, run the station locally (no account needed), or run with upload.curl -fsSL https://www.tofupilot.app/install | shtofupilot run ./procedure.yamltofupilot run ./procedure.yaml --upload

The rebuild is in how to migrate from LabVIEW to Python for manufacturing tests with TofuPilot, and the framework is at tofupilot.com/products/framework. The Lab tier is free, and tofupilot run works without an account.

More Guides

Put this guide into practice