First run

Turn exported LCOV files into one.

An LCOV .info file is a text file written by a coverage exporter. lcovmerge combines those existing files; it does not collect coverage.

Choose the merge point for your ecosystem

Use lcovmerge only after your coverage tool has exported separate LCOV files and a local consumer needs one file. Keep your current path when raw profiles or your reporting service already provide the merge you need.

Scroll horizontally to view all columns.

PipelineCheck firstWhen lcovmerge may fit
gcov coverageTry lcov -a for small shard sets.Downloaded LCOV shards make the final local merge costly.
LLVM coverageMerge raw profiles with llvm-profdata before llvm-cov.Independent LCOV exports are already the handoff.
RustUse cargo-llvm-cov or grcov to handle native profiles.Separate CI jobs leave LCOV files for a local consumer.
PythonUse Coverage.py combine while raw data is available.Only exported LCOV shards remain and one file is required.
JavaScriptUse nyc merge while raw coverage JSON is available.The local report step needs one LCOV file after export.
Go and other producersExport LCOV with a producer or converter.Confirm the converter's records work with your report consumer.
BazelUse the combined report from one bazel coverage run.Separate CI jobs provide LCOV artifacts that need a final merge.
Codecov or CoverallsCheck service-side parallel shard aggregation.A local consumer still needs a single LCOV artifact.

These are workflow pointers, not compatibility claims for every tool version. Check the exporter and report consumer versions used by your pipeline before switching.

Your first merge in three steps

The current source is a native Rust CLI and library. Version 1.2.0 is the first Rust release.

Build the current Rust CLI

Install stable Rust, Python 3.11+, and Make, then build the portable optimized CLI:

git clone https://github.com/megasoft1978/lcovmerge.git
cd lcovmerge
make
./bin/lcovmerge coverage/shard-*.info -o coverage/merged.info

Published release downloads

  1. Download and extract

    Get lcovmerge v1.2.0 for your operating system and verify the archive checksum before extraction. The release includes Linux, macOS, and Windows binaries; see the platform verification scope.

    Choose an operating system and verify the archive ↓
  2. Merge the exported shards

    Run this from the directory that contains coverage/. The shell expands the wildcard.

    lcovmerge coverage/shard-*.info -o coverage/merged.info
  3. Keep your report or upload step

    The output is still an LCOV .info file.

    genhtml coverage/merged.info --output-directory coverage/html

Download and verify a binary

Choose the archive that matches your system and verify it before extraction. Platform verification scope and limits are summarized in the release notes.

Linux · x86-64

For Linux ARM64, choose its matching archive from the release page.

set -eu
asset=lcovmerge-1.2.0-linux-x86_64.tar.gz
base=https://github.com/megasoft1978/lcovmerge/releases/download/v1.2.0
curl -fL "$base/$asset" -o "$asset"
curl -fL "$base/SHA256SUMS" -o SHA256SUMS
entry=$(awk -v file="$asset" '$2 == file || $2 == "*" file { if (found++) exit 1; line=$0 } END { if (found != 1) exit 1; print line }' SHA256SUMS)
printf '%s\n' "$entry" | sha256sum -c -
tar -xzf "$asset"
./lcovmerge --version

Try a no-install sample

Save the downloaded binary as lcovmerge in your current directory, then paste this in a POSIX shell. It creates two synthetic files and runs the binary from the parent directory; it does not install anything on your PATH.

mkdir -p .lcovmerge-demo
cd .lcovmerge-demo
printf '%s\n' 'SF:src/example.rs' 'DA:1,2' 'end_of_record' > shard-a.info
printf '%s\n' 'SF:src/example.rs' 'DA:1,3' 'end_of_record' > shard-b.info
../lcovmerge shard-a.info shard-b.info -o merged.info
cat merged.info

Expected output:

SF:src/example.rs
DA:1,5
FNF:0
FNH:0
BRF:0
BRH:0
MCF:0
MCH:0
LF:1
LH:1
end_of_record

If the first run fails

Common first-run errors and the next check
ErrorTry this
Exit 1 · option or command errorRun lcovmerge --help; check the option spelling and that -o FILE is present.
Exit 2 · parse error with a line numberOpen the named input at that line and confirm it is an exported LCOV .info file, not a raw profile.
No input matchedCheck that the files exist under the current directory and match the wildcard. Use find coverage -name '*.info' or list paths in @coverage-files.txt.
Exit 3 · --tmpdir is not writableChoose an existing directory you can write to, and check that it has free disk space.
Exit 3 · output or temporary-file errorCheck write access and free space for both the output directory and the temporary directory.

See the full exit-status reference for all return codes.

Constrained CI example

This example budgets record memory and puts sorted temporary files in a directory created for this run:

set -eu
sort_dir=$(mktemp -d)
trap 'rm -rf "$sort_dir"' EXIT
lcovmerge --mem-limit 256M --tmpdir "$sort_dir" coverage/shard-*.info -o coverage/merged.info
genhtml coverage/merged.info --output-directory coverage/html

--mem-limit 256M is a coverage-record storage budget, not a total process RSS cap. Sorting needs free disk space in the selected temporary directory.

Check compatibility before switching

Native mode has its own merge policies. The experimental, opt-in LCOV 2.6 profile covers a version-pinned merge workflow; neither mode replaces LCOV collection or reporting. Compare normalized records and your report before switching. See the migration checklist, profile scope and status, documented limits, and private-input measurement guide.

For the same two inputs, create separate outputs with both tools:

lcov --branch-coverage --function-coverage -a coverage/shard-a.info -a coverage/shard-b.info -o coverage/lcov.info
lcovmerge coverage/shard-a.info coverage/shard-b.info -o coverage/lcovmerge.info --strict-checksum

Compare normalized records and the reports produced from both files; a plain text diff is not a semantic compatibility check.

Paths and input lists

Rebase paths, filter inputs, or use a list file

Rebase source paths

Use --rebase when SF: paths point to a build directory but reports use another root.

lcovmerge --rebase /build/worker/project=/workspace/project shard-a.info shard-b.info -o merged.info

A path below /build/worker/project is rewritten below /workspace/project. Check emitted paths against the source tree used by your report generator.

Use a list file

lcovmerge @coverage-files.txt -o merged.info

A list file has one input path per line. Blank lines and lines beginning with # are ignored. Paths are relative to the current working directory; nested list files are limited to eight levels. The shell expands globs; lcovmerge does not.

Advanced options

Show all lcovmerge v1.2.0 options
Command-line options in lcovmerge 1.2.0
OptionPurpose
-o, --output FILERequired. Write to FILE, replacing it only after a successful merge. Use - for standard output.
--mem-limit SIZELimit memory reserved for coverage records. Total process memory can be higher, and sorting uses temporary disk. Default 64M; minimum 8M per job. Bare values are bytes; K, M, and G suffixes are binary multiples of 1024.
--tmpdir DIRWrite sorted batches to temporary files in DIR before merging them. The directory must exist and have enough free disk space. Files are removed after success and handled failures; caught POSIX SIGINT, SIGTERM, and SIGHUP also trigger cleanup. SIGKILL or machine failure can leave files. Windows interruption cleanup is not guaranteed. Default: the system temporary directory.
-j, --jobs NUse 1–32 workers to write sorted batches to temporary files before merging them. The default is min(4, detected cores), reduced if needed to fit the memory limit; explicit jobs require at least 8M per job. One large input file is not split across parser workers. On already-sorted regular files, an explicit -j N of 2 or more can instead split a merge of at least 64 MiB by source path and merge the parts in parallel; output is identical, any warning or error reruns the single-threaded merge, and staged files can briefly use about the output size in disk.
--prefix-strip PREFIXRemove a matching leading SF: source path prefix at a path boundary.
--rebase OLD=NEWRewrite a matching leading SF: source path prefix. Repeatable; matching is at a path boundary.
--include GLOBKeep a source path matching at least one include pattern. Repeatable; supports *, ?, and bracket ranges.
--exclude GLOBDrop matching source paths. Repeatable; exclusions take precedence over includes.
--branch-coverage on|offKeep or drop BRDA: rows. Default: on; this does not create branch data that is absent.
--no-function-dataDrop FN, FNDA, FNL, and FNA records.
--strict-checksumReturn status 2 when non-empty checksums for the same source line differ.
--warn-unknownPrint a diagnostic for each preserved unknown colon-delimited row inside a source section.
-qSuppress routine progress output; errors remain visible.
-vPrint parsed byte and record totals, selected worker count, and merged summary totals to standard error.
--statsPrint merged LF, LH, FNF, FNH, BRF, and BRH totals to standard error.
--versionPrint the version and build's Git commit identifier.
-h, --helpPrint the built-in usage summary.

CI and reporting recipes

Use these recipes after test jobs have exported LCOV files:

  • GitHub Actions · upload shard files, then merge them in a final job.
  • GitLab CI · collect artifacts and merge after test jobs finish.
  • Jenkins · merge files produced by parallel stages.
  • CMake with gcov · capture LCOV, then merge independent outputs.
  • Bazel · use only when a separate LCOV merge is still needed.
  • Report and upload consumers · pass the merged file to an LCOV-aware tool.

Help validate where LCOV merging is useful

Current measurements show specific workloads, not typical production savings. If your pipeline already produces LCOV shards, the project guide explains how to compare both mergers safely and share only reviewed aggregate results.