Gå till innehåll
·22 min läsning

Git bortom grunderna: Arbetsflöden som sparar timmar varje vecka

Interaktiv rebase, cherry-pick, bisect, worktrees, reflog-räddning och de förgreningsstrategier som faktiskt fungerar. Git-kommandon jag använder varje dag som de flesta utvecklare inte vet finns.

Dela:X / TwitterLinkedIn

De flesta utvecklare lär sig fem Git-kommandon och stannar där. add, commit, push, pull, merge. Kanske checkout och branch om de känner sig äventyrliga. Det räcker genom det första året. Sedan har din branch 47 commits med meddelanden som "fix" och "wip" och "snälla fungera", du återställer av misstag något du inte borde ha, och du spenderar 40 minuter på Stack Overflow med att försöka ångra en misslyckad merge.

Jag har använt Git i åratal. Inte sporadiskt — intensivt. Flera branchar, flera repon, flera samarbetspartners, hela dagen, varje dag. Det som följer är kommandona och arbetsflödena jag faktiskt använder. Inte de som ser bra ut i en tutorial. De som sparar mig verklig tid, varje enskild vecka.

Interaktiv Rebase: Städa upp ditt stök innan någon ser det#

Din branch har tolv commits. Hälften av dem är "fix typo." En säger "ångra föregående commit." En annan säger "fixa det faktiskt den här gången." Du ska öppna en PR. Ingen behöver se den historiken.

Interaktiv rebase är hur du skriver om historiken på din branch innan du delar den. Det låter dig squasha commits tillsammans, omformulera meddelanden, ändra ordning på dem eller ta bort dem helt.

Grundkommandot#

bash
git rebase -i HEAD~5

Detta öppnar en editor som visar dina senaste 5 commits, äldst först:

bash
pick a1b2c3d Add user authentication endpoint
pick d4e5f6g Fix typo in auth middleware
pick h7i8j9k Add rate limiting
pick l0m1n2o Fix rate limit bug
pick p3q4r5s Update auth tests

Varje rad börjar med ett kommando. Ändra pick till något av dessa:

  • squash (eller s) — Slå samman denna commit med den ovanför, kombinera meddelandena
  • fixup (eller f) — Samma som squash, men kasta denna commits meddelande
  • reword (eller r) — Behåll committen men ändra dess meddelande
  • drop (eller d) — Radera denna commit helt
  • edit (eller e) — Pausa rebasen vid denna commit så du kan ändra den

En riktig städsession#

Här är vad jag faktiskt gör. Den stökiga historiken ovan blir:

bash
pick a1b2c3d Add user authentication endpoint
fixup d4e5f6g Fix typo in auth middleware
pick h7i8j9k Add rate limiting
fixup l0m1n2o Fix rate limit bug
pick p3q4r5s Update auth tests

Spara och stäng. Nu har du tre rena commits istället för fem. Typo-fixen viks in i auth-committen. Rate limit-bugfixen viks in i rate limit-committen. Din PR-granskare ser en ren, logisk progression.

Ändra ordning på commits#

Du kan bokstavligen flytta raderna. Om test-committen borde komma före rate limiting-committen, flytta bara raden:

bash
pick a1b2c3d Add user authentication endpoint
pick p3q4r5s Update auth tests
pick h7i8j9k Add rate limiting

Git spelar upp dina commits i denna nya ordning. Om det finns konflikter pausar den och låter dig lösa dem.

Autosquash-genvägen#

Om du vet att en commit är en fix för en tidigare, markera den vid commit-tillfället:

bash
git commit --fixup=a1b2c3d

Detta skapar en commit med meddelandet fixup! Add user authentication endpoint. Sedan när du rebasar:

bash
git rebase -i --autosquash HEAD~5

Git ordnar automatiskt om fixup-commits precis under sina mål och markerar dem som fixup. Du sparar och stänger bara. Ingen manuell redigering.

Jag använder detta konstant. Det är det snabbaste sättet att iterera på en branch samtidigt som den slutliga historiken hålls ren.

Den gyllene regeln#

Rebasa aldrig commits som har pushats till en delad branch. Om andra har baserat arbete på dessa commits kommer historikomskrivningen att orsaka verkliga problem. Rebasa dina egna feature branches innan merge. Rebasa aldrig main.

Om du redan har pushat din feature branch och behöver rebasa:

bash
git push --force-with-lease

Flaggan --force-with-lease är säkrare än --force. Den vägrar pusha om någon annan har pushat till samma branch sedan din senaste fetch. Det förhindrar inte alla problem, men det fångar det vanligaste.

Cherry-Pick: Kirurgiska commit-överföringar#

Cherry-pick tar en specifik commit från en branch och tillämpar den på en annan. Inte en merge. Inte en rebase. Bara en commit, rent tillämpad.

När jag faktiskt använder detta#

Det vanligaste scenariot: jag fixade en bugg på min feature branch, men fixen behöver också gå till main eller en release-branch just nu. Jag vill inte merga hela min feature branch. Jag vill bara den ena fixen.

bash
# Hitta commit-hashen för fixen
git log --oneline feature/user-auth
# a1b2c3d Fix null pointer in session validation
 
# Byt till main och cherry-picka den
git checkout main
git cherry-pick a1b2c3d

Klart. Fixen finns på main som en ny commit med samma ändringar.

Cherry-Pick utan att committa#

Ibland vill du tillämpa ändringarna men inte committa dem ännu. Kanske vill du kombinera flera cherry-picks till en commit, eller modifiera ändringarna något:

bash
git cherry-pick --no-commit a1b2c3d

Ändringarna är stageade men inte committade. Du kan modifiera dem, lägga till fler ändringar och sedan committa när du är redo.

Cherry-Pick av ett intervall#

Behöver flera på varandra följande commits? Använd intervallsyntax:

bash
git cherry-pick a1b2c3d..f6g7h8i

Detta cherry-pickar allt efter a1b2c3d fram till och inklusive f6g7h8i. Observera att a1b2c3d i sig exkluderas. Om du vill inkludera den:

bash
git cherry-pick a1b2c3d^..f6g7h8i

Hantering av konflikter#

Cherry-pick-konflikter fungerar som merge-konflikter. När en uppstår:

bash
# Git berättar att det finns en konflikt
# Fixa de konfliktande filerna, sedan:
git add .
git cherry-pick --continue

Eller om du ändrar dig:

bash
git cherry-pick --abort

En sak att tänka på: cherry-pickade commits skapar nya commit-hashar. Om du senare mergar den ursprungliga branchen är Git vanligtvis smart nog att hantera dupliceringen. Men om du cherry-pickar aggressivt mellan branchar som så småningom ska mergas kan du se oväntade konflikter. Använd det kirurgiskt, inte som en merge-strategi.

Git Bisect: Binärsökning efter buggar#

Något gick sönder. Du vet att det fungerade för två veckor sedan. Det har gjorts 200 commits sedan dess. Vilken av dem förstörde det?

Du skulle kunna kontrollera varje commit manuellt. Eller så kan du använda git bisect, som använder binärsökning för att hitta den exakta brytande committen på log2(n) steg. För 200 commits är det ungefär 7-8 kontroller istället för 200.

Den manuella metoden#

bash
# Börja bisekta
git bisect start
 
# Markera den aktuella committen som dålig (buggen finns här)
git bisect bad
 
# Markera en känd bra commit (buggen fanns inte här)
git bisect good v2.1.0

Git checkar ut en commit halvvägs mellan bra och dålig. Testa den. Sedan:

bash
# Om buggen finns vid denna commit:
git bisect bad
 
# Om buggen inte finns vid denna commit:
git bisect good

Git halverar intervallet varje gång. Efter 7-8 steg berättar den:

bash
a1b2c3d4e5f6g7h is the first bad commit
commit a1b2c3d4e5f6g7h
Author: Some Developer <dev@example.com>
Date: Tue Feb 18 14:23:01 2026 +0300
 
    Refactor session handling to use async middleware

Nu vet du exakt vilken commit som introducerade buggen. När du är klar:

bash
git bisect reset

Detta tar dig tillbaka till där du började.

Den automatiserade metoden (Det här är den riktiga kraften)#

Om du har ett test som kan upptäcka buggen kan du automatisera hela processen:

bash
git bisect start
git bisect bad HEAD
git bisect good v2.1.0
git bisect run npm test -- --grep "session validation"

Git checkar automatiskt ut commits, kör testet och markerar dem som bra eller dåliga baserat på exitkoden. Noll betyder bra, icke-noll betyder dåligt. Gå iväg, kom tillbaka, och den berättar den exakta committen.

Du kan använda vilket skript som helst:

bash
git bisect run ./test-regression.sh

Där test-regression.sh är:

bash
#!/bin/bash
npm run build 2>/dev/null || exit 125  # 125 betyder "hoppa över denna commit"
npm test -- --grep "session" || exit 1  # 1 betyder "dålig"
exit 0                                   # 0 betyder "bra"

Exitkod 125 är speciell — den berättar för bisect att hoppa över den committen (användbart om en commit inte kompilerar). Det här är en av de funktionerna som verkar nischad tills du behöver den, och då sparar den dig en hel eftermiddag.

En riktig bisect-session#

Så här ser det ut i praktiken:

bash
$ git bisect start
$ git bisect bad HEAD
$ git bisect good abc1234
Bisecting: 97 revisions left to test after this (roughly 7 steps)
[def5678...] Commit message here
 
$ npm test -- --grep "login flow"
# Tester misslyckas
 
$ git bisect bad
Bisecting: 48 revisions left to test after this (roughly 6 steps)
[ghi9012...] Another commit message
 
$ npm test -- --grep "login flow"
# Tester passerar
 
$ git bisect good
Bisecting: 24 revisions left to test after this (roughly 5 steps)
...
 
# Efter ~7 iterationer:
abc1234def5678ghi is the first bad commit

Sju steg för att hitta en nål i en höstack av 200 commits.

Git Worktrees: Flera branchar, noll stashning#

Det här är den mest underanvända Git-funktionen. Jag är övertygad om att de flesta utvecklare inte vet att den finns.

Problemet: du är djupt inne i en feature branch. Filer är ändrade överallt. Sedan säger någon "kan du kolla på den här produktionsbuggen snabbt?" Du har tre alternativ:

  1. Stasha allt, byt branch, fixa, byt tillbaka, poppa stash. Hoppas att inget går fel.
  2. Committa ditt halvfärdiga arbete med ett "wip"-meddelande. Fult men funktionellt.
  3. Klona repot igen i en annan katalog.

Eller alternativ 4: worktrees.

Vad en Worktree är#

En worktree är en andra (eller tredje, eller fjärde) arbetskatalog kopplad till samma repository. Varje worktree har sin egen utcheckade branch, sina egna arbetsfiler, sitt eget index. Men de delar samma .git-data, så du duplicerar inte hela repot.

Lägga till en Worktree#

bash
# Du är på feature/user-auth, djupt i arbetet
# Behöver fixa en bugg på main:
 
git worktree add ../hotfix-session main

Detta skapar en ny katalog ../hotfix-session med main utcheckad. Din nuvarande katalog förblir exakt som den var. Inget stashat, inget committat, inget stört.

bash
cd ../hotfix-session
# Fixa buggen
git add .
git commit -m "Fix null pointer in session validation"
git push origin main
cd ../my-project
# Fortsätt arbeta på din feature som om inget hänt

Skapa en ny branch i en Worktree#

bash
git worktree add ../hotfix-nav -b hotfix/nav-crash main

Detta skapar worktreen OCH skapar en ny branch hotfix/nav-crash baserad på main.

Hantera Worktrees#

bash
# Lista alla worktrees
git worktree list
# /home/dev/my-project         abc1234 [feature/user-auth]
# /home/dev/hotfix-session     def5678 [main]
 
# Ta bort en worktree när du är klar
git worktree remove ../hotfix-session
 
# Om katalogen redan var raderad:
git worktree prune

Varför det här är bättre än stashning#

Stashning fungerar för snabba kontextbyten. Men worktrees är bättre för allt som tar mer än fem minuter:

  • Din IDE förblir öppen på din feature branch. Ingen omindexering, ingen förlorad scrollposition.
  • Du kan köra tester i båda katalogerna samtidigt.
  • Ingen risk för stash-konflikter eller att glömma vad du stashat.
  • Du kan ha en långvarig dev-server i en worktree och en ren build i en annan.

Jag har vanligtvis två eller tre worktrees aktiva: min huvudsakliga feature branch, en main-worktree för snabba kontroller och ibland en gransknings-worktree där jag checkar ut någon annans PR.

Den enda haken#

Du kan inte ha samma branch utcheckad i två worktrees. Det är medvetet — det förhindrar dig från att göra motstridiga ändringar på samma branch på två ställen. Om du försöker vägrar Git.

Reflog: Ångra-knappen för allt#

Du gjorde en hard reset och förlorade commits. Du raderade en branch. Du rebasade och något gick fruktansvärt fel. Du tror att ditt arbete är borta.

Det är det inte. Git raderar nästan aldrig något på riktigt. Reflogen är ditt skyddsnät.

Vad reflogen är#

Varje gång HEAD flyttas — varje commit, checkout, rebase, reset, merge — registrerar Git det i reflogen. Det är en logg över överallt HEAD har varit, i ordning.

bash
git reflog

Utdata:

bash
a1b2c3d (HEAD -> main) HEAD@{0}: reset: moving to HEAD~3
f4e5d6c HEAD@{1}: commit: Add payment processing
b7a8c9d HEAD@{2}: commit: Update user dashboard
e0f1g2h HEAD@{3}: commit: Fix auth token refresh
i3j4k5l HEAD@{4}: checkout: moving from feature/payments to main

Varje post har ett index (HEAD@{0}, HEAD@{1} osv.) och en beskrivning av vad som hände.

Återhämtning efter en hard reset#

Du körde av misstag git reset --hard HEAD~3 och förlorade tre commits. De finns precis där i reflogen:

bash
# Se vad du förlorade
git reflog
 
# Committen före reseten är HEAD@{1}
git reset --hard f4e5d6c

Alla tre commits är tillbaka. Kris avvärjd.

Återhämtning av en raderad branch#

Du raderade en branch som hade omerget arbete:

bash
git branch -D feature/experimental
# Nej, den hade två veckors arbete

Commitsen finns fortfarande. Hitta dem:

bash
git reflog | grep "feature/experimental"
# Eller titta bara igenom reflogen efter den sista committen på den branchen
 
# Hittade den. Återskapa branchen vid den committen:
git branch feature/experimental a1b2c3d

Branchen är tillbaka, med alla sina commits.

Återhämtning efter en dålig rebase#

Du rebasade och allt gick fel. Konflikter överallt, fel commits, kaos:

bash
# Reflogen visar var du var före rebasen
git reflog
# a1b2c3d HEAD@{0}: rebase (finish): ...
# ...
# f4e5d6c HEAD@{5}: rebase (start): checkout main
# b7a8c9d HEAD@{6}: commit: Your last good commit
 
# Gå tillbaka till före rebasen
git reset --hard b7a8c9d

Du är tillbaka till exakt där du var innan rebasen startade. Som om den aldrig hände.

30-dagarsskyddsnätet#

Som standard behåller Git reflog-poster i 30 dagar (90 dagar för nåbara commits). Efter det kan de skräpsamlas. Så du har en månad på dig att inse att du gjort ett misstag. I praktiken är det mer än tillräckligt.

Du kan kontrollera utgångstiden:

bash
git config gc.reflogExpire
# default: 90.days.ago (för nåbara)
git config gc.reflogExpireUnreachable
# default: 30.days.ago (för onåbara)

Om du är paranoid, öka den:

bash
git config --global gc.reflogExpireUnreachable "180.days.ago"

En personlig regel#

Före varje destruktiv operation — hard reset, force push, branch-radering — kör jag git log --oneline -10 först. Jag noterar mentalt den aktuella HEAD. Det tar två sekunder och har räddat mig mer än en gång från en panik jag inte behövde ha.

Stasha ordentligt: Det är inte bara git stash#

De flesta använder stash så här:

bash
git stash
# gör något
git stash pop

Det fungerar, men det motsvarar att kasta allt i en låda märkt "saker." När du har tre stashar har du ingen aning om vilken som är vilken.

Namnge dina stashar#

bash
git stash push -m "WIP: user auth form validation"

Nu när du listar stashar:

bash
git stash list
# stash@{0}: On feature/auth: WIP: user auth form validation
# stash@{1}: On main: Quick fix attempt for nav bug
# stash@{2}: On feature/payments: Experiment with Stripe webhooks

Du kan se exakt vad varje stash innehåller.

Inkludera ospårade filer#

Som standard stashar git stash bara spårade filer. Nya filer du inte har lagt till lämnas kvar:

bash
# Stasha allt, inklusive nya filer
git stash push --include-untracked -m "WIP: new auth components"
 
# Eller inkludera till och med ignorerade filer (sällan behövt)
git stash push --all -m "Full workspace snapshot"

