To map git commits to billable time, group consecutive commits by branch or ticket reference, measure the elapsed time between them, and split sessions whenever the gap exceeds a fixed idle threshold — typically 20-30 minutes. The output is a draft timesheet the developer reviews rather than writes from scratch.
You have 347 commits across three client repos this month, but your invoice still says “development — 40 hours” because translating git activity into billable line items feels impossible. Commit timestamps, branch names, and ticket references already contain most of the data a billing system needs. The missing piece is the algorithm that turns that raw metadata into sessions, sessions into project attributions, and attributions into an auditable invoice. This guide walks through what a commit actually tells you, the maths behind session splitting, the edge cases that trip teams up, and the full workflow from git log to a line-itemised bill your client will accept.
What do git commits actually tell you about time spent?
A commit is a timestamped event with three useful pieces of metadata. The author date tells you when the work was finished. The branch tells you what feature or ticket it belongs to. The commit message often contains a ticket reference — PROJ-142, #384, feat/login-refactor — that links the work to a client or project.
What a commit does not tell you is when the work started. A developer who commits at 15:42 might have begun at 15:20, 14:00, or yesterday. To reconstruct a time block, you need at least two commits on the same unit of work and a rule for what to assume about the first commit of a session.
Why the gap between commits matters
Gaps between commits carry more information than the commits themselves. A five-minute gap is active typing. A fifteen-minute gap is probably a coffee or a build. A ninety-minute gap is most likely lunch, a meeting, or the end of the day. Any mapping algorithm has to pick a threshold above which the gap counts as non-work rather than coding time.
Widely used open-source tools that estimate developer hours from git history default to around 120 minutes as the maximum gap inside a single session, with a smaller 20-30 minute window treated as continuous work. We will come back to why the choice of threshold is the single biggest driver of accuracy.
How does the algorithm behind git-to-time mapping work?
The core workflow has five steps. Each step turns raw git data into something closer to a billable line item.
Step 1: Extract the commit log with timestamps
Pull the data using git log with a custom format. The ISO 8601 timestamp, branch, author, and message are the only fields the algorithm needs.
git log --all --format='%H|%aI|%an|%D|%s' \
--since='2026-04-01' --until='2026-04-30' \
> commits.csv
The %aI format gives strict ISO 8601 which is easy to parse in any language. Add %D for ref names so you can tell which branch or tag the commit belongs to. If you work across several repositories, run the same command in each and tag rows with the repo name before merging.
Step 2: Group commits by branch or ticket reference
Sort commits by author. Within each author, group by the branch name or the ticket ID parsed from the commit message. Commits that share a ticket belong to the same unit of work even when they cross branch boundaries — which happens during rebases and cherry-picks.
A regex such as \b[A-Z]+-\d+\b catches most issue-tracker ticket formats. For GitHub-style references, look for #\d+ near the start of the message.
Step 3: Calculate elapsed time between commits
Inside each group, sort commits by timestamp. For every adjacent pair, compute the delta in minutes. This gives you a raw duration series — the bones of a timesheet.
Step 4: Apply an idle threshold to split sessions
Walk the delta series in order. If a delta is under the idle threshold, the two commits belong to the same session. If it is over, close the current session and start a new one. The first commit of each session adds a small fixed increment — typically 2-5 minutes — to represent the work that preceded that initial commit.
A 20-minute threshold is aggressive and undercounts teams who think before they type. A 60-minute threshold is generous and risks billing lunch as development. A 30-minute threshold is the value most open-source git-hours tools pick as their default compromise.
Step 5: Assign each session to a project
Use a mapping table: branch pattern or repo name to client or project. A repo called acme-checkout rolls up to Client Acme. A branch matching feat/PROJ-* rolls up to Project PROJ. If your commits reference tickets from an issue tracker, reverse that link and ask the tracker which project each ticket belongs to.
Well-designed activity-based time trackers extend this same logic with pull request events, code review comments, and calendar entries — pulling in signals a commit-only parser cannot see. For teams that already set up time tracking with GitHub, this is the layer that turns raw events into a draft timesheet without a stopwatch.
How do you handle meetings, reviews, and non-commit work?
Commit-only analysis covers the typing part of a developer’s day. It misses four categories of work that often carry the highest billing rates.
Code reviews
Reviewing a pull request produces review comments and approvals — events that GitHub and GitLab emit through their APIs but that never land as commits in the reviewer’s history. A mapping system that listens to pull_request_review and pull_request_review_comment webhooks captures this effort. One that only reads git logs will silently under-bill senior engineers whose main output is reviews rather than code. For more on this specific gap, see our guide to tracking time spent on code reviews.
Pair programming sessions
When two developers work on one keyboard, only one name appears in the commit log. Two strategies help. Use git commit --trailer "Co-authored-by: Name <email>" so both names are preserved, and split the calculated session evenly between the two authors in your billing system.
Meetings and async discussion
A kick-off call, a standup, a product review, a long Slack thread — all real work, none of it visible in git. The fix is to blend calendar events and chat activity with git sessions. Meetings that carry a ticket ID in the title attach cleanly to the same project as the commits.
The first commit of the day
There is always work before the first commit. Reading yesterday’s PR comments, setting up the environment, investigating a bug. A fixed lead-in time (5-15 minutes) on the first session of the day is a reasonable approximation. Long investigations — an hour of reading logs before any code gets written — need explicit capture via a manual entry or a calendar event.
How do you turn git sessions into an auditable invoice?
Raw sessions are not an invoice. An invoice needs three more layers on top.
Step 1: Review and adjust auto-generated sessions
A good dashboard shows each session next to its source events: the commits, PRs, and reviews that produced it. The developer scans the week, fixes anything misallocated — a commit pushed to the wrong branch, a session that was actually lunch — and approves.
According to the 2024 Stack Overflow Developer Survey, 61% of developers spend more than 30 minutes a day searching for answers or solutions. A timesheet that arrives pre-filled saves that half-hour at the end of the week as well as during it.
Step 2: Apply billing rates per project or client
Multiply approved minutes by the rate agreed with the client. Different projects can carry different rates — standard development, urgent hotfix, discovery work. If you charge a blended rate across a whole engagement, a single multiplier per client is enough.
Step 3: Export a line-itemised invoice with commit references
Export the approved hours as CSV or push them directly to your accounting tool. Each line item should carry the commit SHAs or PR numbers that back it up. Clients who receive a bill that says “14.5 hours — commits abc123 through def456 on the checkout refactor” rarely dispute the total. Clients who receive “development — 40 hours” often do. For the full flow from approved hours to billable document, see our guide on generating invoices from tracked hours.
How do you track time across multiple git repos?
Most billable engineering work now spans several repositories. A monorepo for one client, a services repo for another, a shared library team members contribute to from both. A mapping system that only looks at one repo misses the full picture.
The working pattern is simple. Run the extraction step against each repo the developer contributes to, tag every row with the repo name, and merge into a single timeline per author. When a commit in Repo A lands five minutes after a commit in Repo B, the algorithm treats it as a repo switch rather than a new session. The time allocation then splits across whichever clients those two repos map to.
One subtlety: commit authorship is identified by email address. Developers who use different emails for personal and client work will appear as two authors unless you maintain a mailmap. Add a .mailmap file or a central alias table and check it into version control.
What is the maths of how much accuracy git commits actually give you?
Under realistic settings — 30-minute idle threshold, 5-minute lead-in, commits every 30-60 minutes on average — commit-only analysis recovers 70-80% of billable developer time with no manual logging. PR and review events push that to around 90%. Calendar blending closes most of the remaining gap.
The comparison that matters is not “git activity vs a perfect timesheet” but “git activity vs the timesheet a developer fills in on Friday afternoon from memory”. Recall-based timesheets are routinely 20-30% off on both sides — some hours padded, others forgotten. An activity-backed timesheet has a shorter error bar and a clear audit trail behind every entry.
What should you do next?
Three practical moves turn this from theory into a working system.
First, pick an idle threshold and a lead-in value and stick with them for a full month. Changing thresholds mid-cycle makes the numbers impossible to compare.
Second, map every repo to a client or project up front. Do this once, review it quarterly, and never let “unassigned” appear on a timesheet.
Third, wire the approved hours directly into your billing tool. Re-keying hours from one system to another is where the evidence trail breaks and where client disputes start. Teams that set up time tracking with GitHub and export straight into accounting tools rarely have an invoice challenged on volume alone.
Key Takeaway: Commit timestamps plus a 30-minute idle threshold plus repo-to-client mapping recovers roughly 80% of billable developer time automatically. Reviews and calendar events cover most of the rest.
Frequently Asked Questions
Can I map git commits to billable time if I use a monorepo?
Yes. In a monorepo, apply path-based rules instead of repo-based rules. A commit touching packages/acme-checkout/** rolls up to Client Acme; a commit touching packages/shared/** maps to an internal cost code. Most activity-based trackers support directory-level client mapping out of the box.
What happens if I squash commits before merging?
Squashing collapses individual timestamps into a single commit. For accurate time mapping, capture the commit data before the squash merge — from the feature branch rather than main — or use pull request events as the primary signal. Branch-level activity is more resilient than individual commits for teams that squash by policy.
Is git commit time mapping GDPR compliant?
Tracking work timestamps for billing purposes is generally permissible under the legitimate interest lawful basis, provided developers are informed and can access their own data. Store only what you need, document the purpose, and allow correction of auto-generated entries. A published privacy notice and an exclusion path for non-billable hours are proven approaches for staying compliant.
How do you handle work done without commits, like investigating a bug?
Blend git activity with calendar entries and optional manual entries. A two-hour debugging session that produced no code can be captured as a calendar block tagged with the ticket ID, or as a single manual entry with a note. The principle is to keep git as the primary evidence and treat other signals as supplements.
What idle threshold should I use between commits?
A 30-minute threshold is the most common default in open-source git-hours tools and produces the best balance between undercounting and overcounting. Teams that commit rarely — half a dozen times a day — should raise it to 60 minutes. Teams that commit very frequently can lower it to 15-20 minutes.
Will my developers feel this is surveillance?
Only if it is run without their knowledge or consent. Activity-based tracking that shows each developer their own draft timesheet, lets them edit it, and uses it for billing rather than performance is generally welcomed — because it replaces Friday-afternoon reconstruction with a one-click approval. For the full argument, see our guide on developer productivity without surveillance.
How many commits per day are enough for accurate tracking?
Accuracy stabilises at around 3-5 commits per working day. Below that, you rely more heavily on lead-in assumptions. Above about 10 commits, accuracy plateaus because the algorithm has plenty of timestamps to reason about. Encouraging small, frequent commits improves both time accuracy and code review quality.
Ready to turn commits into billable hours automatically?
Connect your repos to Keito and let your git activity build accurate, client-ready timesheets. Review on Friday, approve in a click, export straight to your invoicing tool.