Hvis du har brugt Git i et stykke tid, er du sikkert stødt på en historik fuld af unyttige commits, "WIP"-beskeder, hurtige tests eller endda tomme commits, der er oprettet udelukkende for at udløse en hook eller pipeline. I det øjeblik kigger du på loggen og tænker: "Ingen kan forstå dette"Den gode nyhed er, at du ikke er alene: det sker for os alle, og det er dét, støtte er til for. git rebase.
Det interessante er, at når det bruges korrekt, git rebase giver dig mulighed for at "rydde op" i commit-historikken.Gør det lineært, støjfrit og meget nemmere at gennemgå. Du kan slette test-commits, flette flere sammen til én, omarrangere dem, rette commit-beskeder og endda fjerne ændringer fra fjernbetjeningen via et tvungent push. Lad os med konkrete eksempler se på, hvordan du bruger rebase til at transformere din historik fra totalt kaos til noget organiseret og læsbart.
Hvad er Git Rebase præcist, og hvorfor påvirker det historikken?
Når vi taler om overhaling, taler vi bogstaveligt talt om ændre startpunktet for en grenGit tager commits fra din branch og "reproducerer" dem en efter en på en anden base (normalt branchen main eller en opdateret fjernbranch). Det er som om du gik tilbage i tiden og startede dit arbejde fra en anden commit, men beholdt ændringerne.
Forestil dig, at dit projekt har denne historie i hovedgrenen: A – B – CDu opretter en branch af functionality og foretager derefter to commits: D - EI mellemtiden tilføjer nogen i hovedsagen en ny commit FUden at ændre basen ville dine grene se nogenlunde sådan ud:
A---B---C---F (main)
A---B---C---D---E (feature)
Hvis du laver en klassisk merge af din feature branch ind i main, får du en ekstra merge commit, som ofte genererer sammenfiltret historie med flere krydsede linjer. Med rebase tager Git derimod dine commits D og E og genanvender dem til F:
A---B---C---F---D'---E' (feature reescrita)
De der D' og E' Disse er ikke præcis de samme commits som D og E: de er "kopier" med nye identifikatorer (hashes). Derfor siger vi rebase. omskriver historienResultatet er en mere lineær log uden mellemliggende merge-commits, der kun tilføjer støj.

Hvorfor du bør have en ren commit-historik
En organiseret optegnelse er ikke kun et spørgsmål om æstetik. En ren logbog gør det daglige arbejde meget lettere.Du kan med et enkelt blik se, hvad der blev gjort, hvornår og hvorfor, uden at skulle hoppe gennem tomme merge-commits eller kontekstfri "quick fix"-meddelelser.
Når branches flettes sammen ved konstant at flette fra main, ender man med en masse commits som "Merge branch 'main' into feature-x", der De giver ikke reel information om kodeændringerDette komplicerer opgaver som:
- Find den commit, hvor en fejl blev introduceret, ved hjælp af værktøjer til at sammenligne filerfordi historien er fuld af irrelevante sammenlægninger.
- Gennemgå pull requestsfordi du er nødt til at hoppe mellem redundante commits for at se, hvad der rent faktisk har ændret sig.
- Forståelse af udviklingen af en funktionisær hvis det er blevet udviklet over mange små test-commits.
Git rebase er det ideelle værktøj til at "polere" al den støj, før branchen deles med resten af teamet. Det er ligesom at vaske sin historie i vaskemaskinen.Du beholder de vigtige ændringer, velgrupperede og med klare budskaber.
Vigtige forskelle mellem git merge og git rebase
For fuldt ud at forstå, hvad du gør, når du bruger rebase, er det værd at sammenligne dens opførsel med den af git-fusionBegge tjener til at integrere ændringer, men på forskellige måder og med vigtige implikationer for protokollen.
med fusionereGit opretter en ny merge-commit, der har to forældre: spidsen af din branch og spidsen af den branch, du fusionerer med. Den resulterende historik bevarer præcis den oprindelige rækkefølge af commitsMen det kan ende med at blive fyldt med parallelle forgreninger og fusioner.
med RebaseI stedet for at oprette en merge-commit, tager Git dine commits og anvender dem én efter én på den nye database. Dette genererer nye commits med nye hashesselvom kodeændringerne er de samme.
I praksis:
- Flet Den fastholder historien præcis som den skete, med alle dens krydsforbindelser og sammenfletninger.
- rebase Det genererer en lineær og ren historie, som om alt var sket i en lige linje.
Valget er ikke "den ene er bedre end den anden", men Hvilken situation er hver især bedst egnet til?For at kombinere allerede delte og lukkede branches er merging normalt mere sikkert. For at holde lokale branches organiseret eller før åbning af en pull request, kan rebase shines bruges.

