← Back to blog

Version Control Estimates: Three Way Calibration for Trade Teams

October 12, 2026
Version Control Estimates: Three Way Calibration for Trade Teams

Yes, with preprocessing and calibration, your Git history can give you reliable post-hoc estimates and a usable signal for tuning future bids. The method works when you desquash pull requests, filter out bot noise, and run a three-way comparison between pre-implementation estimates, true post-hoc scope, and actual logged time. The playbook below walks through each step, and you can jump straight to the checklist if you want to run it today.


TL;DR:

  • Recover original commits before measuring, remove bot and formatting changes, and normalize timestamps to developers’ local working hours because raw gaps include meetings and sleep.
  • One documented case found repository changes grew about 20% harder each year, so weight recent history or adjust for decay.
  • Separate scope error from execution variance: compare the initial estimate with cleaned post hoc scope, then compare that scope with developer confirmed coding time.
  • Wait for three to five logged samples before retuning the model, and track PRED(25) and MdAPE to monitor calibration over time.
  • For trade bids, save dated versions of the submitted estimate, awarded scope, and closeout actuals, keeping line item labels consistent across each record.

Subascent
Keep Trade Estimates in View
Subascent serves specialty trade teams managing bids and jobs, a relevant place to explore as you compare estimates with awarded scope and actuals.
Visit Subascent

Table of Contents

Version control essentials that matter for effort signals

Before you pull a single number out of your repository, it helps to know what you are actually looking at. A commit records a snapshot of changes, a timestamp, an author, and a message. A diff shows exactly which lines changed. Pull request metadata adds context: when the branch opened, when it merged, how many review rounds it went through.

None of that data is useful on its own. It becomes useful when your team writes commits that map to real units of work.

  • Atomic commits (one logical change per commit) make it possible to attribute effort accurately instead of guessing which part of a giant commit took the time.
  • Small, frequent pull requests reduce merge conflicts and keep the time between "first commit" and "merge" close to actual working time.
  • Descriptive commit messages let you classify work later (bug fix, feature, refactor) without reverse-engineering intent from code alone.

Squash merges and aggressive rebasing work against you here. They collapse days of granular history into a single commit, which destroys the very signal you are trying to measure. GitLab's version control best practices recommend atomic, small commits with clear messages specifically because they make history easier to parse later, whether for review, debugging, or in this case, estimation.

Why repository history provides useful estimation signals, and where it fails

Certain version-control signals correlate with effort in predictable ways: files touched, lines of code changed, and commit count all tend to track the size of a task, though not in a straight line. A one-line config change can take an hour of investigation, while a 200-line refactor might take twenty minutes of mechanical find-and-replace. The signal is real, but noisy.

This is where a lot of teams go wrong. They assume a generic formula, lines changed divided by some constant, will produce a usable estimate. It will not. A non-intrusive methodology that correlates version-control change history with time-sheet data can estimate change effort, but it also surfaces something teams rarely account for: repository decay.

A documented case found repository changes grew about 20% harder year over year as complexity accumulated, which means historical calibration data needs a decay adjustment or a recency weight, not a flat average across years.

Cold-start estimation, trying to build a formula from someone else's repository data, runs into the same wall from a different direction: it simply does not transfer well across teams or codebases.

Practical extraction and estimation techniques

Converting raw commit history into a defensible estimate takes a few deliberate steps. Here is the sequence that produces a usable "true" range for a given feature or bug fix.

  1. Desquash the pull request. If your workflow squashes commits on merge, pull the original branch history before squashing, or reconstruct it from the diff SHA. A thesis on estimating contribution time from Git and GitHub metadata found that desquashing and recovering contained commits reduces extreme per-commit time estimates substantially, since a single squashed commit otherwise looks like it took either no time or an impossible amount of time.
  2. Classify and filter commits. Strip out automated commits (dependency bumps, formatting-only changes, CI config tweaks) and flag anything from a bot account. These inflate commit counts without reflecting human effort.
  3. Choose your method: heuristic or regression. A heuristic approach (files touched times a fixed multiplier, adjusted by commit type) is fast to set up and easy to explain to a non-technical stakeholder, but it is blunt. A regression model trained on your own historical data captures nonlinear relationships, like the fact that test files take less time per line than business logic, but it needs enough historical samples to be trustworthy, not a formula borrowed from a public dataset.
  4. Cap outliers. Any single commit showing an implausible time gap (days between commits, usually a weekend or context switch) should be capped at a reasonable ceiling rather than left to skew the average. The same thesis work recommends repository-specific caps rather than a universal default, since squash patterns, automation noise, and timezone spread vary by team.
  5. Compute a likely, minimum, and maximum range. Take your filtered, desquashed data and build three numbers: a likely estimate from the median observed effort for similar-sized changes, a minimum from the fastest comparable case, and a maximum from the slowest, padded by a risk margin for scope you have not fully diffed yet.

Pro Tip: Run your first regression model against last quarter's merged PRs before trusting it on a live bid, since a model with no backtest is just a guess with extra steps.