Jag använder --include-untracked nästan varje gång. Att lämna nya filer kvar när du byter branch orsakar förvirring.

Partiell stashning#

Det här är den de flesta inte känner till. Du kan stasha specifika filer:

bash
# Stasha bara specifika filer
git stash push -m "Just the auth changes" src/auth/ src/middleware.ts

Eller använd patch-läge för att stasha specifika hunkar inom filer:

bash
git stash push --patch -m "Partial: only the validation logic"

Git går igenom varje ändring interaktivt och frågar om du vill stasha den. y för ja, n för nej, s för att dela hunken i mindre delar.

Apply kontra Pop#

bash
# Pop: tillämpa och ta bort från stash-listan
git stash pop stash@{2}
 
# Apply: tillämpa men behåll i stash-listan
git stash apply stash@{2}

Jag använder apply när jag inte är säker på om stashen kommer att tillämpas rent. Om det finns en konflikt bevaras stashen. Med pop, om det finns en konflikt, stannar stashen kvar i listan ändå (många vet inte detta), men jag föredrar den explicita avsikten med apply.

Visa stash-innehåll#

bash
# Se vilka filer som ändrades i en stash
git stash show stash@{0}
 
# Se den fullständiga diffen
git stash show -p stash@{0}

Skapa en branch från en stash#

Om din stash har vuxit till något mer substantiellt:

bash
git stash branch feature/auth-validation stash@{0}

Detta skapar en ny branch från committen där du ursprungligen stashade, tillämpar stashen och tar bort den. Rent.

Förgreningsstrategier: Vilken fungerar egentligen#

Det finns tre mainstream förgreningsstrategier. Var och en har ett sammanhang där den lyser och sammanhang där den orsakar smärta.

Gitflow#

