Git Reset vs Revert vs Rebase

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.

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:

  Hvordan endre sidemarger i Word

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.

  Hvordan endre Spotify spillelistebilde

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:

  14 beste e-handelsplattformer for små og mellomstore bedrifter

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.