Eksempler hvor rebase skinner: opdatering og polering af grene
Der er to scenarier, hvor de fleste udviklere bruger rebase dagligt: Hold din arbejdsgren opdateret med main y Ryd op i commits før du deler demLad os se nærmere på dem.
Opdater din funktionsgren med de seneste ændringer fra main
Du arbejder på en ny funktion i din branch, men i mellemtiden laver dine kolleger stadig commits i mainHvis du vil integrere dine ændringer, er én mulighed at:
git checkout tu-rama-feature
git merge main
Dette virker, men det genererer en merge-commit hver gang du synkroniserer, hvilket i sidste ende forårsager problemer. en historie fuld af gentagne sammenlægningerMen hvis du gør:
git checkout tu-rama-feature
git rebase main
Git vil flytte dine commits oven på den sidste tilstand af main, som om du havde startet branchen efter disse ændringer. Du vil få en lineær historik uden mellemliggende merge-commitsog anmeldelsen vil være tydeligere.
Rens dine commits, før du åbner en pull request
Det er meget almindeligt, at man under udviklingen af en funktion ender med commits som "typo rettelse", "pipeline testing", "flere login ændringer" osv. Det er fint, mens man arbejder, men Det er ikke den slags historie, man vil vise. når du åbner en PR.
Interaktiv rebase giver dig mulighed for reorganiser og grupper disse commits til noget mere logisk. For eksempel i stedet for dette:
- WIP: añadir login
- Más cambios login
- Corregir tests login
- Arreglar typo variable
Du kan ende med en enkelt, velbeskrevet commit:
- Añadir funcionalidad completa de login de usuario con tests
Den "polering" af historien gør den meget lettere for anmeldere at forstå. hvad hver enkelt forpligtelse bidrager med og forenkler fejlfinding i fremtiden.
Interaktiv rebase for at omskrive historien
Den grundlæggende version af rebase flytter blot dine commits til en anden base. Men kronjuvelen er interaktiv overbase, som åbner en editor med en liste over seneste commits, så du kan beslutte, hvad du vil gøre med hver enkelt.
Den typiske måde at starte dette på er ved at angive, hvor mange commits tilbage du vil "røre" fra din nuværende HEAD. For eksempel:
git rebase -i HEAD~6
Denne kommando fortæller Git: "tag de sidste 6 commits fra denne branch og forbered en interaktiv rebase for mig." Git åbner din standardeditor (Vim, Nano, VS Code osv.) med noget i retning af:
pick 7ed9c6e update version
pick ecb7ef3 empty commit 1
pick a323615 empty commit 2
pick 2c3d41d empty commit 3
pick d53c00f empty commit 4
pick 22dcc79 empty commit 5
# Gentag basen på 549dd76..22dcc79 til 549dd76 (6 kommandoer)
#
# Kommandoer:
# p, vælg = brug commit
# r, omformulering = Brug commit, men rediger beskeden
# e, rediger = Brug commit og stop til at ændre det
# s, squash = merge i den forrige commit
# f, rettelse = som squash, men kasserer budskabet
# x, udførelse = udfør shell-kommando
# b, break = stop rebase her
# d, slip = slet commit
# ...
Bemærk én vigtig detalje: Rækkefølgen i denne fil er den modsatte af, hvad du ser i git-loggen.I filen er den første anførte commit (7ed9c6e) den ældste af de seks, og den sidste (22dcc79) er den nyeste. Dette er nøglen til at undgå forvirring, når du sletter eller omarrangerer commits.
Fjern test- eller tomme commits fra den lokale historik
Antag at du, for at teste en Git-hook, har lavet tomme commits med indstillingen –allow-tom. For eksempel:
git commit -m "commit with no changes" --allow-empty
Denne indstilling giver dig mulighed for at oprette en commit, selv når der ikke er ændringer i filerne, hvilket er nyttigt til testning, men Det fylder historikken med commits, der ikke har nogen reel værdi.Forestil dig, at din log ser sådan ud:
git log --pretty=oneline --abbrev-commit
Og du får:
22dcc79 (HEAD -> main, origin/main, origin/HEAD) empty commit 5
d53c00f empty commit 4
2c3d41d empty commit 3
a323615 empty commit 2
ecb7ef3 empty commit 1
7ed9c6e update version
I dette scenarie vil du kun beholde den nyttige "update version"-commit og fjerne alle de andre. tom commit som blot var tests. For at gøre dette kører du den interaktive rebase på de sidste 6 commits:
git rebase -i HEAD~6
Editoren åbner med de 6 commits. Dit mål er at fjerne linjerne, der svarer til de tomme commits. Det vil sige, at du kun efterlader noget i retning af dette:
pick 7ed9c6e update version
# Gentag basen på 549dd76..22dcc79 til 549dd76 (6 kommandoer)
# … resten af kommentarerne …
Som angivet i hjælpeafsnittet i selve filen, Hvis du sletter en linje, forsvinder den commit fra historikken. I den nye, omskrevne version vil Git kun reproducere commit'en "update version" når editoren gemmes og lukkes, og kassere de andre.
Upload af den nye historie til Origin: brug af tvungen push
Indtil videre er alle ændringer i rebase foretaget i din lokale kopi af arkivet. Hvis du ønsker, at denne oprydning også skal afspejles i det eksterne arkiv (f.eks. i oprindelse/hoved), bliver du nødt til at overskrive fjernhistorikken med den nye.
Dette gøres med en tvungen skubEn almindelig måde at indikere dette på er ved at bruge "+"-tegnet foran grennavnet, når du trykker på:
git push origin +main
Plustegnet fortæller Git, at Ignorer historikdivergensen og overskriv den eksterne gren med din omskrevne version. Hvis du blot prøvede at gøre:
git push origin main
Git ville advare dig om, at din lokale historik ikke er en direkte efterkommer af den eksterne historik (fordi du har omskrevet commits med rebase) og ville afvise pushet for at undgå datatab.
Det er vigtigt at forstå, at efter dette påtvungne pres, Slettede commits vil ikke længere være tilgængelige fra origin/mainDe kan stadig være i reflogs eller lokale kopier fra andre kolleger, men af praktiske årsager har du ryddet den eksterne historik.
Alvorlig advarsel: omskrivning af delte grene er ikke et spil
At omskrive historik lyder godt til at organisere alting, men det har en vigtig konsekvens: når man opretter nye commits med nye hashes, Du afviser alle, der allerede havde baseret deres arbejde på de gamle commits.Derfor findes den berømte gyldne regel:
Genbasér ikke grene, der allerede deles og aktivt bruges af andre.
I praksis betyder det, at det er sikkert at bruge rebase på:
- Lokale afdelinger som du ikke har udgivet endnu, eller som kun du bruger.
- Nylige forpligtelser dem du ved, at ingen andre er afhængige af endnu.
Og det er en ret dårlig idé at gøre det ved:
- main, develop eller enhver "officiel" gren fra det arkiv, der tjener som grundlag for flere personer.
- Delte arbejdsgrene hvor der er mere end én udvikler, der foretager commits.
Hvis du omskriver historikken for en delt gren og derefter udfører et tvungent push, vil andre holdkammerater opdage, at Dens grene peger på commits, der ikke længere findes i fjerntliggende områder.De bliver nødt til at udføre mere avancerede operationer (såsom at basere sig på den nye historik eller nulstille) for at rette op på rodet.
Krafttryk: bedre med sikkerhedssele
I mange tilfælde skal du efter en rebase forcere et push. Den klassiske mulighed er:
git push --force origin tu-rama
Denne variant overskriver dog alt på fjernbetjeningen uden at spørge. For at undgå at overskrive andres arbejde ved et uheld tilbyder Git en langt bedre mulighed: –tvangs-med-leasing.
Når du gør:
git push --force-with-lease origin tu-rama
Git tjekker først det Fjernbetjeningen er stadig i den stand, du troede, den var. Da du foretog din sidste pull eller fetch. Hvis den registrerer, at nogen har sendt nye commits til den branch siden da, afvises pushet og fremtvinges ikke, hvilket forhindrer dig i at overskrive andre personers ændringer.
Ideen er at kombinere rebase og force push, altid med et koldt hoved: kun i grene, du kontrollerer og bruger, når det er muligt, –force-with-lease som et ekstra sikkerhedslag.
Hvad skal man gøre, når en rebase går galt: reflog kommer til undsætning
Det er sket for os alle: du starter en interaktiv rebase, sletter eller ændrer noget ved et uheld, løser en konflikt forkert, og pludselig Det ser ud til, at du har mistet noget af dit jobFør du går i panik, så husk at Git har et es i ærmet: git-reflog.
Refloggen er en lokal registrering af alle HEAD-bevægelser: nye commits, nulstillinger, rebases, merges… Takket være den kan du finde ud af, hvor din branch var, før du ødelagde den, og vende tilbage til det punkt med en hard reset.
Det typiske flow ville være:
git reflog
Der vil du se en liste over poster med noget i retning af:
abc1234 HEAD@{0}: rebase terminado
def5678 HEAD@{1}: checkout: moving from main to main
...
Du identificerer den commit, du var ved, før du startede rebasen (for eksempel def5678) og du vender tilbage til ham med:
git reset --hard def5678
På denne måde Du fortryder overlayet helt og du vender tilbage til den forrige tilstand. Du kan også afbryde en igangværende rebase (hvis du er midt i processen og ikke er færdig) blot ved at:
git rebase --abort
Denne kommando efterlader din gren, som den var lige før den aktuelle rebase startede. Perfekt når der opstår konflikter, som du ikke ønsker, eller du ser, at det ikke er et godt tidspunkt at fortsætte.
Git pull vs. git pull –rebase: små forskelle, stor effekt
Et andet punkt, der ofte rejser tvivl, er forskellen mellem git pull normal og git pull --rebaseBegge opdaterer din lokale filial fra fjernbetjeningen, men de gør det på forskellige måder.
Når du løber:
git pull
Git tager to trin: git hente for at overføre ændringerne fra fjernbetjeningen og derefter en git-fusion at kombinere dem med din nuværende gren. Dette kan oprette en ekstra merge-commit, hvis du har lokale commits over fjernbetjeningen, hvilket igen historik med unødvendige fusioner.
Men hvis du kører:
git pull --rebase
Git henter og derefter Repliker dine lokale commits over den opdaterede version på fjernbetjeningen.Resultatet er det samme som hvis du havde gjort det git fetch efterfulgt af git rebase origin/mainog opretholder en renere, mere lineær historie.
Derfor konfigurerer mange teams Git til at bruge rebase som standard, når de laver pulls. Det er en simpel måde at undgå automatiske merge-commits som ikke bidrager med meget.
Sletning af filer eller billeder fra historikken: generel idé
Nogle gange er problemet ikke en grim commit, men en fil, der aldrig burde have nået arkivet: et forkert billede, forkerte loginoplysninger, enorme filer osv. Fristelsen er at gå til GitHub og kigge efter papirkurvsikonet, men hvis det ser ud til at være deaktiveret og viser meddelelser som "du skal være på en gren", er det fordi GitHub tillader ikke at slette historikken på den måde..
Den korrekte metode involverer normalt at bruge historikomskrivning fra din lokale maskine (med interaktiv rebase eller værktøjer som git filter-repo) og derefter udføre et tvungent push. I GitHub Desktop kan du også administrere branches og commits, men driften af fjern en fil fuldstændigt fra alle commits Dette indebærer en omskrivning af historien på en lignende måde, som vi ser her.
Kort sagt, hvis du uploader det forkerte billede eller en følsom fil og ønsker, at den skal "forsvinde" fra historikken, er det ikke nok blot at slette den i den sidste commit: De commits, hvor det blev introduceret, skal omskrives. og derefter tvinge skubbet. Det er en delikat operation, og den bør udføres roligt og i koordinering med dit team.
Praktisk flow til at øve overhaling uden at ødelægge noget
Den bedste måde at blive dygtig til overhaling på er at øve sig i et kontrolleret miljø uden frygt for at forstyrre andres arbejde. En simpel fremgangsmåde ville være:
- Opret en ny gren fra main med git checkout -b mine-gren-tests.
- Foretag flere små commits (disse kan være trivielle ændringer eller testfiler).
- Simuler hovedfremdrift ved at lave nye commits der (eller bede en anden om at gøre det).
- Gå tilbage til din testgren og kør git rebase main for at se, hvordan dine commits er omplaceret.
- Prueba un git rebase -i HEAD~3 at kombinere, omdøbe eller slette de seneste commits.
Med denne øvelse vil du se, hvordan Ændr historien før og efterHvordan Git reagerer på konflikter, og hvordan du kan vende tilbage til tidligere tilstande ved hjælp af reflog, hvis det er nødvendigt. Jo mere øvelse du har lokalt, jo mere sikker vil du være, når du anvender disse teknikker på rigtige projektbranches.
At mestre Git rebase giver dig mulighed for at transformere en kaotisk historik fuld af tomme commits, unødvendige merges og meningsløse beskeder til en klar og læsbar sekvens af betydelige ændringer. Ved at bruge interaktiv rebase, slette test commits, gruppere spredt arbejde, opdatere branches lineært og bruge værktøjer som reflog og tvungne pushes med `--force-with-lease` kan du holde dit repository i en meget sundere og mere professionel tilstand, så længe du husker kun at anvende disse teknikker på branches under din kontrol og underrette teamet, før du omskriver den delte historik.