I denne artikkelen vil du lære om forskjellige måter å leke med commits i Git.
Som utvikler ville du vært i slike situasjoner flere ganger hvor du ville ha ønsket å gå tilbake til en av dine tidligere forpliktelser, men ikke sikker på hvordan du gjør det. Og selv om du kjenner Git-kommandoene som reset, revert, rebase, er du ikke klar over forskjellene mellom dem. Så la oss komme i gang og forstå hva git reset, revert og rebase er.
Innholdsfortegnelse
Git Reset
Git reset er en kompleks kommando, og den brukes til å angre endringene.
Du kan tenke på git-tilbakestilling som en tilbakeføringsfunksjon. Med git reset kan du hoppe mellom ulike commits. Det er tre moduser for å kjøre en git-reset-kommando: –myk, –blandet og –hard. Som standard bruker git reset-kommandoen blandet modus. I en arbeidsflyt for tilbakestilling av git kommer tre interne administrasjonsmekanismer for git inn i bildet: HEAD, iscenesettelsesområde (indeks) og arbeidskatalogen.
Arbeidsmappen er stedet der du jobber, det er stedet der filene dine er tilstede. Ved å bruke en git-statuskommando kan du se hvilke filer/mapper som finnes i arbeidskatalogen.
Staging Area (Index) er der git sporer og lagrer alle endringene i filene. De lagrede endringene gjenspeiles i .git-katalogen. Du bruker git add «filnavn» for å legge til filen i oppsamlingsområdet. Og som før, når du kjører git-status, vil du se hvilke filer som finnes i oppsamlingsområdet.
Den nåværende grenen i Git blir referert til som HEAD. Det peker på den siste forpliktelsen, som skjedde i den nåværende kasseavdelingen. Den behandles som en pekepinn for enhver referanse. Når du betaler til en annen filial, flytter HEAD også til den nye filialen.
La meg forklare hvordan git-tilbakestilling fungerer i harde, myke og blandede moduser. Hard-modus brukes til å gå til den spisse commit, arbeidskatalogen blir fylt med filer av den commit, og iscenesettelsesområdet blir tilbakestilt. Ved myk tilbakestilling endres kun pekeren til den angitte commit. Filene til alle forpliktelsene forblir i arbeidskatalogen og oppsamlingsområdet før tilbakestillingen. I blandet modus (standard), blir både pekeren og oppstillingsområdet tilbakestilt.
Git Reset Hard
Hensikten med git hard reset er å flytte HEAD til den spesifiserte commit. Det vil fjerne alle forpliktelsene som skjedde etter den angitte forpliktelsen. Denne kommandoen vil endre commit-historikken og peke til den angitte commit.
I dette eksemplet vil jeg legge til tre nye filer, commit dem og deretter utføre en hard tilbakestilling.
Som du kan se fra kommandoen nedenfor, akkurat nå, er det ingenting å forplikte seg til.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
Nå skal jeg lage 3 filer og legge til noe innhold til det.
$ vi file1.txt $ vi file2.txt $ vi file3.txt
Legg til disse filene i det eksisterende depotet.
$ git add file*
Når du kjører statuskommandoen på nytt, vil den gjenspeile de nye filene jeg nettopp opprettet.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: file1.txt new file: file2.txt new file: file3.txt
Før jeg forplikter meg, la meg vise deg at jeg for øyeblikket har en logg over 3 forpliktelser i Git.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Nå vil jeg forplikte meg til depotet.
$ git commit -m 'added 3 files' [master d69950b] added 3 files 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txt
Hvis jeg gjør ls-filer, vil du se at de nye filene er lagt til.
$ git ls-files demo dummyfile newfile file1.txt file2.txt file3.txt
Når jeg kjører log-kommandoen i git, har jeg 4 commits, og HEAD peker på siste commit.
$ git log --oneline d69950b (HEAD -> master) added 3 files 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Hvis jeg går og sletter file1.txt manuelt og gjør en git-status, vil den vise meldingen om at endringene ikke er iscenesatt for commit.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: file1.txt no changes added to commit (use "git add" and/or "git commit -a")
Nå vil jeg kjøre kommandoen hard reset.
$ git reset --hard HEAD is now at d69950b added 3 files
Hvis jeg sjekker statusen på nytt, vil jeg finne at det ikke er noe å forplikte seg til, og filen jeg slettet har kommet tilbake til depotet. Tilbakeføringen har skjedd fordi jeg ikke forpliktet etter å ha slettet filen, så etter en hard tilbakestilling gikk den tilbake til forrige tilstand.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
Hvis jeg sjekker loggen til git, er det slik det vil se ut.
$ git log commit d69950b7ea406a97499e07f9b28082db9db0b387 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 19:53:31 2020 +0530 added 3 files commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test
Hensikten med hard reset er å peke på den angitte commit og oppdatere arbeidskatalogen og oppsamlingsområdet. La meg vise deg et eksempel til. For øyeblikket ser visualiseringen av forpliktelsene mine slik ut:
Her vil jeg kjøre kommandoen med HEAD^, som betyr at jeg vil tilbakestille til forrige commit (en commit tilbake).
$ git reset --hard HEAD^ HEAD is now at 0db602e one more commit
Du kan se at hodepekeren nå er endret til 0db602e fra d69950b.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Hvis du sjekker loggen, er commit av d69950b borte, og hodet peker nå på 0db602e SHA.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 Test
Hvis du kjører ls-filene, kan du se at file1.txt, file2.txt og files3.txt ikke er i depotet lenger fordi den commit og dens fil ble fjernet etter den harde tilbakestillingen.
$ git ls-files demo dummyfile newfile
Git Soft Reset
På samme måte vil jeg nå vise deg et eksempel på en myk tilbakestilling. Tenk på at jeg har lagt til de 3 filene igjen som nevnt ovenfor og begått dem. Git-loggen vil vises som vist nedenfor. Du kan se «soft reset» er min siste forpliktelse, og HEAD peker også på det.
$ git log --oneline aa40085 (HEAD -> master) soft reset 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Detaljer om forpliktelsen i loggen kan sees ved å bruke kommandoen nedenfor.
$ git log commit aa400858aab3927e79116941c715749780a59fc9 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 21:01:36 2020 +0530 soft reset commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test
Når jeg bruker den myke tilbakestillingen, vil jeg bytte til en av de eldre forpliktelsene med SHA 0db602e085a4d59cfa9393abac41ff5fd7afcb14
For å gjøre det, vil jeg kjøre kommandoen nedenfor. Du må bestå mer enn 6 starttegn i SHA, fullstendig SHA er ikke nødvendig.
$ git reset --soft 0db602e085a4
Nå når jeg kjører git-loggen, kan jeg se at HEAD er tilbakestilt til forpliktelsen jeg spesifiserte.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test
Men forskjellen her er at filene til commit (aa400858aab3927e79116941c715749780a59fc9) hvor jeg hadde lagt til 3 filer er fortsatt i arbeidskatalogen min. De har ikke blitt slettet. Det er derfor du bør bruke en myk tilbakestilling i stedet for en hard tilbakestilling. Det er ingen risiko for å miste filene i myk modus.
$ git ls-files demo dummyfile file1.txt file2.txt file3.txt newfile
Git Revert
I Git brukes revert-kommandoen til å utføre en revert-operasjon, dvs. å tilbakestille noen endringer. Det ligner på tilbakestillingskommandoen, men den eneste forskjellen her er at du utfører en ny commit for å gå tilbake til en bestemt commit. Kort sagt, det er rimelig å si at git revert-kommandoen er en commit.
Git revert-kommandoen sletter ingen data mens du utfører tilbakestillingsoperasjonen.
La oss si at jeg legger til 3 filer og utfører en git commit-operasjon for tilbakestillingseksemplet.
$ git commit -m 'add 3 files again' [master 812335d] add 3 files again 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txt
Loggen vil vise den nye forpliktelsen.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Nå vil jeg gjerne gå tilbake til en av mine tidligere forpliktelser, la oss si – «59c86c9 ny forpliktelse». Jeg ville kjøre kommandoen nedenfor.
$ git revert 59c86c9
Dette vil åpne en fil, du vil finne detaljene for forpliktelsen du prøver å gå tilbake til, og du kan gi den nye forpliktelsen et navn her, og deretter lagre og lukke filen.
Revert "new commit" This reverts commit 59c86c96a82589bad5ecba7668ad38aa684ab323. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # Your branch is ahead of 'origin/master' by 4 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: dummyfile
Etter at du har lagret og lukket filen, er dette utdataene du får.
$ git revert 59c86c9 [master af72b7a] Revert "new commit" 1 file changed, 1 insertion(+), 1 deletion(-)
Nå for å gjøre de nødvendige endringene, i motsetning til tilbakestilling, har revert utført en ny commit til. Hvis du sjekker loggen på nytt, vil du finne en ny commit på grunn av tilbakestillingsoperasjonen.
$ git log --oneline af72b7a (HEAD -> master) Revert "new commit" 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Git-loggen vil ha all historien om forpliktelser. Hvis du vil fjerne forpliktelsene fra historikken, er ikke revert et godt valg, men hvis du vil opprettholde commit-endringene i historikken, er revert den passende kommandoen i stedet for reset.
Git Rebase
I Git er rebase måten å flytte eller kombinere commits fra en gren over en annen gren. Som utvikler ville jeg ikke lage funksjonene mine på mastergrenen i et virkelighetsscenario. Jeg ville jobbe med min egen gren (en «funksjonsgren»), og når jeg har noen få forpliktelser i funksjonsgrenen min med funksjonen lagt til, vil jeg flytte den til hovedgrenen.
Rebase kan noen ganger være litt forvirrende å forstå fordi det ligner veldig på en sammenslåing. Målet med å slå sammen og rebase begge er å ta commitene fra min feature-gren og legge dem til en master-gren eller en hvilken som helst annen gren. Tenk på, jeg har en graf som ser slik ut:
Anta at du jobber i et team med andre utviklere. I så fall kan du forestille deg at dette kan bli veldig komplisert der du har en haug med andre utviklere som jobber med forskjellige funksjonsgrener, og de har slått sammen flere endringer. Det blir forvirrende å spore.
Så det er her rebase kommer til å hjelpe. Denne gangen, i stedet for å gjøre en git-fletting, vil jeg gjøre en rebase, hvor jeg vil ta mine to funksjonsgren-commits og flytte dem til master-grenen. En rebase vil ta alle mine commits fra feature-grenen og flytte dem oppå master-gren-commits. Så, bak kulissene, dupliserer git funksjonsgrenen som utføres på mastergrenen.
Denne tilnærmingen vil gi deg en ren rettlinjet graf med alle forpliktelsene på rad.
Det gjør det enkelt å spore hvilke forpliktelser som gikk hvor. Du kan forestille deg at hvis du er på et lag med mange utviklere, er alle forpliktelsene fortsatt på rad. Så det er veldig enkelt å følge med selv om du har mange som jobber med samme prosjekt samtidig.
La meg vise deg dette praktisk talt.
Slik ser mestergrenen min ut for øyeblikket. Den har 4 forpliktelser.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Jeg vil kjøre kommandoen nedenfor for å opprette og bytte til en ny gren kalt funksjon, og denne grenen vil bli opprettet fra 2. commit, dvs. 59c86c9
(master) $ git checkout -b feature 59c86c9 Switched to a new branch 'feature'
Hvis du sjekker loggen i funksjonsgrenen, har den kun 2 commits som kommer fra masteren (hovedlinjen).
(feature) $ git log --oneline 59c86c9 (HEAD -> feature) new commit e2f44fc (origin/master, origin/HEAD) test
Jeg vil lage funksjon 1 og forplikte den til funksjonsgrenen.
(feature) $ vi feature1.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 1' [feature c639e1b] feature 1 1 file changed, 1 insertion(+) create mode 100644 feature1.txt
Jeg vil lage en funksjon til, dvs. funksjon 2, i funksjonsgrenen og begå den.
(feature) $ vi feature2.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 2' [feature 0f4db49] feature 2 1 file changed, 1 insertion(+) create mode 100644 feature2.txt
Nå, hvis du sjekker loggen til funksjonsgrenen, har den to nye commits, som jeg utførte ovenfor.
(feature) $ git log --oneline 0f4db49 (HEAD -> feature) feature 2 c639e1b feature 1 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Nå vil jeg legge til disse to nye funksjonene til mastergrenen. For det vil jeg bruke rebase-kommandoen. Fra funksjonsgrenen vil jeg rebase mot mastergrenen. Hva dette vil gjøre er at det vil forankre min funksjonsgren mot de siste endringene.
(feature) $ git rebase master Successfully rebased and updated refs/heads/feature.
Nå skal jeg gå videre og sjekke mestergrenen.
(feature) $ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits)
Og til slutt, rebase mastergrenen mot funksjonsgrenen min. Dette vil ta de to nye commitene på min feature-gren og spille dem på toppen av min master-gren.
(master) $ git rebase feature Successfully rebased and updated refs/heads/master.
Hvis jeg nå sjekker loggen på mastergrenen, kan jeg se at de to forpliktelsene til funksjonsgrenen min har blitt lagt til mastergrenen min.
(master) $ git log --oneline 766c996 (HEAD -> master, feature) feature 2 c036a11 feature 1 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Det handlet om tilbakestilling, tilbakestilling og rebase kommandoer i Git.
Konklusjon
Det handlet om tilbakestilling, tilbakestilling og rebase kommandoer i Git. Jeg håper denne trinnvise veiledningen var nyttig. Nå vet du hvordan du leker med forpliktelsene dine etter behov ved å bruke kommandoene nevnt i artikkelen.