Klassikern. main, develop, feature/*, release/*, hotfix/*. Skapad av Vincent Driessen 2010.

bash
# Feature branch
git checkout -b feature/user-auth develop
# ... arbeta ...
git checkout develop
git merge --no-ff feature/user-auth
 
# Release branch
git checkout -b release/2.1.0 develop
# ... slutgiltiga fixar ...
git checkout main
git merge --no-ff release/2.1.0
git tag -a v2.1.0 -m "Release 2.1.0"
git checkout develop
git merge --no-ff release/2.1.0
 
# Hotfix
git checkout -b hotfix/session-fix main
# ... fixa ...
git checkout main
git merge --no-ff hotfix/session-fix
git checkout develop
git merge --no-ff hotfix/session-fix

När det fungerar: Mobilappar, desktopprogram, allt med namngivna versionerade releaser och flera versioner som stöds samtidigt. Om du levererar v2.1 och v3.0 och behöver patcha båda hanterar Gitflow det.

När det inte fungerar: Webbapplikationer med kontinuerlig driftsättning. Om du driftsätter till produktion 5 gånger om dagen är ceremonin med release-branchar och develop-branchar ren overhead. De flesta webbteam som antar Gitflow slutar med en develop-branch som är perpetuellt trasig och release-branchar som ingen förstår.

GitHub Flow#

Enkelt. Du har main. Du skapar feature branches. Du öppnar PR:er. Du mergar till main. Du driftsätter main.

bash
git checkout -b feature/user-auth main
# ... arbeta ...
git push origin feature/user-auth
# Öppna PR, bli granskad, merga
# main är alltid driftsättbar

När det fungerar: Små till medelstora team som levererar webbappar. Kontinuerlig driftsättning. Om main alltid driftsätts är det allt du behöver. Det är vad den här sajten använder.

När det inte fungerar: När du behöver underhålla flera releaseversioner, eller när du har en lång QA-cykel före driftsättning. GitHub Flow förutsätter att main går till produktion snabbt.

Trunk-baserad utveckling#

Alla committar till main ("stammen") direkt eller via mycket kortlivade branchar (mindre än en dag). Inga långvariga feature branches.

bash
# Kortlivad branch (mergad samma dag)
git checkout -b fix/auth-token main
# ... liten, fokuserad ändring ...
git push origin fix/auth-token
# PR granskad och mergad inom timmar, inte dagar

När det fungerar: Högpresterande team med bra CI/CD, omfattande testsviter och funktionsflaggor. Google, Meta och de flesta stora teknikföretag använder trunk-baserad utveckling. Det tvingar fram små, inkrementella ändringar och eliminerar merge-helvetet.

När det inte fungerar: Team utan bra testtäckning eller CI. Om merge till stammen innebär att driftsätta otestad kod kommer du att krascha produktionen konstant. Du behöver också funktionsflaggor för allt som tar mer än en dag att bygga:

bash
# Funktionsflagga i koden
if (featureFlags.isEnabled('new-checkout-flow')) {
  renderNewCheckout();
} else {
  renderLegacyCheckout();
}

Min rekommendation#

För de flesta webbutvecklingsteam: börja med GitHub Flow. Det är enkelt, det fungerar, och det kräver ingen verktygsanpassning utöver vad GitHub/GitLab redan erbjuder.

Om ditt team växer förbi 15-20 ingenjörer och ni driftsätter flera gånger om dagen, titta på trunk-baserad utveckling med funktionsflaggor. Investeringen i funktionsflagginfrastruktur betalar sig själv i minskade merge-konflikter och snabbare iteration.

Om du levererar versionerad programvara (mobilappar, CLI-verktyg, bibliotek): Gitflow eller en förenklad version av det. Du behöver faktiskt de där release-brancharna.

Välj inte en strategi för att ett blogginlägg sa att det är den bästa. Välj den som matchar hur ni faktiskt levererar.

Git Hooks: Automatisera det du ständigt glömmer#

Git hooks är skript som körs automatiskt vid specifika punkter i Git-arbetsflödet. De är lokala för din maskin (inte pushade till remote), vilket innebär att du behöver ett sätt att dela dem med ditt team.

De hooks som faktiskt spelar roll#

pre-commit — Körs före varje commit. Använd det för lintning och formatering:

bash
#!/bin/bash
# .git/hooks/pre-commit
 
# Kör ESLint på bara stageade filer
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|tsx)$')
 
if [ -n "$STAGED_FILES" ]; then
  echo "Running ESLint on staged files..."
  npx eslint $STAGED_FILES --quiet
  if [ $? -ne 0 ]; then
    echo "ESLint failed. Fix errors before committing."
    exit 1
  fi
fi
 
# Kör Prettier på stageade filer
if [ -n "$STAGED_FILES" ]; then
  echo "Running Prettier..."
  npx prettier --check $STAGED_FILES
  if [ $? -ne 0 ]; then
    echo "Prettier check failed. Run 'npx prettier --write' first."
    exit 1
  fi
fi

commit-msg — Validerar commit-meddelandets format. Perfekt för att genomdriva konventionella commits:

bash
#!/bin/bash
# .git/hooks/commit-msg
 
COMMIT_MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,72}"
 
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
  echo "Invalid commit message format."
  echo "Expected: type(scope): description"
  echo "Example: feat(auth): add session refresh endpoint"
  echo ""
  echo "Valid types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert"
  exit 1
fi

pre-push — Körs före push. Använd det för tester:

bash
#!/bin/bash
# .git/hooks/pre-push
 
echo "Running tests before push..."
npm test
if [ $? -ne 0 ]; then
  echo "Tests failed. Push aborted."
  exit 1
fi

Husky kontra nativa hooks#

Nativa hooks lever i .git/hooks/. Problemet: .git-katalogen spåras inte av Git, så du kan inte dela hooks genom repot. Alla måste ställa in dem manuellt.

Husky löser detta. Det lagrar hook-konfigurationer i repot och ställer in .git/hooks automatiskt vid npm install:

bash
npx husky init

Detta skapar en .husky/-katalog. Lägg till hooks som filer:

bash
# .husky/pre-commit
npx lint-staged

Kombinerat med lint-staged får du snabba, riktade pre-commit-kontroller:

json
{
  "lint-staged": {
    "*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.css": ["prettier --write"],
    "*.json": ["prettier --write"]
  }
}

Detta kör ESLint och Prettier bara på filerna du faktiskt committar. Inte hela kodbasen. Snabbt.

När man hoppar över hooks#

Ibland behöver du committa utan att hooks körs. Akuta hotfixar, work-in-progress commits på din egen branch:

bash
git commit --no-verify -m "WIP: debugging production issue"

Använd detta sparsamt. Om du märker att du hoppar över hooks regelbundet är dina hooks förmodligen för långsamma eller för strikta.

Alias som sparar tid#

Min .gitconfig har utvecklats under år. Dessa är de alias som överlevt — de jag faktiskt använder dagligen, inte de jag lade till för att de såg smarta ut.

Snygg logg#

Standard git log är pratig. Det här ger dig en ren, färgglad, grafbaserad vy:

bash
git config --global alias.lg "log --oneline --graph --all --decorate"

Användning:

bash
git lg
# * a1b2c3d (HEAD -> main) Fix session validation
# | * d4e5f6g (feature/payments) Add Stripe integration
# | * h7i8j9k Update payment models
# |/
# * l0m1n2o Merge PR #42
# * p3q4r5s Add user dashboard

Jag kör detta 20 gånger om dagen. Det är det snabbaste sättet att förstå tillståndet för ditt repository.

Ångra senaste commit#

Behåll ändringarna, ångra bara committen:

bash
git config --global alias.undo "reset HEAD~1 --mixed"

Användning:

bash
git undo
# Committen är borta, men alla ändringar finns fortfarande i din arbetskatalog

Jag använder detta när jag committar för tidigt, glömmer en fil eller vill omstrukturera ändringarna.

Ta bort allt från staging#

bash
git config --global alias.unstage "reset HEAD --"

Användning:

bash
git unstage src/auth/session.ts
# Filen är borttagen från staging men ändringarna bevaras

Lista alla alias#

Eftersom du kommer att glömma vad du ställde in:

bash
git config --global alias.aliases "config --get-regexp ^alias\\."

Fler alias jag använder#

bash
# Visa vad du ska committa
git config --global alias.staged "diff --staged"
 
# Kort status
git config --global alias.st "status -sb"
 
# Ändra utan att byta meddelande
git config --global alias.amend "commit --amend --no-edit"
 
# Visa den senaste committen
git config --global alias.last "log -1 HEAD --stat"
 
# Pull med rebase istället för merge
git config --global alias.up "pull --rebase --autostash"
 
# Radera branchar som har mergats till main
git config --global alias.cleanup "!git branch --merged main | grep -v '^[ *]*main$' | xargs git branch -d"

Aliaset up är särskilt bra. pull --rebase håller din historik linjär istället för att skapa merge-commits för varje pull. --autostash stashar och återställer automatiskt dina ändringar om du har smutsiga filer. Det är vad pull borde ha varit som standard.

Aliaset cleanup raderar lokala branchar som har mergats till main. Efter ett tag samlar du på dig dussintals inaktuella branchar. Kör detta varje vecka.

Kommandon jag använder dagligen#

Dessa är inte alias eller avancerade funktioner. De är bara kommandon jag kör konstant som många utvecklare inte verkar känna till.

Det ultimata loggkommandot#

bash
git log --oneline --graph --all

Detta visar varje branch, varje merge, hela topologin för ditt repo i en kompakt vy. Det är det första jag kör när jag pullar ändringar. Det svarar på "vad händer i detta repo just nu?"

Diff av stageade ändringar#

bash
git diff --staged

Detta visar vad som ska committas. Inte vad som ändrats i din arbetskatalog — vad som faktiskt är stageat. Jag kör alltid detta innan jag committar. Alltid. Det fångar oavsiktliga inkluderingar, debug-satser, console.logs som inte borde vara där.

bash
# Se ostageade ändringar
git diff
 
# Se stageade ändringar
git diff --staged
 
# Se båda
git diff HEAD

Visa en specifik commit#

bash
git show a1b2c3d

Visar den fullständiga diffen av en enstaka commit. Användbart vid granskning av historik, för att förstå vad en commit faktiskt ändrade.

bash
# Visa bara filerna som ändrades
git show --stat a1b2c3d
 
# Visa en specifik fil vid en specifik commit
git show a1b2c3d:src/auth/session.ts

Det sista är otroligt användbart. Du kan visa vilken fil som helst vid vilken punkt i historiken som helst utan att checka ut den committen.

Blame med radintervall#

bash
git blame -L 42,60 src/auth/session.ts

Visar vem som senast ändrade rad 42-60. Mer användbart än att blame:a hela filen, som vanligtvis är överväldigande.

bash
# Visa commit-meddelandet också, inte bara hashen
git blame -L 42,60 --show-name src/auth/session.ts
 
# Ignorera whitespace-ändringar (mycket användbart)
git blame -w -L 42,60 src/auth/session.ts
 
# Visa committen före den blame:ade (gräv djupare)
git log --follow -p -- src/auth/session.ts

Flaggan -w är viktig. Utan den kommer blame att tillskriva rader till den som senast omformaterade filen, vilket sällan är personen du letar efter.

Hitta en sträng genom hela historiken#

bash
# Hitta när en funktion lades till eller togs bort
git log -S "validateSession" --oneline
 
# Hitta när ett regex-mönster dök upp
git log -G "session.*timeout" --oneline

-S ("pickaxe:n") hittar commits där antalet förekomster av en sträng ändrades. -G hittar commits där diffen matchar ett regex. Båda är kraftfulla för arkeologi — att ta reda på när något introducerades eller togs bort.

Visa vad som ändrades mellan två punkter#

bash
# Vad ändrades mellan två branchar
git diff main..feature/auth
 
# Vad ändrades på denna branch sedan den avvek från main
git diff main...feature/auth
 
# Lista bara de ändrade filerna
git diff main...feature/auth --name-only
 
# Statistikvy (filer + tillägg/borttagningar)
git diff main...feature/auth --stat

Två punkter kontra tre punkter spelar roll. Två punkter visar skillnaden mellan spetsarna av båda brancharna. Tre punkter visar vad som ändrades på höger sida sedan den avvek från vänster sida. Tre punkter är vanligtvis vad du vill ha när du granskar en feature branch.

Städa ospårade filer#

bash
# Se vad som skulle raderas (torrkörning)
git clean -n
 
# Radera ospårade filer
git clean -f
 
# Radera ospårade filer och kataloger
git clean -fd
 
# Radera ospårade och ignorerade filer (kärnvapenalternativet)
git clean -fdx

Kör alltid med -n först. git clean -fdx raderar dina node_modules, .env, byggartefakter — allt som inte spåras av Git. Användbart för en verkligt ny start, men destruktivt.

Återställ en enskild fil från en annan branch#

bash
# Hämta main-branchens version av en fil utan att byta branch
git restore --source main -- src/config/database.ts

Eller från en specifik commit:

bash
git restore --source a1b2c3d -- src/config/database.ts

Det här är renare än den gamla git checkout main -- path/to/file-syntaxen, och det påverkar inte HEAD.

Att sätta ihop det: Ett riktigt arbetsflöde#

Så här ser en typisk dag ut med dessa verktyg:

bash
# Morgon: kolla vad som händer
git lg
git fetch --all
 
# Börja en feature
git checkout -b feature/session-refresh main
 
# Arbeta, committa inkrementellt
git add -p                        # Stagea specifika hunkar, inte hela filer
git commit -m "Add token refresh endpoint"
git commit -m "Add refresh token rotation"
git commit -m "Fix: handle expired refresh tokens"
git commit -m "Add integration tests"
 
# Avbruten: behöver fixa en produktionsbugg
git worktree add ../hotfix main
cd ../hotfix
# ... fixa, committa, pusha, PR mergad ...
cd ../my-project
git worktree remove ../hotfix
 
# Tillbaka till feature-arbete
git commit -m "Fix edge case in token validation"
 
# Redo för PR: städa historiken
git rebase -i main
# Squasha fix-commits, omformulera för tydlighet
 
# Pusha och öppna PR
git push -u origin feature/session-refresh
 
# Något gick sönder i staging? Ta reda på vilken commit:
git bisect start
git bisect bad HEAD
git bisect good main
git bisect run npm test
 
# Hoppsan, jag hard-resetade fel sak
git reflog
git reset --hard HEAD@{2}

Vart och ett av dessa kommandon tar sekunder. Tillsammans sparar de timmar. Inte hypotetiska timmar — verkliga timmar, varje vecka, som jag annars skulle spendera på att reda ut Git-härvor, manuellt leta efter buggar eller förlora arbete vid kontextbyten.

Git är ett verktyg som belönar djup. Grunderna tar dig genom dagen. Men kommandona i det här inlägget är vad som skiljer "jag använder Git" från "Git gör mig faktiskt snabbare." Lär dig dem inkrementellt. Välj en ny teknik den här veckan och använd den tills den sitter i muskelminnet. Välj sedan en till.

Ditt framtida jag, stirrandes på en produktionsbugg klockan 23, kommer att tacka dig för att du kan git bisect.

Relaterade inlägg