Data cleaning and pitfalls: timezones, bots, squashed history, and git timestamps

Most bad VCS-based estimates trace back to dirty input data, not a flawed method. A few checks catch the majority of problems before they reach your calibration report.

  • Bot and automation commits inflate counts without reflecting human work; filter by author account, commit message pattern, or known CI service names.
  • Squashed history hides the real timeline of work; use a diff-SHA approach or PR expansion to recover the original commits before measuring time gaps.
  • Raw git timestamps are an unreliable proxy for effort. A benchmark on cold-start estimation found that git timestamps include sleep, meetings, and context switches baked into the gap between commits, so treat them as a rough signal, never as a direct measurement.
  • Timezone spread across distributed teams can make a commit look like it happened overnight when it was actually mid-afternoon for the author; normalize everything to the developer's local working hours before computing gaps.
  • Repo decay and non-coding work (meetings, spec review, waiting on a response from a general contractor) both stretch the apparent timeline without reflecting coding effort, so your "actual" number should come from a developer-confirmed figure, not the raw git delta.

Pro Tip: Always normalize timestamps to working days first, then validate with the developer, since the order matters: validating noisy data just produces a confidently wrong number.

Calibration and validation: the three-way comparison workflow

An effective estimation system involves comparing three key values: the pre-implementation estimate, the post-hoc calculated true estimate based on version control data, and the developer-validated actual time spent coding. A documented three-way calibration playbook defines exactly this structure and the formulas that separate two distinct failure modes.

  1. Compute scope_variance_pct: the percentage difference between the pre-impl estimate and the true estimate. A large gap here means your scoping was off, not your team's execution.
  2. Compute exec_variance_pct: the percentage difference between the true estimate and the actual logged time. A large gap here means execution ran slower or faster than the scope alone would predict.
  3. Plot both numbers against each other to build an outcome matrix: low scope variance with high exec variance points to a developer or environment issue, while high scope variance with low exec variance points to an estimation process problem.

The same playbook is explicit on one rule: do not adjust your model parameters from a single sample. Wait for three to five logged rows before treating a pattern as real, and track two rolling metrics over time, PRED(25) (the percentage of estimates within 25% of actual) and MdAPE (median absolute percentage error), both of which are used as standard calibration targets in estimation benchmarking work.

MetricWhat it measuresAction when it drifts
scope_variance_pctGap between pre-impl guess and true post-hoc scopeRevisit how estimates are scoped, not how fast people work
exec_variance_pctGap between true scope and actual logged timeInvestigate execution conditions, interruptions, or skill match
PRED(25)Share of estimates landing within 25% of actualTrack over 3 to 5+ samples before retuning the model
MdAPEMedian absolute percentage error across samplesUse as the headline number when reporting calibration health

Playbook: run this on a PR or feature branch

This is the compact version you can run on a single pull request today.

  1. Pre-flight: capture the pre-implementation estimate and any available frontmatter (ticket scope, acceptance criteria) before a single line of code is written.
  2. Execution: once merged, desquash or expand the PR to recover individual commits, compute the true range from the cleaned diff, and extract the git window from first commit to merge.
  3. Validate: ask the developer to confirm actual coding time, excluding meetings and context switches, then compute scope_variance_pct and exec_variance_pct and log the row to a CSV or tracking sheet.
  4. Post: store the sample alongside prior ones and wait until you have three or more before making any directional change to your estimation model.

Pro Tip: Keep this CSV next to your bid log rather than buried in a separate tool, since you'll want to cross-reference variance against bid outcomes later. Teams that already track bid invitations and due dates in one place find it easier to bolt this calibration log on as another column rather than a separate system.

Integrating version control data with trade estimating tools and spreadsheets

Most electrical, plumbing, HVAC, and other trade estimators are not working in a pure software environment, so "version control" usually means a spreadsheet workbook, a takeoff file, and a bid log, not a Git repository full of code. The same calibration logic still applies: you are comparing a pre-bid estimate against what the job actually took.

The practical move is to treat each bid workbook version the same way you would treat a pull request. Save a dated copy before submitting the bid (your pre-impl estimate), another copy reflecting the final awarded scope after any GC negotiation (your true estimate), and a final copy updated with actual labor hours and material costs once the job closes (your actual). An HVAC estimating workflow built around consistent bid items makes this three-way comparison far easier, because each version maps to the same line items instead of a reshuffled spreadsheet.

Three bid estimate versions compared by scope and actuals

If your estimating tool exports to CSV or integrates with QuickBooks, pull labor hours and job costs directly rather than retyping them, since manual re-entry is where most variance-tracking efforts quietly die. The goal is not to turn your estimating spreadsheet into a code repository. It is to borrow the discipline: dated snapshots, consistent scope labels, and a habit of comparing what you guessed to what actually happened.

Handling version control for CAD drawings, specs, and takeoff documents

Non-code assets, like CAD drawings, spec books, and takeoff PDFs, do not diff cleanly the way text-based code does, which is exactly why they get mishandled most often. A revised drawing looks identical to the last version until you zoom in on one detail that changes your material count.

