Skip to content

achhetr/git-trace

gittrace

License: MIT Contributions Welcome

A Kotlin CLI tool that runs git blame when given a file path with line number.

Usage

# Using -fl (file:line) - recommended
./gittrace -fl="src/main/kotlin/dev/gittrace/Main.kt:20"
./gittrace --file-line="src/Main.kt:42"

# Using separate -f and -l options
./gittrace -f="src/Main.kt" -l=42
./gittrace --file="src/Main.kt" --line=42

# Positional argument also works
gittrace src/Main.kt:42

# With context: show 5 lines before/after
./gittrace -fl="src/Main.kt:42" -n 5
./gittrace -f="src/Main.kt" -l=42 -n 5

# JSON output (for scripting/editor integration)
./gittrace -fl="src/Main.kt:42" --json
./gittrace -f="src/Main.kt" -l=42 --json

# Profile scan duration (ms)
./gittrace -fl="src/Main.kt:42" -pf

# Skip scope for speed in large repos (e.g. Rails, Linux kernel)
./gittrace -fl="src/Main.kt:42" -S

# Single-line output: "You, 20 mins ago * commit message"
./gittrace -fl="src/Main.kt:42" -ol

# Full file blame
./gittrace -fl="src/Main.kt:1" --full
./gittrace -f="src/Main.kt" -l=1 --full

Output Format

Shows commit details for the target line (no raw blame table):

─── src/main/kotlin/dev/gittrace/Main.kt : Commit f2fe7845 (covers lines 18, 20–22) ───
Status:     committed
Scope:      5 files, 77 lines changed
Author:     Akash Paudel
Email:      akash.chhetri1@gmail.com
Message:    java version fixed and warning removed
When:       1 hours ago (2026-01-31 18:48)
SHA:        f2fe7845b7065628e3d10bf060470298c4e527f1
Commit:     https://github.com/owner/repo/commit/f2fe7845...
PR:         https://github.com/owner/repo/pull/123   (if commit message references #123)

Supports GitHub, GitLab, and Bitbucket URLs (from remote.origin.url).

For uncommitted lines: shows last committed state, committed vs current content (with whitespace markers), and diff.

Errors: Distinct messages for "Not in a git repository", "File is untracked (not in HEAD)", and "Git command failed". With --json, errors include errorKind: outside_repo, untracked, or git_failed.

Build & Run

# Build (use Java 17–24 if you have multiple JDKs, or use asdf)
./gradlew build

# Reclaim disk: remove build output (~6MB)
./gradlew clean

# Run from project directory
./gittrace -fl="src/main/kotlin/dev/gittrace/Main.kt:20"

# Install globally (use from any directory)
./install.sh
# or: ./gradlew install

# Then add to PATH if needed (add to ~/.zshrc):
export PATH="$HOME/.local/bin:$PATH"

# Run from anywhere
gittrace -fl="src/main/kotlin/dev/gittrace/Main.kt:20"

# Large repos (Rails, Linux, etc.): add -S for faster output (~40% faster)
gittrace -fl="activerecord/lib/active_record.rb:17" -S

Testing

# Run all tests
./gradlew test

# Run end-to-end test
./gradlew test --tests "*EndToEndTest.end-to-end test with -fl option"

# Generate test coverage report
./gradlew jacocoTestReport
# View report at: build/reports/jacoco/test/html/index.html

Requirements

  • JDK 17–24 (Java 25 has Kotlin compiler compatibility issues)
  • Git

asdf (recommended): The project includes .tool-versions for asdf. Install Java via:

asdf plugin add java   # if not already added
asdf install           # installs version from .tool-versions

If the build fails with Java 25, gradlew auto-switches to Java 17–24 when available. If it still fails, run ./gradlew --stop to clear cached daemons, or set JAVA_HOME to Java 24 (e.g. export JAVA_HOME=$(/usr/libexec/java_home -v 24)).

Project Structure

gittrace/
├── .tool-versions      # asdf: Java version for this project
├── gittrace            # Wrapper script: ./gittrace -fl="file:line"
├── install.sh          # Install globally: ./install.sh
├── build.gradle.kts
├── settings.gradle.kts
├── LICENSE             # MIT License
├── CONTRIBUTING.md     # Contribution guidelines
├── CODE_OF_CONDUCT.md  # Code of Conduct
└── src/main/kotlin/dev/gittrace/
    ├── Main.kt           # CLI entry point, Clikt command
    ├── LocationParser.kt # Parses "file:line" format
    ├── GitBlame.kt       # Runs git blame, error handling
    ├── GitParallel.kt    # Parallel git commands for perf
    ├── PorcelainParser.kt# Parses git blame --porcelain output
    ├── CommitFormatter.kt# Orchestrates formatting
    ├── HumanFormatter.kt # Human-readable output
    ├── JsonFormatter.kt  # JSON output (aligned schema)
    ├── FormatterUtils.kt # Shared time/range formatting
    ├── Constants.kt      # UNCOMMITTED_HASH, etc.
    ├── FormatOptions.kt  # JSON output options
    ├── GitLinks.kt       # Git ops, commit/PR URLs
    └── BlameEntry.kt     # Data model for blame lines

Contributing

We welcome contributions from the community! Whether it's bug fixes, new features, documentation improvements, or other enhancements, your help makes gittrace better for everyone.

How to Contribute

  1. Fork the repository and clone your fork
  2. Create a branch for your changes (git checkout -b feature/your-feature-name)
  3. Make your changes following our coding guidelines
  4. Test your changes (./gradlew clean build)
  5. Commit with clear messages
  6. Push to your fork and open a Pull Request

For detailed guidelines, please see CONTRIBUTING.md.

Areas We Need Help

  • 🐛 Bug fixes and issue resolution
  • ✨ New features and enhancements
  • 📚 Documentation improvements
  • 🧪 Test coverage
  • 🚀 Performance optimizations
  • 🌐 Platform compatibility (Windows, macOS, Linux)

Code of Conduct

Please read our Code of Conduct before contributing. We are committed to providing a welcoming and inclusive environment for all contributors.

Security

If you discover a security vulnerability, please follow our Security Policy for responsible disclosure.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Built with Kotlin
  • Uses Clikt for CLI parsing
  • Inspired by the need for better git blame tooling

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors