
Husky kör ett skript i Gits pre-commit-hook. lint-staged låter det skriptet köra lint och formatering enbart på filerna du har stageat. Fäller en kontroll avbryts committen. I standardläget återställer lint-staged filerna till läget före kontrollen; din felaktiga ändring finns alltså kvar så att du kan rätta den. Men vem som helst kan hoppa över hooken, så samma kontroller måste också köras i CI.
1. Bygg ett provrepo utanför projektet
En AI-assistent skriver gärna kod som ser rimlig ut men innehåller ett felstavat variabelnamn eller oformaterade rader. Om du committar direkt hamnar felet i historiken och upptäcks först i CI eller i produktion. En pre-commit-hook flyttar kontrollen till ögonblicket innan committen skapas. Gör först hela flödet i en tom katalog, så att du ser vad som händer innan du ändrar ditt riktiga projekt.
Provet förutsätter Git och Node.js med npm. Kör blocken i samma PowerShell-fönster. Kommandona skapar en ny katalog i din temporärmapp och installerar paketen lokalt där.
$provKatalog = Join-Path ([System.IO.Path]::GetTempPath()) ('hook-prov-' + [guid]::NewGuid())
New-Item -ItemType Directory -Path $provKatalog | Out-Null
Set-Location $provKatalog
git init -b main
git config user.name 'Hookprov'
git config user.email 'hookprov@example.invalid'
npm init -y
2. Installera Husky och kör init
Huskys kom-igång-sida anger två steg för npm: installera paketet som utvecklingsberoende och kör init. Sidan beskriver init som det rekommenderade sättet. Kommandot skapar ett pre-commit-skript i katalogen .husky och uppdaterar prepare-skriptet i package.json.
npm install --save-dev husky
npx husky init
Get-Content .husky/pre-commit
(Get-Content package.json -Raw | ConvertFrom-Json).scripts
Facit i vårt prov var raden npm test i .husky/pre-commit och värdet husky för prepare. Lägg märke till en fallgrop: npm init -y skapar ett test-skript som avslutas med fel. Committar du innan du byter hookens innehåll stoppas alltså varje commit av npm test. Det är rätt beteende, men förvirrande om du inte vet varför.
3. Lägg till lint-staged, ESLint och Prettier
lint-staged README anger tre delar: installera paketet, låt pre-commit-hooken köra lint-staged och konfigurera vilka kommandon som ska köras för vilka filmönster. Hookfilen innehåller då bara npx lint-staged. Konfigurationen kan ligga i package.json, i en .lintstagedrc-fil eller i en JavaScript-fil; här används .lintstagedrc.json.
npm install --save-dev lint-staged eslint @eslint/js prettier
$utf8 = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText("$provKatalog/.husky/pre-commit", "npx lint-staged`n", $utf8)
[System.IO.File]::WriteAllText("$provKatalog/.gitignore", "node_modules`n", $utf8)
[System.IO.File]::WriteAllText("$provKatalog/.lintstagedrc.json", '{ "*.{js,mjs}": ["eslint --fix", "prettier --write"] }', $utf8)
$eslintConfig = @'
import js from "@eslint/js";
export default [js.configs.recommended];
'@
[System.IO.File]::WriteAllText("$provKatalog/eslint.config.mjs", $eslintConfig, $utf8)
New-Item -ItemType Directory -Path src | Out-Null
[System.IO.File]::WriteAllText("$provKatalog/src/sum.js", "export function sum(a, b) {`n return a + b;`n}`n", $utf8)
git add -A
git commit -m 'Grund'
Filerna skrivs uttryckligen som UTF-8 utan BOM, så att innehållet blir exakt det du ser i blocket oavsett vilken PowerShell-version du har. ESLint-konfigurationen är provets minsta möjliga; i ditt projekt använder du den du redan har.
Arrayen i konfigurationen gör att eslint --fix körs före prettier --write för samma filer. Enligt README lägger lint-staged till filnamnen sist i kommandot och skickar absoluta sökvägar. Du skriver alltså inga filnamn själv. Facit för den första committen: lint-staged skrev en varning om att backup hoppades över eftersom repot ännu saknade en första commit, körde båda kommandona på två filer och committen skapades. Varningen gäller bara det allra första läget i ett nytt repo.
4. Låt en trasig AI-ändring försöka bli en commit
Ändringen nedan är skriven för att likna en typisk förhastad AI-ändring: funktionen räknar ut en summa, men returraden använder ett felstavat namn och formateringen är slarvig. Samtidigt skapas en ny fil, som inte stageas, och som får representera ditt eget pågående arbete.
$trasig = @'
export function sum(a, b) {
return a + b;
}
export function average(values){
const total = values.reduce((acc,v)=>acc+v,0)
return totl / values.length
}
'@
[System.IO.File]::WriteAllText("$provKatalog/src/sum.js", $trasig, $utf8)
git add src/sum.js
[System.IO.File]::WriteAllText("$provKatalog/anteckning.txt", "eget arbete`n", $utf8)
git commit -m 'Ny funktion average'
"exit=$LASTEXITCODE"
git log --oneline
git status --short
Facit: lint-staged rapporterade att originalläget säkerhetskopierades. eslint --fix misslyckades med två fel: totl är inte definierad och total tilldelas utan att användas. prettier --write hoppades över. Därefter stod det att läget återställdes på grund av felen, och Husky skrev att pre-commit-skriptet misslyckades med kod 1. Exitkoden var 1, loggen visade fortfarande bara committen Grund och status visade M framför src/sum.js samt ?? framför anteckning.txt. Ändringen ligger alltså kvar i index och anteckningen är orörd.
5. Förstå backupen och återställningen
README beskriver i sin FAQ vad som händer i standardläget. Hela originalläget sparas i en git stash med git stash create och git stash store, vilket lämnar filerna kvar i arbetskatalogen. Filer som är delvis stageade får sina ostageade delar sparade i en patchfil och undanlagda medan kommandona körs, och sedan tillbakalagda. Vid fel återställs läget med git reset och originalet hämtas ur stashen.
Stashen tas bort först i sista steget. Om processen avbryts halvvägs, till exempel om du stänger terminalen, ska ändringarna enligt README gå att hämta ur den. Kontrollera då med git stash list och leta efter en post med texten lint-staged automatic backup. I vårt prov var stashlistan tom efter det misslyckade försöket, eftersom återställningen hann slutföras. FAQ:n anger också att otrackade filer sannolikt inte ingår, eftersom det är standardbeteendet för git stash. Behandla därför inte backupen som en ersättning för din egen undanläggning; guiden om Git stash före ett AI-försök visar hur du sparar och kontrollerar eget arbete separat.
Flaggan --no-stash stänger av backupen och lämnar enligt README ändringarna i index när committen avbryts. Använd den inte i provet; standardläget är det som skyddar dig.
6. Rätta felet och se formateringen följa med
[System.IO.File]::WriteAllText("$provKatalog/src/sum.js", $trasig.Replace('totl', 'total'), $utf8)
git add src/sum.js
git commit -m 'Ny funktion average'
git show HEAD:src/sum.js
Facit: båda kommandona lyckades och committen skapades. Den committade filen hade fått mellanslag efter parametrarna, semikolon och mellanslag kring pilfunktionen, trots att du stageade den oformaterade versionen. README anger att lint-staged lägger till ändringar från kommandona i committen så länge inga fel uppstår, så du behöver inte köra git add igen. Läs diffen efteråt; ett --fix-kommando kan ändra mer än du väntar dig.
7. Hooken kan hoppas över, så CI behövs ändå
Huskys How To anger att de flesta Git-kommandon har flaggan -n eller --no-verify för att hoppa över hooks, och att miljövariabeln HUSKY=0 stänger av dem tillfälligt. Kom-igång-sidan säger uttryckligen att Husky inte tvingar på Git-hooks. Prova själv:
[System.IO.File]::WriteAllText("$provKatalog/src/bad.js", "export const x = y;`n", $utf8)
git add src/bad.js
git commit --no-verify -m 'Commit utan hook'
"exit=$LASTEXITCODE"
npx eslint .
"eslint exit=$LASTEXITCODE"
Facit: committen skapades med exitkod 0 trots att y inte finns. Det separata ESLint-anropet hittade felet och gav exitkod 1. Hooken körs dessutom bara i kloner där den är installerad, och ett verktyg som committar på egen hand kan använda samma flagga. Kör därför lint och tester även i CI, mot hela projektet och efter en ren installation; guiden om npm ci visar hur beroendena återskapas där. How To rekommenderar också HUSKY=0 på CI-servrar och i Docker, så att hooks inte installeras där.
När flödet fungerar i provet för du över de tre delarna till ditt projekt: hookfilen, konfigurationen och de nya utvecklingsberoendena i package.json. Committa .husky tillsammans med package.json, som README påpekar, så att resten av teamet får samma kontroll. Ta sedan bort provkatalogen.
Källor och genomförda prov
- Husky: Get started – installation, init, prepare-skriptet och att hooks kan stängas av.
- Husky: How To – -n/--no-verify, HUSKY=0 och CI-servrar.
- lint-staged README – installation, konfigurationsfiler, filnamn som argument, automatisk staging, --no-stash och hur backupen fungerar.
Källorna kontrollerades 16 oktober 2026. Hela kommandoflödet kördes samma dag i ett temporärt repository utanför sajten, i Windows PowerShell med de paketversioner npm installerade då. Resultaten i facit är de som visades i det provet. Ingen AI-assistent kördes; den trasiga ändringen skrevs för hand. Husky och lint-staged anger inga versionskrav på de sidor som användes, och guiden omfattar inte yarn, pnpm, monorepon eller TypeScript-konfiguration.