GitHub already records a large part of your development history. The difficult part is not collecting the activity; it is turning that activity into a useful account of how your work changes over time.

A contribution graph can tell you that something happened on a given day. It cannot, by itself, tell you whether a repository expanded, contracted, changed languages, went dormant, came back to life, or passed through a period of unusually high churn.

A better analysis starts by treating Git history as a longitudinal record rather than a score.

Start with a time window

Metrics become easier to interpret when every number belongs to a clearly defined period.

Compare the last 30 days with the previous 30 days — the 7D, 30D, 90D, YTD, and 1Y ranges each answer a different question. Look at a quarter when you want to understand a release cycle. Use a year when you want to see changes in language mix, repository activity, or the cadence of work.

The same commit count can mean very different things across different windows. A burst of 80 commits during a migration is not equivalent to 80 commits distributed across several months of maintenance.

The first question should therefore be: what period am I actually trying to understand?

Measure source growth separately from activity

Commit counts describe activity. They do not describe the direction of the codebase.

For that, additions and deletions matter.

A simple measure is:

net source growth = additions - deletions

Positive net growth means more source was added than removed during the selected period. Negative net growth can be equally informative: a refactor, migration, decommissioning, or simplification may remove a large amount of code while improving the project.

The important point is that growth is descriptive, not automatically good or bad.

Use churn to see how intensely code is changing

Churn looks at additions and deletions together rather than subtracting one from the other.

A useful basic definition is:

churn = additions + deletions

High churn can accompany a rewrite, major refactor, generated-code change, branch correction, or rapid feature development. Low churn can describe a stable maintenance period.

Churn is particularly useful beside net growth. Two periods can have identical net growth but radically different churn. Adding 1,000 lines with almost no deletions is a different kind of change from adding 6,000 lines while deleting 5,000.

Treat commit count as context, not productivity

Commits are useful, but they are easy to overinterpret.

Different developers structure commits differently. Some make small, atomic commits. Others consolidate work. Rebases, squash merges, bots, generated files, and repository conventions can all change the shape of the history.

Commit count is most useful when you use it to answer narrower questions:

  • When was a repository most active?
  • Did activity become more or less frequent?
  • Which periods contain unusual bursts?
  • How does commit cadence align with source growth or churn?

It is much weaker as a standalone measure of developer ability or productivity.

Look at active days and cadence

The distribution of work across time often reveals more than the raw total.

Active days can show whether a period was concentrated or sustained. Streaks can expose uninterrupted runs of development. Time-of-day patterns can reveal when work usually happens.

These are descriptive patterns, not prescriptions. A long streak is not inherently superior to intermittent work, and a particular circadian pattern is not evidence of better engineering.

The value is in seeing the rhythm that aggregate totals hide.

Track language composition over time

A current language breakdown is a snapshot. A historical language breakdown is a trajectory.

Language changes can indicate:

  • a new frontend or backend stack
  • a migration away from an older implementation
  • the introduction of infrastructure or automation
  • expansion into mobile, data, or systems work
  • a repository being replaced by another project

This becomes much more useful when language history is considered alongside repository history. A sudden rise in TypeScript, for example, means more when you can see which repositories drove it and when they became active.

Follow repository lifecycles

Repositories are not equally active forever.

A project may begin intensely, become quiet, enter maintenance, or revive after months of inactivity. Looking at those repository lifecycle transitions gives you a clearer picture of a body of work than treating every repository as a permanent, equally weighted object.

Useful questions include:

  • Which repositories are active now?
  • Which have become dormant?
  • Which were revived after a long gap?
  • When did a repository account for most of the development activity?
  • Did one project replace another?

This is where developer history starts to look less like a feed and more like a portfolio evolving through time.

Mark milestones instead of only totals

Totals compress history. Milestones restore some of its structure.

A milestone might be the first active month of a repository, a new language appearing, a project returning after a long dormant period, or a major shift in source growth.

Milestones help explain why a chart changed rather than simply showing that it changed.

Avoid conclusions the data cannot support

Repository metadata can reveal patterns, but it does not know the difficulty of a problem, the quality of an architectural decision, the amount of research behind a small change, or the value of work performed outside Git.

That limitation matters.

Developer analytics are most useful as an instrument for inspecting work, not as an automatic performance score.

A practical workflow

A useful review can be surprisingly simple:

  1. Choose a fixed range.
  2. Check net source growth and total churn.
  3. Inspect commit activity and active days.
  4. Identify the repositories responsible for the largest changes.
  5. Compare language composition with the previous period.
  6. Look for dormant, revived, or newly active projects.
  7. Record the milestones that explain the largest changes.
  8. Repeat with another range to see whether the pattern persists.

That sequence keeps the analysis grounded in context instead of chasing a single headline number.

Putting the history in one place

Dev Ledger was built around this idea: GitHub history is more useful when it can be read as a connected record of growth, activity, languages, milestones, and project evolution.

It uses read-only GitHub access and is designed to collect metrics rather than repository source code.

Open Dev Ledger or inspect the source on GitHub.