codeforge-dev 1.5.8 → 1.8.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/.devcontainer/.env +4 -5
- package/.devcontainer/.env.example +29 -0
- package/.devcontainer/.gitignore +8 -0
- package/.devcontainer/.secrets.example +12 -0
- package/.devcontainer/CHANGELOG.md +186 -0
- package/.devcontainer/CLAUDE.md +108 -21
- package/.devcontainer/README.md +173 -57
- package/.devcontainer/config/defaults/keybindings.json +5 -0
- package/.devcontainer/config/{main-system-prompt.md → defaults/main-system-prompt.md} +135 -2
- package/.devcontainer/config/{settings.json → defaults/settings.json} +25 -6
- package/.devcontainer/config/file-manifest.json +20 -0
- package/.devcontainer/devcontainer.json +38 -2
- package/.devcontainer/docs/configuration-reference.md +90 -0
- package/.devcontainer/docs/keybindings.md +100 -0
- package/.devcontainer/docs/optional-features.md +129 -0
- package/.devcontainer/docs/plugins.md +154 -0
- package/.devcontainer/docs/troubleshooting.md +128 -0
- package/.devcontainer/features/README.md +21 -7
- package/.devcontainer/features/agent-browser/install.sh +6 -0
- package/.devcontainer/features/ast-grep/install.sh +6 -0
- package/.devcontainer/features/biome/README.md +27 -0
- package/.devcontainer/features/biome/install.sh +6 -0
- package/.devcontainer/features/ccburn/README.md +60 -0
- package/.devcontainer/features/ccburn/devcontainer-feature.json +38 -0
- package/.devcontainer/features/ccburn/install.sh +180 -0
- package/.devcontainer/features/ccstatusline/README.md +22 -21
- package/.devcontainer/features/ccstatusline/devcontainer-feature.json +6 -1
- package/.devcontainer/features/ccstatusline/install.sh +55 -16
- package/.devcontainer/features/ccusage/install.sh +6 -0
- package/.devcontainer/features/claude-monitor/install.sh +6 -0
- package/.devcontainer/features/dprint/README.md +30 -0
- package/.devcontainer/features/dprint/devcontainer-feature.json +18 -0
- package/.devcontainer/features/dprint/install.sh +131 -0
- package/.devcontainer/features/hadolint/README.md +35 -0
- package/.devcontainer/features/hadolint/devcontainer-feature.json +13 -0
- package/.devcontainer/features/hadolint/install.sh +86 -0
- package/.devcontainer/features/lsp-servers/devcontainer-feature.json +5 -0
- package/.devcontainer/features/lsp-servers/install.sh +7 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +6 -1
- package/.devcontainer/features/mcp-qdrant/install.sh +13 -6
- package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +6 -1
- package/.devcontainer/features/mcp-reasoner/install.sh +8 -1
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +5 -0
- package/.devcontainer/features/notify-hook/install.sh +7 -0
- package/.devcontainer/features/ruff/README.md +26 -0
- package/.devcontainer/features/ruff/devcontainer-feature.json +21 -0
- package/.devcontainer/features/ruff/install.sh +74 -0
- package/.devcontainer/features/shellcheck/README.md +38 -0
- package/.devcontainer/features/shellcheck/devcontainer-feature.json +13 -0
- package/.devcontainer/features/shellcheck/install.sh +24 -0
- package/.devcontainer/features/shfmt/README.md +37 -0
- package/.devcontainer/features/shfmt/devcontainer-feature.json +13 -0
- package/.devcontainer/features/shfmt/install.sh +85 -0
- package/.devcontainer/features/splitrail/devcontainer-feature.json +5 -0
- package/.devcontainer/features/splitrail/install.sh +7 -0
- package/.devcontainer/features/tmux/install.sh +8 -0
- package/.devcontainer/features/tree-sitter/install.sh +6 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +3 -10
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/__pycache__/format-on-stop.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py +133 -13
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +4 -5
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/__pycache__/lint-file.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +477 -78
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/AGENT-REDIRECTION.md +226 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/REVIEW-RUBRIC.md +440 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +207 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/bash-exec.md +173 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +146 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +2 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +250 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +246 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +237 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +134 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/git-archaeologist.md +242 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/migrator.md +201 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/perf-profiler.md +265 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/refactorer.md +213 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/researcher.md +195 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/security-auditor.md +289 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +297 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/statusline-config.md +188 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/test-writer.md +248 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +51 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/advisory-test-runner.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/collect-edited-files.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/commit-reminder.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/git-state-injector.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/guard-readonly-bash.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/redirect-builtin-agents.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/skill-suggester.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/syntax-validator.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/ticket-linker.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/todo-harvester.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/verify-no-regression.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/verify-tests-pass.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/advisory-test-runner.py +174 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/collect-edited-files.py +8 -6
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/commit-reminder.py +90 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/git-state-injector.py +114 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/guard-readonly-bash.py +611 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/redirect-builtin-agents.py +83 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +146 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/syntax-validator.py +9 -4
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/ticket-linker.py +137 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/todo-harvester.py +130 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/verify-no-regression.py +221 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/verify-tests-pass.py +176 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/SKILL.md +224 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/references/error-handling.md +166 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/api-design/references/rest-conventions.md +215 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/ast-grep-patterns/SKILL.md +211 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/ast-grep-patterns/references/language-patterns.md +327 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/claude-agent-sdk/SKILL.md +599 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/claude-agent-sdk/references/sdk-typescript-reference.md +954 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/SKILL.md +134 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/references/ecosystem-commands.md +264 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/dependency-management/references/license-compliance.md +80 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/SKILL.md +153 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/references/api-doc-templates.md +221 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/references/docstring-formats.md +296 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/SKILL.md +276 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/references/advanced-commands.md +332 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/references/investigation-playbooks.md +319 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/SKILL.md +150 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/references/javascript-migrations.md +179 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/migration-patterns/references/python-migrations.md +141 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/SKILL.md +341 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/references/interpreting-results.md +235 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/references/tool-commands.md +395 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/SKILL.md +344 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/references/safe-transformations.md +247 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/references/smell-catalog.md +332 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/SKILL.md +277 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/references/owasp-patterns.md +269 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/references/secrets-patterns.md +253 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +320 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/references/criteria-patterns.md +245 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/references/ears-templates.md +239 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/__pycache__/block-dangerous.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/__pycache__/guard-protected.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +40 -39
- package/.devcontainer/scripts/check-setup.sh +72 -0
- package/.devcontainer/scripts/setup-aliases.sh +51 -6
- package/.devcontainer/scripts/setup-auth.sh +74 -0
- package/.devcontainer/scripts/setup-config.sh +112 -20
- package/.devcontainer/scripts/setup-plugins.sh +38 -46
- package/.devcontainer/scripts/setup-projects.sh +175 -0
- package/.devcontainer/scripts/setup-symlink-claude.sh +36 -0
- package/.devcontainer/scripts/setup-update-claude.sh +19 -8
- package/.devcontainer/scripts/setup.sh +49 -14
- package/README.md +23 -190
- package/package.json +1 -1
- package/setup.js +245 -71
- package/.devcontainer/features/claude-code/README.md +0 -498
- package/.devcontainer/features/claude-code/config/settings.json +0 -36
- package/.devcontainer/features/claude-code/config/system-prompt.md +0 -118
- package/.devcontainer/features/claude-code/config/world-building-sp.md +0 -1432
- package/.devcontainer/features/claude-code/devcontainer-feature.json +0 -42
- package/.devcontainer/features/claude-code/install.sh +0 -466
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +0 -7
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +0 -17
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +0 -6
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +0 -14
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +0 -989
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +0 -33
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +0 -71
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +0 -68
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +0 -120
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +0 -133
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +0 -253
- package/.devcontainer/scripts/setup-irie-claude.sh +0 -32
package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/SKILL.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-forensics
|
|
3
|
+
description: >-
|
|
4
|
+
This skill should be used when the user asks to "find who changed this line",
|
|
5
|
+
"search git history for a deleted function", "bisect a regression",
|
|
6
|
+
"recover a lost commit", "investigate when a bug was introduced",
|
|
7
|
+
"trace the history of a file", "search commit messages",
|
|
8
|
+
"find when code was removed", "check git blame", "use git reflog",
|
|
9
|
+
or discusses git archaeology, git bisect, git log search, pickaxe,
|
|
10
|
+
blame analysis, reflog recovery, or commit history investigation.
|
|
11
|
+
version: 0.1.0
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Git Forensics
|
|
15
|
+
|
|
16
|
+
## Mental Model
|
|
17
|
+
|
|
18
|
+
Git is a **forensic evidence system**. Every commit is a timestamped, attributed snapshot of a decision someone made. The history doesn't just record *what* changed -- it records *who* changed it, *when* they changed it, and (if commit messages are good) *why* they changed it.
|
|
19
|
+
|
|
20
|
+
Git forensics answers questions that code alone cannot:
|
|
21
|
+
- "When did this behavior change?" -- `git bisect`
|
|
22
|
+
- "Who last touched this logic and why?" -- `git blame`
|
|
23
|
+
- "When was this function deleted?" -- `git log -S`
|
|
24
|
+
- "What did this file look like 6 months ago?" -- `git show`
|
|
25
|
+
- "I accidentally reset -- can I recover?" -- `git reflog`
|
|
26
|
+
|
|
27
|
+
The key insight is that git stores *content*, not *files*. Git tracks blobs of content, and commands like `git log -S` search for when content was added or removed regardless of which file it was in. This makes git a powerful search engine for code archaeology.
|
|
28
|
+
|
|
29
|
+
Approach every investigation with a hypothesis. Start with the broadest tool (`git log`) to narrow the timeframe, then use focused tools (`git blame`, `git bisect`) to identify the exact commit.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Essential Commands
|
|
34
|
+
|
|
35
|
+
These commands form the daily toolkit for understanding code history:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Compact commit history with branch topology
|
|
39
|
+
git log --oneline --graph --all
|
|
40
|
+
|
|
41
|
+
# History of a specific file
|
|
42
|
+
git log --oneline -- path/to/file.py
|
|
43
|
+
|
|
44
|
+
# Show what changed in a specific commit
|
|
45
|
+
git show abc1234
|
|
46
|
+
|
|
47
|
+
# Show a file at a specific commit
|
|
48
|
+
git show abc1234:path/to/file.py
|
|
49
|
+
|
|
50
|
+
# Diff between two commits
|
|
51
|
+
git diff abc1234 def5678
|
|
52
|
+
|
|
53
|
+
# Diff between two branches
|
|
54
|
+
git diff main..feature-branch
|
|
55
|
+
|
|
56
|
+
# Who last modified each line (with commit and date)
|
|
57
|
+
git blame path/to/file.py
|
|
58
|
+
|
|
59
|
+
# Blame a specific line range
|
|
60
|
+
git blame -L 42,60 path/to/file.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Advanced Archaeology
|
|
66
|
+
|
|
67
|
+
### Pickaxe Search (`-S`)
|
|
68
|
+
|
|
69
|
+
Find commits that **added or removed** a specific string. This is the most powerful tool for finding when code appeared or disappeared:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Find when "calculate_tax" was added or removed
|
|
73
|
+
git log -S "calculate_tax" --oneline
|
|
74
|
+
|
|
75
|
+
# With diff to see the actual change
|
|
76
|
+
git log -S "calculate_tax" -p
|
|
77
|
+
|
|
78
|
+
# Restrict to specific files
|
|
79
|
+
git log -S "calculate_tax" --oneline -- "*.py"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`-S` counts occurrences -- it finds commits where the number of times the string appears changed. It's fast because it doesn't need to regex-match every line of every diff.
|
|
83
|
+
|
|
84
|
+
### Regex Search (`-G`)
|
|
85
|
+
|
|
86
|
+
Find commits where **a line matching a regex was added or removed**. More flexible than `-S` but slower:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Find commits that changed lines containing a pattern
|
|
90
|
+
git log -G "def\s+calculate_\w+" --oneline
|
|
91
|
+
|
|
92
|
+
# Combined with file filter
|
|
93
|
+
git log -G "TODO|FIXME|HACK" --oneline -- "*.py"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The difference: `-S "foo"` finds commits where the count of "foo" changed. `-G "foo"` finds commits where any changed line matches "foo". Use `-S` for exact strings, `-G` for patterns.
|
|
97
|
+
|
|
98
|
+
### Follow Renames (`--follow`)
|
|
99
|
+
|
|
100
|
+
Track a file across renames. Without `--follow`, history stops at the rename:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Follow a file through renames
|
|
104
|
+
git log --follow --oneline -- path/to/current_name.py
|
|
105
|
+
|
|
106
|
+
# Blame through renames
|
|
107
|
+
git log --follow -p -- path/to/file.py
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Contributor Statistics
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Commits per author (sorted)
|
|
114
|
+
git shortlog -sn --no-merges
|
|
115
|
+
|
|
116
|
+
# Commits per author in a date range
|
|
117
|
+
git shortlog -sn --after="2024-01-01" --before="2024-07-01"
|
|
118
|
+
|
|
119
|
+
# Files most frequently changed (hot spots)
|
|
120
|
+
git log --pretty=format: --name-only | sort | uniq -c | sort -rn | head -20
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
> **Deep dive:** See `references/advanced-commands.md` for the full command reference with all flags and options.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Bisect Workflow
|
|
128
|
+
|
|
129
|
+
`git bisect` performs a binary search through commit history to find the exact commit that introduced a bug. It halves the search space with each step.
|
|
130
|
+
|
|
131
|
+
### Manual Bisect
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Start bisecting
|
|
135
|
+
git bisect start
|
|
136
|
+
|
|
137
|
+
# Mark the current commit as bad (has the bug)
|
|
138
|
+
git bisect bad
|
|
139
|
+
|
|
140
|
+
# Mark a known-good commit (did not have the bug)
|
|
141
|
+
git bisect good v2.1.0
|
|
142
|
+
|
|
143
|
+
# Git checks out a middle commit. Test it, then:
|
|
144
|
+
git bisect good # if this commit doesn't have the bug
|
|
145
|
+
git bisect bad # if this commit has the bug
|
|
146
|
+
|
|
147
|
+
# Repeat until git identifies the first bad commit
|
|
148
|
+
# When done:
|
|
149
|
+
git bisect reset # return to your original branch
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
For 1000 commits, bisect finds the culprit in ~10 steps (log2(1000)).
|
|
153
|
+
|
|
154
|
+
### Automated Bisect
|
|
155
|
+
|
|
156
|
+
Provide a test script that exits 0 for good and non-zero for bad:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# Automated bisect with a test command
|
|
160
|
+
git bisect start HEAD v2.1.0
|
|
161
|
+
git bisect run pytest tests/test_tax.py -x
|
|
162
|
+
|
|
163
|
+
# Or with a custom script
|
|
164
|
+
git bisect run bash -c '
|
|
165
|
+
python -c "from myapp import calculate_tax; assert calculate_tax(100) == 7.5"
|
|
166
|
+
'
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The test script must be:
|
|
170
|
+
- **Self-contained** -- it can't rely on state from previous runs
|
|
171
|
+
- **Deterministic** -- same commit, same result
|
|
172
|
+
- **Fast** -- it runs once per bisect step; slow tests multiply the total time
|
|
173
|
+
|
|
174
|
+
Exit code 125 tells bisect to skip the current commit (useful for commits that don't compile).
|
|
175
|
+
|
|
176
|
+
> **Deep dive:** See `references/investigation-playbooks.md` for common investigation scenarios with step-by-step instructions.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Blame Deep Dive
|
|
181
|
+
|
|
182
|
+
Basic `git blame` shows the last commit to touch each line, but that's often a formatting change or bulk rename. Use flags to look deeper:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# Ignore whitespace changes
|
|
186
|
+
git blame -w path/to/file.py
|
|
187
|
+
|
|
188
|
+
# Detect lines moved within the file
|
|
189
|
+
git blame -M path/to/file.py
|
|
190
|
+
|
|
191
|
+
# Detect lines moved or copied from other files
|
|
192
|
+
git blame -C path/to/file.py
|
|
193
|
+
|
|
194
|
+
# Stack all three for maximum accuracy
|
|
195
|
+
git blame -w -M -C path/to/file.py
|
|
196
|
+
|
|
197
|
+
# Blame at a specific commit (go back before a known refactoring)
|
|
198
|
+
git blame abc1234^ -- path/to/file.py
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### .git-blame-ignore-revs
|
|
202
|
+
|
|
203
|
+
Large formatting commits (running `black`, `prettier`, or `gofmt`) pollute blame output. Create a file listing commits to skip:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Create .git-blame-ignore-revs at repo root
|
|
207
|
+
echo "# Black formatting pass" >> .git-blame-ignore-revs
|
|
208
|
+
echo "abc1234abc1234abc1234abc1234abc1234abc1234" >> .git-blame-ignore-revs
|
|
209
|
+
|
|
210
|
+
# Configure git to use it
|
|
211
|
+
git config blame.ignoreRevsFile .git-blame-ignore-revs
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Commit `.git-blame-ignore-revs` to the repo so the whole team benefits. GitHub and GitLab both respect this file in their web UI.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Reflog Recovery
|
|
219
|
+
|
|
220
|
+
The reflog records every change to `HEAD` and branch tips, even those not reachable from any branch. It's your safety net for recovering from mistakes.
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Show recent HEAD movements
|
|
224
|
+
git reflog
|
|
225
|
+
|
|
226
|
+
# Show reflog for a specific branch
|
|
227
|
+
git reflog show feature-branch
|
|
228
|
+
|
|
229
|
+
# Typical output:
|
|
230
|
+
# abc1234 HEAD@{0}: reset: moving to HEAD~3
|
|
231
|
+
# def5678 HEAD@{1}: commit: add user validation
|
|
232
|
+
# 789abcd HEAD@{2}: commit: fix login bug
|
|
233
|
+
|
|
234
|
+
# Recover a commit after accidental reset
|
|
235
|
+
git reflog # find the commit hash
|
|
236
|
+
git branch recovery-branch abc1234 # create a branch pointing to it
|
|
237
|
+
|
|
238
|
+
# Recover after accidental branch delete
|
|
239
|
+
git reflog | grep "feature-branch" # find the last commit
|
|
240
|
+
git branch feature-branch abc1234 # recreate the branch
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Reflog lifetime:** By default, unreachable reflog entries expire after 30 days, reachable ones after 90 days. For critical recovery, act within this window. Running `git gc` prunes expired entries.
|
|
244
|
+
|
|
245
|
+
**What reflog can recover:**
|
|
246
|
+
- Commits after `git reset --hard`
|
|
247
|
+
- Deleted branches
|
|
248
|
+
- Amended commits (the pre-amend version)
|
|
249
|
+
- Rebased commits (the pre-rebase versions)
|
|
250
|
+
- Stash drops (via `git fsck --unreachable` if reflog also expired)
|
|
251
|
+
|
|
252
|
+
**What reflog cannot recover:**
|
|
253
|
+
- Uncommitted changes (never tracked by git)
|
|
254
|
+
- Changes after `git checkout -- file` (working tree overwrite)
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Ambiguity Policy
|
|
259
|
+
|
|
260
|
+
These defaults apply when the user does not specify a preference. State the assumption when making a choice:
|
|
261
|
+
|
|
262
|
+
- **Search scope:** Default to the current branch. Add `--all` only when the user says "in any branch" or "across all branches".
|
|
263
|
+
- **Blame flags:** Default to `git blame -w -M -C` to skip whitespace and detect moves/copies. Drop flags only if the user wants raw blame.
|
|
264
|
+
- **Log format:** Default to `--oneline` for browsing, `-p` (patch) when the user needs to see the actual changes.
|
|
265
|
+
- **Bisect automation:** Default to manual bisect unless the user provides a test command or the project has a clear test suite.
|
|
266
|
+
- **Recovery strategy:** After finding a lost commit via reflog, default to creating a new branch rather than force-resetting an existing branch.
|
|
267
|
+
- **File scope:** When investigating a specific function, use `-L` (line range) or `-S` (function name) rather than blaming the entire file.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Reference Files
|
|
272
|
+
|
|
273
|
+
| File | Contents |
|
|
274
|
+
|------|----------|
|
|
275
|
+
| `references/advanced-commands.md` | Full command reference for git log, blame, bisect, reflog, show, and diff with all flags and options |
|
|
276
|
+
| `references/investigation-playbooks.md` | Step-by-step playbooks for common investigation scenarios: finding when a bug was introduced, tracing deleted code, recovering lost work, identifying hot spots |
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# Git Forensics: Advanced Command Reference
|
|
2
|
+
|
|
3
|
+
Full command reference for git history investigation tools with all commonly used flags.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [git log](#git-log)
|
|
8
|
+
- [git blame](#git-blame)
|
|
9
|
+
- [git bisect](#git-bisect)
|
|
10
|
+
- [git reflog](#git-reflog)
|
|
11
|
+
- [git show](#git-show)
|
|
12
|
+
- [git diff](#git-diff)
|
|
13
|
+
- [git shortlog](#git-shortlog)
|
|
14
|
+
- [Hot Spot Analysis](#hot-spot-analysis)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## git log
|
|
19
|
+
|
|
20
|
+
The primary tool for browsing commit history.
|
|
21
|
+
|
|
22
|
+
### Output Formatting
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# One line per commit
|
|
26
|
+
git log --oneline
|
|
27
|
+
|
|
28
|
+
# Graph with branch topology
|
|
29
|
+
git log --oneline --graph --all
|
|
30
|
+
|
|
31
|
+
# Custom format
|
|
32
|
+
git log --pretty=format:"%h %an %ar %s"
|
|
33
|
+
# %h = short hash, %an = author name, %ar = relative date, %s = subject
|
|
34
|
+
|
|
35
|
+
# Full patch (diff) for each commit
|
|
36
|
+
git log -p
|
|
37
|
+
|
|
38
|
+
# Stats (files changed, insertions, deletions)
|
|
39
|
+
git log --stat
|
|
40
|
+
|
|
41
|
+
# Name only (just file paths)
|
|
42
|
+
git log --name-only
|
|
43
|
+
|
|
44
|
+
# Name + status (added/modified/deleted)
|
|
45
|
+
git log --name-status
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Filtering
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# By author
|
|
52
|
+
git log --author="Alice"
|
|
53
|
+
git log --author="alice@example.com"
|
|
54
|
+
|
|
55
|
+
# By date range
|
|
56
|
+
git log --after="2024-01-01" --before="2024-06-30"
|
|
57
|
+
git log --since="3 months ago"
|
|
58
|
+
|
|
59
|
+
# By commit message
|
|
60
|
+
git log --grep="fix.*login" --regexp-ignore-case
|
|
61
|
+
|
|
62
|
+
# By file path
|
|
63
|
+
git log -- path/to/file.py
|
|
64
|
+
git log -- "*.py" # all Python files
|
|
65
|
+
|
|
66
|
+
# By number of commits
|
|
67
|
+
git log -10 # last 10 commits
|
|
68
|
+
|
|
69
|
+
# Exclude merges
|
|
70
|
+
git log --no-merges
|
|
71
|
+
|
|
72
|
+
# Only merges
|
|
73
|
+
git log --merges
|
|
74
|
+
|
|
75
|
+
# Commits on branch but not on main
|
|
76
|
+
git log main..feature-branch
|
|
77
|
+
|
|
78
|
+
# Commits on either branch but not both
|
|
79
|
+
git log main...feature-branch
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Content Search
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Pickaxe: commits that changed the count of a string
|
|
86
|
+
git log -S "function_name"
|
|
87
|
+
git log -S "function_name" -p # with patch
|
|
88
|
+
git log -S "function_name" -- "*.py" # restricted to Python files
|
|
89
|
+
|
|
90
|
+
# Regex search: commits where changed lines match a pattern
|
|
91
|
+
git log -G "def\s+calculate_\w+"
|
|
92
|
+
git log -G "TODO|FIXME" --oneline
|
|
93
|
+
|
|
94
|
+
# Difference between -S and -G:
|
|
95
|
+
# -S "foo" → finds commits where the NUMBER of "foo" occurrences changed
|
|
96
|
+
# -G "foo" → finds commits where any CHANGED LINE matches "foo"
|
|
97
|
+
# -S is faster; -G is more flexible
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## git blame
|
|
103
|
+
|
|
104
|
+
Shows the last commit to modify each line of a file.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Basic blame
|
|
108
|
+
git blame path/to/file.py
|
|
109
|
+
|
|
110
|
+
# Blame a specific line range
|
|
111
|
+
git blame -L 42,60 path/to/file.py
|
|
112
|
+
|
|
113
|
+
# Blame a function (by name, if the language is supported)
|
|
114
|
+
git blame -L :function_name path/to/file.py
|
|
115
|
+
|
|
116
|
+
# Ignore whitespace changes
|
|
117
|
+
git blame -w path/to/file.py
|
|
118
|
+
|
|
119
|
+
# Detect lines moved within the same file
|
|
120
|
+
git blame -M path/to/file.py
|
|
121
|
+
|
|
122
|
+
# Detect lines moved or copied from other files in the same commit
|
|
123
|
+
git blame -C path/to/file.py
|
|
124
|
+
|
|
125
|
+
# Detect lines copied from any file in any commit (most thorough)
|
|
126
|
+
git blame -C -C -C path/to/file.py
|
|
127
|
+
|
|
128
|
+
# Combine all filters for best results
|
|
129
|
+
git blame -w -M -C path/to/file.py
|
|
130
|
+
|
|
131
|
+
# Blame at a specific revision (e.g., before a known refactoring)
|
|
132
|
+
git blame abc1234^ -- path/to/file.py
|
|
133
|
+
|
|
134
|
+
# Show email instead of name
|
|
135
|
+
git blame -e path/to/file.py
|
|
136
|
+
|
|
137
|
+
# Show original filename (for renamed files)
|
|
138
|
+
git blame -f path/to/file.py
|
|
139
|
+
|
|
140
|
+
# Ignore specific revisions (bulk formatting commits)
|
|
141
|
+
git blame --ignore-rev abc1234 path/to/file.py
|
|
142
|
+
git blame --ignore-revs-file .git-blame-ignore-revs path/to/file.py
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## git bisect
|
|
148
|
+
|
|
149
|
+
Binary search through commit history to find a regression.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Start a bisect session
|
|
153
|
+
git bisect start
|
|
154
|
+
|
|
155
|
+
# Mark the current commit as bad
|
|
156
|
+
git bisect bad
|
|
157
|
+
|
|
158
|
+
# Mark a known-good commit
|
|
159
|
+
git bisect good v2.0.0
|
|
160
|
+
git bisect good abc1234
|
|
161
|
+
|
|
162
|
+
# After testing each checkout:
|
|
163
|
+
git bisect good # this commit is OK
|
|
164
|
+
git bisect bad # this commit has the bug
|
|
165
|
+
|
|
166
|
+
# Skip a commit that can't be tested (e.g., won't compile)
|
|
167
|
+
git bisect skip
|
|
168
|
+
|
|
169
|
+
# Automated bisect with a test script
|
|
170
|
+
git bisect start HEAD v2.0.0
|
|
171
|
+
git bisect run pytest tests/test_specific.py -x
|
|
172
|
+
|
|
173
|
+
# Automated with a custom test
|
|
174
|
+
git bisect run bash -c 'python -c "from myapp import func; assert func(1) == 2"'
|
|
175
|
+
|
|
176
|
+
# Exit codes for bisect run:
|
|
177
|
+
# 0 = good (no bug)
|
|
178
|
+
# 1-124 = bad (has bug)
|
|
179
|
+
# 125 = skip (can't test this commit)
|
|
180
|
+
# 126+ = abort bisect
|
|
181
|
+
|
|
182
|
+
# Show the bisect log (useful for sharing investigations)
|
|
183
|
+
git bisect log
|
|
184
|
+
|
|
185
|
+
# Replay a bisect session from a log
|
|
186
|
+
git bisect replay bisect.log
|
|
187
|
+
|
|
188
|
+
# End the bisect session and return to original branch
|
|
189
|
+
git bisect reset
|
|
190
|
+
|
|
191
|
+
# Reset to a specific branch instead
|
|
192
|
+
git bisect reset feature-branch
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## git reflog
|
|
198
|
+
|
|
199
|
+
Records every change to HEAD and branch refs, including operations that don't create commits.
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# Show HEAD reflog (default)
|
|
203
|
+
git reflog
|
|
204
|
+
git reflog show HEAD
|
|
205
|
+
|
|
206
|
+
# Show reflog for a specific branch
|
|
207
|
+
git reflog show main
|
|
208
|
+
git reflog show feature-branch
|
|
209
|
+
|
|
210
|
+
# Show with dates
|
|
211
|
+
git reflog --date=iso
|
|
212
|
+
git reflog --date=relative
|
|
213
|
+
|
|
214
|
+
# Show with full commit messages
|
|
215
|
+
git reflog --format="%h %gd %gs %s"
|
|
216
|
+
|
|
217
|
+
# Filter reflog entries
|
|
218
|
+
git reflog | grep "commit:" # only commits
|
|
219
|
+
git reflog | grep "reset:" # only resets
|
|
220
|
+
git reflog | grep "rebase:" # only rebases
|
|
221
|
+
|
|
222
|
+
# Recover a lost commit
|
|
223
|
+
git reflog # find the hash
|
|
224
|
+
git cherry-pick abc1234 # apply it to current branch
|
|
225
|
+
# OR
|
|
226
|
+
git branch recovery abc1234 # create a branch at that commit
|
|
227
|
+
|
|
228
|
+
# Recover a deleted branch
|
|
229
|
+
git reflog | grep "feature-name" # find the last commit
|
|
230
|
+
git branch feature-name abc1234 # recreate the branch
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## git show
|
|
236
|
+
|
|
237
|
+
Display the contents of a commit, tag, or tree object.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Show a commit (message + diff)
|
|
241
|
+
git show abc1234
|
|
242
|
+
|
|
243
|
+
# Show just the commit message
|
|
244
|
+
git show abc1234 --quiet
|
|
245
|
+
|
|
246
|
+
# Show a file at a specific commit
|
|
247
|
+
git show abc1234:path/to/file.py
|
|
248
|
+
|
|
249
|
+
# Show stats only
|
|
250
|
+
git show abc1234 --stat
|
|
251
|
+
|
|
252
|
+
# Show a specific file's changes in a commit
|
|
253
|
+
git show abc1234 -- path/to/file.py
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## git diff
|
|
259
|
+
|
|
260
|
+
Compare commits, branches, or the working tree.
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# Unstaged changes
|
|
264
|
+
git diff
|
|
265
|
+
|
|
266
|
+
# Staged changes
|
|
267
|
+
git diff --staged
|
|
268
|
+
|
|
269
|
+
# Between two commits
|
|
270
|
+
git diff abc1234 def5678
|
|
271
|
+
|
|
272
|
+
# Between two branches
|
|
273
|
+
git diff main..feature-branch
|
|
274
|
+
|
|
275
|
+
# Only show file names
|
|
276
|
+
git diff --name-only main..feature-branch
|
|
277
|
+
|
|
278
|
+
# Show stats
|
|
279
|
+
git diff --stat main..feature-branch
|
|
280
|
+
|
|
281
|
+
# Ignore whitespace
|
|
282
|
+
git diff -w
|
|
283
|
+
|
|
284
|
+
# Word-level diff (instead of line-level)
|
|
285
|
+
git diff --word-diff
|
|
286
|
+
|
|
287
|
+
# Show only changes in specific files
|
|
288
|
+
git diff main..feature-branch -- "*.py"
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## git shortlog
|
|
294
|
+
|
|
295
|
+
Summarize commit history by author.
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
# Commit count per author (sorted descending)
|
|
299
|
+
git shortlog -sn
|
|
300
|
+
|
|
301
|
+
# Exclude merges
|
|
302
|
+
git shortlog -sn --no-merges
|
|
303
|
+
|
|
304
|
+
# Within a date range
|
|
305
|
+
git shortlog -sn --after="2024-01-01"
|
|
306
|
+
|
|
307
|
+
# For a specific path
|
|
308
|
+
git shortlog -sn -- src/
|
|
309
|
+
|
|
310
|
+
# Group by committer (not author)
|
|
311
|
+
git shortlog -snc
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Hot Spot Analysis
|
|
317
|
+
|
|
318
|
+
Find files that change most frequently (potential maintenance burdens):
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
# Most frequently changed files
|
|
322
|
+
git log --pretty=format: --name-only | sort | uniq -c | sort -rn | head -20
|
|
323
|
+
|
|
324
|
+
# Most frequently changed files by a specific author
|
|
325
|
+
git log --author="Alice" --pretty=format: --name-only | sort | uniq -c | sort -rn | head -20
|
|
326
|
+
|
|
327
|
+
# Files with the most distinct authors (shared ownership)
|
|
328
|
+
git log --pretty=format:"%an" --name-only | paste - - | sort -u | cut -f2 | sort | uniq -c | sort -rn | head -20
|
|
329
|
+
|
|
330
|
+
# Churn: lines added + removed per file
|
|
331
|
+
git log --numstat --pretty=format: | awk '{added+=$1; removed+=$2; file=$3} END {print added+removed, file}' | sort -rn | head -20
|
|
332
|
+
```
|