| --- |
| license: mit |
| language: |
| - en |
| pipeline_tag: text-classification |
| --- |
| # git-commits-sorter |
|
|
| Classify raw git commit messages into categories (`bugfix`, `feature`, `chore`, `docs`, `refactor`, etc.) using a hybrid ML pipeline: TF-IDF + metadata → SVM / RF / CatBoost. |
|
|
| ## Features |
|
|
| - **Hybrid model** — combines TF-IDF on the message text with numeric features (files changed, additions, deletions, test/doc/src counts) and categorical features (file extensions, directories) |
| - **Multiple classifiers** — LinearSVC, LogisticRegression, RandomForest, CatBoost, XGBoost |
| - **CPU & GPU** — `--gpu` flag enables cuML / CatBoost GPU / XGBoost GPU automatically |
| - **Auto-labeled dataset** — 83% of raw commits automatically labeled via conventional commit prefixes, gitmoji, and keyword heuristics |
| - **Resumable scraping** — GitHub commit scraper with exponential backoff, progress persistence, and connection error resilience |
|
|
| ## Pipeline |
|
|
| ``` |
| parser.py → GitHub API → commits.jsonl (resilient scraping) |
| build_dataset.py → commits.jsonl → dataset.jsonl (auto-label + feature extraction) |
| train.py → dataset.jsonl → model.joblib (train & save) |
| predict.py → model.joblib → label (inference CLI) |
| commitsorter.py → CommitClassifier class (library API) |
| ``` |
|
|
| ## Usage |
|
|
| ### CLI |
|
|
| ```bash |
| # single prediction |
| python predict.py "fix broad phase crash" 3 45 12 |
| |
| # positional args: message [files_count] [additions] [deletions] |
| python predict.py "bump lodash to 2.1" |
| |
| # batch via stdin |
| echo '{"text":"fix crash","files_count":2} |
| {"text":"add login page","files_count":5,"additions":200}' | python predict.py --stdin |
| ``` |
|
|
| ### Library |
|
|
| ```python |
| from commitsorter import CommitClassifier |
| |
| clf = CommitClassifier("model.joblib") |
| |
| label, scores = clf.sort("fix renderer crash", files_count=2, additions=10) |
| # → ("bugfix", [("bugfix", 0.77), ("chore", 0.11), ...]) |
| |
| results = clf.sort_batch([ |
| {"text": "update dependencies", "files_count": 1}, |
| {"text": "add user auth", "files_count": 5, "additions": 200}, |
| ]) |
| ``` |
|
|
| ### Training |
|
|
| ```bash |
| # single model (default: SVM) |
| python train.py svm |
| python train.py lr |
| python train.py rf |
| python train.py cb |
| python train.py xgb |
| |
| # tournament — compare all models |
| python train.py --all |
| |
| # GPU acceleration (requires cuML / CUDA) |
| python train.py svm --gpu |
| python train.py --all --gpu |
| ``` |
|
|
| ## Dataset features |
|
|
| Each training sample: |
|
|
| | Field | Type | Description | |
| |---|---|---| |
| | `text` | string | Commit message (prefix stripped) | |
| | `files_count` | int | Number of files changed | |
| | `additions` | int | Lines added | |
| | `deletions` | int | Lines deleted | |
| | `changed_tests` | int | Test files touched | |
| | `changed_docs` | int | Doc files touched | |
| | `changed_source` | int | Source files touched | |
| | `has_tests` | bool | Any file in a test directory | |
| | `has_docs` | bool | Any file in a docs directory | |
| | `extensions` | [string] | Unique file extensions | |
| | `directories` | [string] | Unique top-level directories | |
| | `label` | string | Target class | |
|
|
| ## Model: TF-IDF + metadata |
|
|
| ``` |
| commit message ──→ TF-IDF(10k unigrams+bigrams) |
| file metadata ──→ StandardScaler |
| extensions ──→ OneHotEncoder |
| directories ──→ OneHotEncoder |
| ↓ |
| ColumnTransformer |
| ↓ |
| LinearSVC / RF / CatBoost / XGBoost |
| ``` |
|
|
| Best result: **LinearSVC at 79% accuracy** on held-out test set. |
|
|
| ## Supported labels |
|
|
| | Label | Heuristics | |
| |---|---| |
| | `bugfix` | `fix:`, `:bug:`, "crash", "prevent" | |
| | `feature` | `feat:`, `:sparkles:`, "add", "implement" | |
| | `chore` | `chore:`, "bump", "update", "lint" | |
| | `docs` | `docs:`, file-only docs/, `.md` | |
| | `refactor` | `refactor:`, "cleanup", "remove", "rename" | |
| | `test` | `test:`, file-only spec/ or test/ | |
| | `build` | `build:`, "upgrade", dependency changes | |
| | `ci` | `ci:`, CI config changes | |
| | `perf` | `perf:`, "optimize" | |
| | `style` | `style:`, "format", "prettier" | |
| | `revert` | `revert:` | |
|
|
| ## Data scraping |
|
|
| ```bash |
| # needs GITHUB_TOKEN in .env |
| python parser.py |
| ``` |
|
|
| Collects commits from configured repos into `commits.jsonl`. Resumes on interrupt via `progress.json`. |