Free tool

Graft heart rate, power, or cadence from one file onto another.

Merge HR, power, cadence, speed, elevation, or temperature streams from one activity file into another. Drop a target FIT (or GPX or TCX), drop a parallel source file, pick which streams to copy, and the tool time-aligns and grafts them in. Built for athletes recording on two devices simultaneously who need one clean output with all the data.

power: nonebecomespower: 248 W

Target file (gets the new data)

Source file (data to graft in)

How it works

  1. 1

    Drop the target file

    The file that gets the new data grafted in. Output keeps this file's format.

  2. 2

    Drop the source file

    The file with the streams you want to copy over. FIT, GPX, or TCX all work.

  3. 3

    Pick streams and tolerance

    Check the streams to graft (HR, power, cadence, speed, elevation, temperature). Pick a time-match tolerance - we copy from the closest source point within ± your window.

What you get

  • Per-stream checkboxes - copy only HR, only power, or any combination
  • Time-aligned matching with configurable tolerance (1s to 30s)
  • Diff stats show how many target points got each grafted stream
  • Works with FIT, GPX, and TCX as both target and source
  • Re-encodes the output via the official Garmin SDK for round-trip safety
  • Works offline - both files stay on your device

When to use this

Use the merger any time two devices captured the same activity and you want one combined file. Common scenarios: bike-computer-plus-watch double recording (head unit has GPS/power, watch has HR), HR strap forgotten on one device but paired to another, third-party power-meter app on the phone recording alongside a head unit without ANT+ pairing, dual-recording a race for redundancy and then noticing one stream is cleaner on the backup device. The merger turns two parallel recordings into one canonical file you can upload everywhere.

How it works under the hood

The tool decodes both files into per-stream time series in your browser. For each trackpoint in the target file, it looks up the source file for the closest timestamp within your tolerance window. If a match is found, it copies the source value for each checked stream into the target trackpoint. If no match is found inside the tolerance, the target keeps its existing value (or null, if it had none). After the per-point graft, the file is re-encoded - FIT through the official Garmin SDK, GPX and TCX through native XML serialization - and downloaded. The whole process is local: neither file leaves your device.

Common mistakes

Three mistakes worth flagging. First, mismatched clocks - if one device's clock was off by minutes (common with phones that did not sync), the graft will silently fail for most points because nothing matches inside the tolerance. Check the diff stats; if a low percentage of points matched, run the source through our [FIT Time Adjuster](/tools/fit-time-adjuster) to correct the clock first. Second, grafting GPS positions across devices - the tool does not do this by default because the two devices will disagree by a few meters per point and the result is jagged. Stick to HR, power, cadence, and other scalar streams. Third, grafting elevation from a noisy phone GPS onto a clean barometric altimeter recording - the target gets worse. Always graft from the better device into the target file.

Frequently asked questions

What if the two recordings do not start at the same time?
No problem - the tool matches by absolute timestamp, not by record index. As long as the two files overlap in real time, the graft works. The portion of the target outside the source's time window stays without grafted data (you keep whatever was there originally).
What tolerance should I use?
5 seconds is a sensible default and covers most cases. Drop to 1-2 seconds if both devices recorded at 1Hz and you want strict matching. Raise to 10-30 seconds if one device subsampled its stream (some Garmin units record HR at lower frequencies to save battery, and some power meters report at varying intervals). The diff stats after merge tell you what percentage of target points matched, so you can re-run with a larger tolerance if too many points were skipped.
Will the source file's laps and session totals carry over?
No - only per-trackpoint stream values. The target file's laps, session summary, course points, and event messages stay intact, so the structure of the activity does not change. This is intentional: you usually want the target's organization and the source's sensor data, not a mash of both.
What is the canonical use case for this?
Two-device recording. You record an outdoor ride on your Garmin Edge (which has GPS, power, cadence) but you also wore an Apple Watch (which captured HR and recovery data). You want one merged FIT for Strava that has the Garmin's power and the Apple's HR. Drop the Garmin FIT as target, the Apple GPX as source, check the HR box, download. Done.
Can I merge power from a pedal-based meter into a ride recorded on a head unit without power?
Yes - if the power meter records its own FIT (some do via Connect IQ data fields or a paired phone app), drop the no-power head-unit ride as target and the power-only FIT as source, check power, merge. The output will look like a normal head-unit recording with power baked in.
Does this work for swap-direction merging too?
Yes. The "target" and "source" labels are just which file the output is shaped from. You can use either file as either role. Try one direction, look at the diff stats, and switch if the other way is cleaner.
What happens if the target already has the stream I am grafting?
The graft overwrites the target's existing values at each matched timestamp. This is intentional - you usually graft because the target's version of the stream is missing or wrong. If you only want to fill gaps (write source values only where target is missing), check the gap-fill option on the tool page.
Will Strava and Garmin Connect accept the merged file?
Yes - the output is a fully valid FIT (or GPX/TCX) re-encoded with the official Garmin SDK. Strava treats it like any other upload. If you are re-uploading because the original was missing a stream, Strava will detect a duplicate by start time and distance - either delete the original first, or shift the start by a minute using our [FIT Time Adjuster](/tools/fit-time-adjuster).

Save your training to a real log

Patch the file once, then keep every ride and run analyzed in one place. Domestique reads the data for you.

Create free account