Count number of lines in a git repository
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The fastest way to count lines in a git repository is git ls-files | xargs wc -l. For a language-aware breakdown that separates code from comments and blanks, use cloc $(git ls-files). This article covers both approaches along with advanced filtering, per-author attribution, historical tracking, and CI integration.
Basic Line Count with git ls-files and wc
The simplest approach pipes the list of tracked files into wc -l:
This produces a per-file count followed by a total:
git ls-files only lists files tracked by git, so anything in .gitignore is automatically excluded. This is an advantage over find . -type f, which would include build artifacts, node_modules, and other ignored content.
Handle Filenames with Spaces
If your repository contains files with spaces or special characters in their names, the basic pipe breaks. Use null-terminated output instead:
The -z flag makes git ls-files output null-separated paths, and -0 tells xargs to split on null bytes instead of whitespace.
Filter by File Type
Counting every file is rarely what you want. A repository typically contains source code, configuration, documentation, images, and vendor dependencies. Filter by extension to get meaningful numbers:
You can also exclude entire directories:
Language-Aware Counting with cloc
cloc (Count Lines of Code) is a dedicated tool that recognizes programming languages, separates code from comments and blank lines, and produces a structured report.
Sample output:
Install cloc with your system package manager:
cloc vs wc Comparison
| Feature | git ls-files + wc | cloc |
| Language detection | No | Yes |
| Separates code/comments/blanks | No | Yes |
| Handles binary files | Counts (incorrectly) | Skips automatically |
| Installation | Built-in | Requires install |
| Speed on large repos | Fast | Moderate |
| Output formats | Text only | Text, JSON, CSV, XML |
For CI reporting or dashboards, cloc can output JSON:
Count Lines by Author
To see how many lines each developer currently has in the repository:
This runs git blame on every file and counts lines per author. The output looks like:
Be aware that this takes significant time on large repositories because it runs git blame on every tracked file.
For a faster approximation, git shortlog counts commits rather than lines, but it gives a useful sense of contribution distribution:
Track Line Count Over Time
To see how the codebase size has changed, you can script git to check out historical commits and count lines:
A more practical approach uses git diff --stat between two references:
Sample output:
Count Lines Changed in a Time Period
To measure recent development activity:
This counts the net lines added and removed across all commits in the time window.
Integration with CI/CD
Adding line count tracking to a CI pipeline creates a historical record. Here is a GitHub Actions example:
This adds a formatted table to the GitHub Actions summary page and saves the JSON report as a build artifact.
Alternative Tools
| Tool | Focus | Install |
cloc | Language-aware line counting | brew install cloc |
tokei | Fast line counting (Rust-based) | brew install tokei |
scc | Fast counting with complexity estimates | brew install scc |
loc | Minimal and fast (Rust-based) | cargo install loc |
tokei and scc are notably faster than cloc on large repositories. scc also estimates code complexity (COCOMO model) alongside line counts:
Common Pitfalls
Using find . -type f | xargs wc -l instead of git ls-files counts untracked files like build outputs, dependencies, and editor temp files. Always use git ls-files to respect the repository's tracking rules.
Not handling filenames with spaces causes xargs to split paths incorrectly and produce wrong counts or errors. Always use the -z and -0 flags for robustness.
Counting lines without filtering by file type inflates the number with auto-generated code, lockfiles, and vendor dependencies. A 50,000-line repository might actually contain 8,000 lines of application code and 42,000 lines of package-lock.json.
Confusing total lines with lines of code is misleading. A file with 100 lines might contain 60 lines of code, 25 lines of comments, and 15 blank lines. Use cloc or similar tools when the distinction matters.
Running git blame across the entire repository for author attribution is slow on large codebases. It scales linearly with repository size and history depth. For rough estimates, git shortlog -sn is much faster.
Summary
- Use
git ls-files | xargs wc -lfor a quick total line count of tracked files. - Use
git ls-files -z | xargs -0 wc -lwhen filenames may contain spaces. - Filter by extension (
git ls-files '*.py') to count only relevant source files. - Use
cloc $(git ls-files)for language-aware breakdown of code, comments, and blanks. - Use
git diff --shortstatto measure changes between two points in history. - Consider
tokeiorsccas faster alternatives toclocfor large repositories.