The fix is procedural, not technical. Name every revision with a date and revision number, never overwrite a file in place. Keep a short changelog, even a single line per revision, noting what changed and why: "Rev 3, moved panel location per RFI 14." That one line is often the only thing that tells you, six months later, why your conduit run estimate from Rev 2 no longer matches the as-built.

A documented document version control process for trade teams covers this in more depth, but the core habit is simple: treat every takeoff document the way you would treat a commit, dated, labeled, and tied to a specific scope change, so that when a bid comes in high or low, you can trace it back to which drawing revision drove the number.

Aligning VCS-based estimates with bid invitations and deadlines

A calibrated estimate is only useful if it lands before the bid is due. The three-way workflow described earlier takes time to run properly, so build it into your bid calendar rather than treating it as an afterthought squeezed in the night before submission.

The practical sequence: log the bid invitation and due date the moment it arrives, block time for takeoff and scope review well ahead of the deadline, and run your pre-impl estimate early enough that you have room to sanity-check it against comparable past jobs before submission. Teams that struggle with this usually are not bad at estimating, they are bad at tracking which invitations are due when, so the estimate gets compressed into the final hours and skips the calibration step entirely.

When you are comparing multiple bids side by side, consistent scope labeling matters just as much as timing. A clear process for leveling bids against each other keeps your estimate versions comparable across jobs, which is what makes the true-versus-actual comparison meaningful instead of apples-to-oranges.

Training estimators and project managers to read VCS data correctly

The biggest obstacle to adopting this workflow is not the math, it is getting estimators and project managers comfortable treating document and commit history as a measurement tool rather than just an archive.

Start with a short internal walkthrough using one real, already-closed job: show the pre-impl bid estimate, the final awarded scope, and the actual labor and material cost, side by side. Most estimators have an instinct for why a job ran over, but have never seen it laid out as three concrete numbers with a percentage gap attached. That exercise does more to build buy-in than any abstract explanation of regression models.

Project managers need a different piece of training: how to read a revision log or commit history without getting lost in noise. Teach them to ask "what changed in this revision and who confirmed it" rather than trying to parse every line of a diff. Pairing that habit with earned value tracking gives PMs an early warning system, since a job running significantly behind its planned burn rate three or four weeks in is usually the same job that will show high exec_variance_pct once it closes.

Real-world patterns across trades

Specialty trade subs rarely have a formal "estimation model," but the three-way comparison pattern shows up informally wherever a team keeps good records. A masonry estimator who tracks square footage bid against square footage actually laid, job after job, is running an unofficial version of this calibration loop. A fire protection sub comparing sprinkler head counts from the original takeoff against the final as-built count is doing the same thing with a different unit.

The pattern that holds across trades is consistency of scope labeling. When a framing crew's change order documentation uses the same line-item names from bid to actual, the variance calculation is a straightforward subtraction. When the labels drift (one document says "exterior wall framing," the next says "shell framing" for the same scope), the comparison breaks down regardless of how good the underlying estimate was. A standard change order template helps enforce that consistency, since a reusable format keeps scope descriptions aligned across the bid, the change order, and the closeout documentation.

Author perspective and practical notes for small teams

Small, mixed-role teams produce the noisiest commit and revision history of any group, since one person is estimating, drafting, and revising documents in the same afternoon. The fix is not more process, it is tighter labeling: tie every commit or saved revision to a specific bid or scope item, even with a one-line note. That single habit does more for calibration accuracy than any regression model ever will.

— Dave

Why Subascent is a practical next step for versioned scope and calibration

Subascent

We build our platform around the habit this entire guide depends on: versioned scope that stays tied to a specific bid, not a workbook that gets overwritten every time something changes. Our platform lets specialty trade teams attach takeoffs to a bid record, track actuals against the original scope, and keep a calibration history without juggling a separate spreadsheet. Visit Subascent to see how it fits your bid workflow and start a trial.

FAQ

What is a version control system?

A version control system records changes to files over time, tracking who changed what, when, and why, so earlier versions can be recovered and compared. Git is the most widely used version control system for code, while trade teams often apply the same principle informally to dated drawing and spreadsheet revisions.

What is the best estimating software?

There is no single best estimating software, since the right fit depends on your trade, team size, and whether you need PDF takeoff, QuickBooks sync, or bid tracking built in rather than bolted on. Platforms built specifically for specialty trade subcontractors, like Subascent, tend to fit better than general contractor-focused tools because the scope, bid, and change order workflows match how subs actually work.

What is the 40/20/40 rule in software engineering?

This guideline is used as a rule of thumb for budgeting effort across a project's phases rather than a precise formula.

What is software estimation?

Software estimation is the process of predicting the time, effort, or cost a piece of work will require before it is built. The three-way calibration method described in this guide improves on gut-feel estimation by comparing a pre-implementation guess against the true scope and the confirmed actual time once the work is done.

Sources

These sources cover the desquash techniques, calibration formulas, and decay effects referenced above, useful if you want to implement your own regression or variance tracking.