git-archaeologist 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +32 -38
- package/dist/core/gitParser.d.ts +2 -2
- package/dist/core/gitParser.d.ts.map +1 -1
- package/dist/core/gitParser.js +6 -4
- package/dist/core/gitParser.js.map +1 -1
- package/dist/core/orchestrator.d.ts +1 -1
- package/dist/core/orchestrator.d.ts.map +1 -1
- package/dist/core/orchestrator.js +5 -4
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/output/htmlReport.d.ts.map +1 -1
- package/dist/output/htmlReport.js +193 -140
- package/dist/output/htmlReport.js.map +1 -1
- package/package.json +5 -5
- package/preview.png +0 -0
- package/demo.gif +0 -0
- package/git-arch-report-express.html +0 -513
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sushant Verma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
# git-archaeologist
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](./preview.png)
|
|
4
4
|
|
|
5
|
-
](https://www.npmjs.com/package/git-archaeologist) [](LICENSE) [](https://nodejs.org)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> Find the most dangerous files in any git repo — before you touch them.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
[Install](#install) · [Usage](#usage) · [What it finds](#what-it-finds) · [How scoring works](#how-scoring-works)
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
**Cursed file score** — not just most changed. A file touched 100 times in 6 months by 12 developers who never talked scores way higher than one touched 100 times over 5 years by the same person.
|
|
16
|
-
|
|
17
|
-
**Bus factor per folder** — not per repo. Knowing the lib/ folder will be orphaned the day Douglas leaves is actionable. Knowing the whole repo has bus factor 2 is useless.
|
|
18
|
-
|
|
19
|
-
**Implicit coupling** — files that always change together even though nothing in the code connects them. Hidden dependencies. Future outages.
|
|
13
|
+
You inherit a codebase. You touch a file. Three things break that you had no idea were connected.
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
---
|
|
15
|
+
This tool reads your entire git history and tells you which files are ticking time bombs, who will orphan a whole module when they quit, which files are secretly coupled even though nothing in the code shows it, and who truly owns what right now.
|
|
24
16
|
|
|
25
17
|
## Install
|
|
26
18
|
|
|
@@ -28,49 +20,51 @@ I wrote this after two days tracking a bug that started because I touched a file
|
|
|
28
20
|
npm install -g git-archaeologist
|
|
29
21
|
```
|
|
30
22
|
|
|
31
|
-
---
|
|
32
|
-
|
|
33
23
|
## Usage
|
|
34
24
|
|
|
35
25
|
```bash
|
|
36
|
-
# full report
|
|
37
26
|
git-arch analyze /path/to/repo
|
|
27
|
+
git-arch analyze /path/to/repo --since 90d # only last 90 days of commits
|
|
28
|
+
git-arch analyze /path/to/repo --since 2y # only last 2 years
|
|
29
|
+
git-arch analyze /path/to/repo --since 2024-01-01 # since a specific date
|
|
30
|
+
git-arch analyze /path/to/repo --html # dark-themed interactive report
|
|
31
|
+
git-arch cursed --top 10 # just the danger ranking
|
|
32
|
+
git-arch analyze /path/to/repo --json # pipe into other tools
|
|
33
|
+
```
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
git-arch cursed --top 10
|
|
41
|
-
|
|
42
|
-
# shareable HTML report
|
|
43
|
-
git-arch analyze /path/to/repo --html
|
|
35
|
+
## What it finds
|
|
44
36
|
|
|
45
|
-
|
|
46
|
-
git-arch analyze /path/to/repo --json
|
|
47
|
-
```
|
|
37
|
+
Curse score — not just most changed. A file touched 100 times in 6 months by 15 people who never talked scores way higher than one touched 200 times over a decade by the same person. Recency, author chaos, and churn rate combined into one number.
|
|
48
38
|
|
|
49
|
-
|
|
39
|
+
Bus factor per folder — not per repo. Knowing the whole repo has bus factor 2 is useless. Knowing lib/ is orphaned the day one person leaves is something you can act on.
|
|
50
40
|
|
|
51
|
-
|
|
41
|
+
Implicit coupling — files that always change together in the same commit even though nothing in the code connects them. These are your hidden dependencies.
|
|
52
42
|
|
|
53
|
-
|
|
43
|
+
Ownership — who owns the lines alive in HEAD right now, not who created the file or who committed last.
|
|
54
44
|
|
|
55
|
-
|
|
45
|
+
## Tested on Express.js
|
|
56
46
|
|
|
57
|
-
|
|
47
|
+
Express is one of the most downloaded npm packages in history. 230 contributors. 16 years old.
|
|
58
48
|
|
|
59
|
-
|
|
49
|
+
Running git-archaeologist on it takes 3 seconds and finds:
|
|
60
50
|
|
|
61
|
-
|
|
51
|
+
- `lib/response.js` — 128 changes, 53 different authors, curse score 2261. The core HTTP response logic of the framework has been touched by 53 people and nobody fully owns it.
|
|
52
|
+
- Bus factor across every module (lib/, test/, examples/, benchmarks/) is 1. One person. The entire project depends on Douglas Christopher Wilson continuing to show up.
|
|
53
|
+
- `benchmarks/Makefile` and `benchmarks/run` have been committed together 100% of the time. They have never changed separately. They are one file.
|
|
62
54
|
|
|
63
|
-
##
|
|
55
|
+
## How scoring works
|
|
64
56
|
|
|
65
57
|
```
|
|
66
58
|
curse_score = changes x log2(authors+1) x exp(-0.5 x age_years) x log2(churn_rate+2)
|
|
67
59
|
```
|
|
68
60
|
|
|
69
|
-
The exponential decay on age means old chaos that stabilized does not show up. Only
|
|
61
|
+
The exponential decay on age means old chaos that stabilized does not show up. Only files actively dangerous right now.
|
|
70
62
|
|
|
71
|
-
|
|
63
|
+
## Requirements
|
|
72
64
|
|
|
73
|
-
|
|
65
|
+
Node.js >= 18 and git >= 2.30. Works on Linux, macOS, and Windows (WSL).
|
|
66
|
+
|
|
67
|
+
## Contributing
|
|
74
68
|
|
|
75
69
|
```bash
|
|
76
70
|
git clone https://github.com/SushantVerma7969/git-archaeologist.git
|
|
@@ -79,6 +73,6 @@ npm install && npm run build
|
|
|
79
73
|
node dist/index.js analyze /any/repo
|
|
80
74
|
```
|
|
81
75
|
|
|
82
|
-
|
|
76
|
+
## License
|
|
83
77
|
|
|
84
|
-
MIT
|
|
78
|
+
[MIT](LICENSE)
|
package/dist/core/gitParser.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CommitRecord, FileStats } from '../types';
|
|
2
2
|
export declare function validateRepo(repoPath: string): void;
|
|
3
3
|
export declare function getRepoName(repoPath: string): string;
|
|
4
|
-
export declare function getTotalCommitCount(repoPath: string): number;
|
|
5
|
-
export declare function parseCommits(repoPath: string): CommitRecord[];
|
|
4
|
+
export declare function getTotalCommitCount(repoPath: string, since?: string): number;
|
|
5
|
+
export declare function parseCommits(repoPath: string, since?: string): CommitRecord[];
|
|
6
6
|
export declare function buildFileStats(commits: CommitRecord[]): Map<string, FileStats>;
|
|
7
7
|
//# sourceMappingURL=gitParser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitParser.d.ts","sourceRoot":"","sources":["../../src/core/gitParser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CASnD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAcpD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"gitParser.d.ts","sourceRoot":"","sources":["../../src/core/gitParser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CASnD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAcpD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAS5E;AAYD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CA0C7E;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CA+B9E"}
|
package/dist/core/gitParser.js
CHANGED
|
@@ -68,8 +68,9 @@ function getRepoName(repoPath) {
|
|
|
68
68
|
}
|
|
69
69
|
return path.basename(path.resolve(repoPath));
|
|
70
70
|
}
|
|
71
|
-
function getTotalCommitCount(repoPath) {
|
|
72
|
-
const
|
|
71
|
+
function getTotalCommitCount(repoPath, since) {
|
|
72
|
+
const sinceFlag = since ? ` --after="${since}"` : '';
|
|
73
|
+
const out = (0, child_process_1.execSync)(`git rev-list --count HEAD${sinceFlag}`, {
|
|
73
74
|
cwd: repoPath,
|
|
74
75
|
stdio: 'pipe',
|
|
75
76
|
})
|
|
@@ -86,10 +87,11 @@ function sanitizeFilePath(raw) {
|
|
|
86
87
|
}
|
|
87
88
|
return p;
|
|
88
89
|
}
|
|
89
|
-
function parseCommits(repoPath) {
|
|
90
|
+
function parseCommits(repoPath, since) {
|
|
90
91
|
const DELIMITER = '||GITARCH||';
|
|
91
92
|
const BEGIN_MARKER = 'BEGINCOMMIT' + DELIMITER;
|
|
92
|
-
const
|
|
93
|
+
const sinceFlag = since ? ` --after="${since}"` : '';
|
|
94
|
+
const raw = (0, child_process_1.execSync)(`git log --pretty=format:"${BEGIN_MARKER}%H${DELIMITER}%ae${DELIMITER}%an${DELIMITER}%at" --name-only${sinceFlag}`, { cwd: repoPath, stdio: 'pipe', maxBuffer: 512 * 1024 * 1024 }).toString();
|
|
93
95
|
const commits = [];
|
|
94
96
|
const blocks = raw
|
|
95
97
|
.split(BEGIN_MARKER)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitParser.js","sourceRoot":"","sources":["../../src/core/gitParser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,oCASC;AAED,kCAcC;AAED,
|
|
1
|
+
{"version":3,"file":"gitParser.js","sourceRoot":"","sources":["../../src/core/gitParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAY1C,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAY1C,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAkEvF"}
|
|
@@ -9,16 +9,17 @@ const gitParser_1 = require("./gitParser");
|
|
|
9
9
|
const curseScorer_1 = require("../analyzers/curseScorer");
|
|
10
10
|
const ownershipAnalyzer_1 = require("../analyzers/ownershipAnalyzer");
|
|
11
11
|
const busFactorAnalyzer_1 = require("../analyzers/busFactorAnalyzer");
|
|
12
|
-
async function analyze(repoPath) {
|
|
12
|
+
async function analyze(repoPath, since) {
|
|
13
13
|
const spinner = (0, ora_1.default)({ text: 'Validating repository...', color: 'magenta' }).start();
|
|
14
14
|
try {
|
|
15
15
|
// Step 1 — validate
|
|
16
16
|
(0, gitParser_1.validateRepo)(repoPath);
|
|
17
17
|
const repoName = (0, gitParser_1.getRepoName)(repoPath);
|
|
18
|
-
const totalCommits = (0, gitParser_1.getTotalCommitCount)(repoPath);
|
|
19
|
-
|
|
18
|
+
const totalCommits = (0, gitParser_1.getTotalCommitCount)(repoPath, since);
|
|
19
|
+
const sinceLabel = since ? ` (since ${since})` : '';
|
|
20
|
+
spinner.text = `Parsing ${totalCommits.toLocaleString()} commits in ${repoName}${sinceLabel}...`;
|
|
20
21
|
// Step 2 — parse all commits
|
|
21
|
-
const commits = (0, gitParser_1.parseCommits)(repoPath);
|
|
22
|
+
const commits = (0, gitParser_1.parseCommits)(repoPath, since);
|
|
22
23
|
spinner.text = 'Building file statistics...';
|
|
23
24
|
// Step 3 — build per-file stats
|
|
24
25
|
const fileStats = (0, gitParser_1.buildFileStats)(commits);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":";;;;;AAaA,
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -43,22 +43,42 @@ const path = __importStar(require("path"));
|
|
|
43
43
|
const orchestrator_1 = require("./core/orchestrator");
|
|
44
44
|
const terminalRenderer_1 = require("./output/terminalRenderer");
|
|
45
45
|
const htmlReport_1 = require("./output/htmlReport");
|
|
46
|
+
function parseSince(input) {
|
|
47
|
+
// Accept: 90d, 30days, 6months, 1year, or ISO date like 2024-01-01
|
|
48
|
+
const match = input.match(/^(\d+)\s*(d|day|days|m|month|months|y|year|years)$/i);
|
|
49
|
+
if (match) {
|
|
50
|
+
const n = parseInt(match[1], 10);
|
|
51
|
+
const unit = match[2].toLowerCase();
|
|
52
|
+
const date = new Date();
|
|
53
|
+
if (unit.startsWith('d'))
|
|
54
|
+
date.setDate(date.getDate() - n);
|
|
55
|
+
else if (unit.startsWith('m'))
|
|
56
|
+
date.setMonth(date.getMonth() - n);
|
|
57
|
+
else if (unit.startsWith('y'))
|
|
58
|
+
date.setFullYear(date.getFullYear() - n);
|
|
59
|
+
return date.toISOString().split('T')[0];
|
|
60
|
+
}
|
|
61
|
+
// Already a date string
|
|
62
|
+
return input;
|
|
63
|
+
}
|
|
46
64
|
const program = new commander_1.Command();
|
|
47
65
|
program
|
|
48
66
|
.name('git-arch')
|
|
49
67
|
.description(chalk_1.default.hex('#A78BFA')('⛏ Git Archaeologist') +
|
|
50
68
|
' — uncover history, ownership & tech debt in any git repo')
|
|
51
|
-
.version('1.
|
|
69
|
+
.version('1.1.0');
|
|
52
70
|
program
|
|
53
71
|
.command('analyze [repoPath]')
|
|
54
72
|
.alias('a')
|
|
55
73
|
.description('Analyze a git repository and print the full report')
|
|
56
74
|
.option('-j, --json', 'Output raw JSON instead of the terminal report')
|
|
57
75
|
.option('-H, --html [outputFile]', 'Generate an HTML report file')
|
|
76
|
+
.option('-s, --since <date>', 'Only analyze commits after this date (e.g. 90d, 2024-01-01, 6months)')
|
|
58
77
|
.action(async (repoPath, options) => {
|
|
59
78
|
const resolvedPath = path.resolve(repoPath ?? '.');
|
|
79
|
+
const since = options.since ? parseSince(options.since) : undefined;
|
|
60
80
|
try {
|
|
61
|
-
const result = await (0, orchestrator_1.analyze)(resolvedPath);
|
|
81
|
+
const result = await (0, orchestrator_1.analyze)(resolvedPath, since);
|
|
62
82
|
if (options.json) {
|
|
63
83
|
const serializable = {
|
|
64
84
|
...result,
|
|
@@ -114,7 +134,7 @@ program
|
|
|
114
134
|
.action(async () => {
|
|
115
135
|
const resolvedPath = path.resolve('.');
|
|
116
136
|
try {
|
|
117
|
-
const result = await (0, orchestrator_1.analyze)(resolvedPath);
|
|
137
|
+
const result = await (0, orchestrator_1.analyze)(resolvedPath, undefined);
|
|
118
138
|
(0, terminalRenderer_1.renderReport)(result);
|
|
119
139
|
}
|
|
120
140
|
catch (err) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,yCAAoC;AACpC,kDAA0B;AAC1B,2CAA6B;AAE7B,sDAA8C;AAC9C,gEAAyD;AACzD,oDAAyD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlReport.d.ts","sourceRoot":"","sources":["../../src/output/htmlReport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"htmlReport.d.ts","sourceRoot":"","sources":["../../src/output/htmlReport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA8B1C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAsLnF"}
|