1. En detaljert guide til Git for nybegynnere

I dag skal vi snakke om et versjonskontrollsystem, nemlig Git.

Du kan virkelig ikke være en fullverdig programmerer uten å kjenne og forstå dette verktøyet. Selvfølgelig trenger du ikke å ha alle Git-kommandoene og funksjonene i hodet for å være kontinuerlig ansatt. Du må kjenne til et sett med kommandoer som vil hjelpe deg å forstå alt som skjer.

Grunnleggende om Git

Git er et distribuert versjonskontrollsystem for koden vår. Hvorfor trenger vi det? Team trenger et slags system for å administrere arbeidet sitt. Det er nødvendig å spore endringer som skjer over tid.

Det vil si at vi må kunne se trinn for trinn hvilke filer som har endret seg og hvordan. Dette er spesielt viktig når du undersøker hva som endret seg i sammenheng med en enkelt oppgave, noe som gjør det mulig å tilbakestille endringene.

La oss forestille oss følgende situasjon: vi har fungerende kode, alt i den er bra, men så bestemmer vi oss for å forbedre eller justere noe. Ingen big deal, men vår "forbedring" brøt halvparten av programmets funksjoner og gjorde det umulig å fungere. Så hva nå? Uten Git ville du måtte sitte og tenke i timevis og prøve å huske hvordan alt var opprinnelig. Men med Git ruller vi bare tilbake forpliktelsen – og det er det.

Eller hva om det er to utviklere som gjør sine egne kodeendringer samtidig? Uten Git kopierer de de originale kodefilene og endrer dem separat. Det kommer en tid da begge ønsker å legge til endringene sine i hovedkatalogen. Hva gjør du i dette tilfellet?

Det vil ikke være slike problemer hvis du bruker Git.

Installerer Git

La oss installere Java på datamaskinen din. Denne prosessen er litt forskjellig for forskjellige operativsystemer.

Installerer på Windows

Som vanlig må du laste ned og kjøre en exe-fil. Alt er enkelt her: klikk på den første Google-lenken , utfør installasjonen, og det er det. For å gjøre dette bruker vi bash-konsollen levert av Windows.

På Windows må du kjøre Git Bash. Slik ser det ut i startmenyen:

Nå er dette en ledetekst du kan jobbe med.

For å unngå å måtte gå til mappen med prosjektet hver gang for å bestille å åpne Git der, kan du åpne ledeteksten i prosjektmappen med høyre museknapp med banen vi trenger:

Installerer på Linux

Vanligvis er Git en del av Linux-distribusjoner og er allerede installert, siden det er et verktøy som opprinnelig ble skrevet for Linux-kjerneutvikling. Men det er situasjoner når det ikke er det. For å sjekke, må du åpne en terminal og skrive: git --version. Hvis du får et forståelig svar, trenger du ingenting å installere.

Åpne en terminal og installer. For Ubuntu må du skrive: sudo apt-get install git. Og det er det: nå kan du bruke Git i hvilken som helst terminal.

Installerer på macOS

Også her må du først sjekke om Git allerede er der (se ovenfor, det samme som på Linux).

Hvis du ikke har det, er den enkleste måten å få det på å laste ned den nyeste versjonen . Hvis Xcode er installert, vil Git definitivt bli installert automatisk.

Git-innstillinger

Git har brukerinnstillinger for brukeren som skal sende inn arbeid. Dette gir mening og er nødvendig, fordi Git tar denne informasjonen for Author-feltet når en commit opprettes.

Sett opp et brukernavn og passord for alle prosjektene dine ved å kjøre følgende kommandoer:

git config --global bruker.navn "Ivan Ivanov" git config --global bruker.email ivan.ivanov@gmail.com

Hvis du trenger å endre forfatteren for et spesifikt prosjekt (for et personlig prosjekt, for eksempel), kan du fjerne "--global". Dette vil gi oss følgende:

git config bruker.navn "Ivan Ivanov" git config bruker.e-post ivan.ivanov@gmail.com

Litt teori

For å dykke ned i temaet bør vi introdusere deg for noen nye ord og handlinger... Ellers blir det ingenting å snakke om. Dette er selvfølgelig sjargong som kommer til oss fra engelsk, så jeg legger til oversettelser i parentes.

Hvilke ord og handlinger?

  • git repository
  • begå
  • gren
  • slå sammen
  • konflikter
  • dra
  • trykk
  • hvordan ignorere noen filer (.gitignore)

Og så videre.

Statuser i Git

Git har flere statuer som må forstås og huskes:

  • usporet
  • modifisert
  • iscenesatt
  • engasjert

Hvordan skal du forstå dette?

Dette er statuser som gjelder for filene som inneholder koden vår. Med andre ord ser livssyklusen deres vanligvis slik ut:

  • En fil som er opprettet, men som ennå ikke er lagt til i depotet, har statusen "usporet".
  • Når vi gjør endringer i filer som allerede er lagt til i Git-depotet, blir statusen deres "modifisert".
  • Blant filene vi har endret, velger vi de vi trenger (for eksempel trenger vi ikke kompilerte klasser), og disse klassene endres til statusen "iscenesatt".
  • En commit opprettes fra forberedte filer i trinnvis tilstand og går inn i Git-depotet. Etter det er det ingen filer med "iscenesatt" status. Men det kan fortsatt være filer hvis status er "endret".

Slik ser det ut:

Hva er en forpliktelse?

En commit er hovedbegivenheten når det kommer til versjonskontroll. Den inneholder alle endringene som er gjort siden forpliktelsen startet. Forpliktelser er koblet sammen som en enkeltlenket liste.

Konkret er det en første forpliktelse. Når den andre forpliktelsen er opprettet, vet den (den andre) hva som kommer etter den første. Og på denne måten kan informasjon spores.

En commit har også sin egen informasjon, såkalte metadata:

  • forpliktelsens unike identifikator, som kan brukes til å finne den
  • navnet på forpliktelsens forfatter, som opprettet den
  • datoen forpliktelsen ble opprettet
  • en kommentar som beskriver hva som ble gjort under forpliktelsen

Slik ser det ut:

Hva er en gren?

En gren er en pekepinn til en forpliktelse. Fordi en commit vet hvilken commit som går foran den, når en gren peker på en commit, gjelder alle de tidligere commitene også for den.

Følgelig kan vi si at du kan ha så mange grener du vil som peker på samme commit.

Arbeid skjer i grener, så når en ny commit opprettes, flytter grenen pekeren til den nyere commit.

Komme i gang med Git

Du kan jobbe med et lokalt depot alene så vel som med et eksternt.

For å praktisere de nødvendige kommandoene kan du begrense deg til det lokale depotet. Den lagrer kun all prosjektets informasjon lokalt i .git-mappen.

Hvis vi snakker om det eksterne depotet, så er all informasjonen lagret et sted på den eksterne serveren: bare en kopi av prosjektet lagres lokalt. Endringer som er gjort i din lokale kopi kan skyves (git push) til det eksterne depotet.

I diskusjonen vår her og nedenfor snakker vi om å jobbe med Git i konsollen. Selvfølgelig kan du bruke en slags GUI-basert løsning (for eksempel IntelliJ IDEA), men først bør du finne ut hvilke kommandoer som blir utført og hva de betyr.

Arbeide med Git i et lokalt depot

For å opprette et lokalt depot, må du skrive:

git init

Dette vil opprette en skjult .git-mappe i konsollens gjeldende katalog.

.git-mappen lagrer all informasjon om Git-depotet. Ikke slett den ;)

Deretter legges filer til prosjektet, og de får statusen "Usporet". For å sjekke gjeldende status for arbeidet ditt, skriv dette:

git status

Vi er i mestergrenen, og her blir vi værende til vi bytter til en annen gren.

Dette viser hvilke filer som har endret seg, men som ennå ikke er lagt til "iscenesatt" status. For å legge dem til "iscenesatt"-status, må du skrive "git add". Vi har noen alternativer her, for eksempel:

  • git add -A — legg til alle filene til "iscenesatt" status
  • git legg til. - legg til alle filer fra denne mappen og alle undermapper. I hovedsak den samme som den forrige;
  • git add <file name> — legger til en spesifikk fil. Her kan du bruke regulære uttrykk for å legge til filer etter et eller annet mønster. For eksempel git add *.java: Dette betyr at du bare vil legge til filer med java-utvidelsen.

De to første alternativene er helt klart enkle. Ting blir mer interessant med det siste tilskuddet, så la oss skrive:

git add *.txt

For å sjekke statusen bruker vi kommandoen som allerede er kjent for oss:

git status

Her kan du se at det regulære uttrykket har fungert riktig: test_resource.txt har nå statusen "stadium".

Og til slutt, den siste fasen for å jobbe med et lokalt depot (det er en til når du arbeider med det eksterne depotet ;)) — å lage en ny forpliktelse:

git commit -m "alle txt-filer ble lagt til prosjektet"

Neste opp er en flott kommando for å se på forpliktelseshistorien på en gren. La oss bruke det:

git logg

Her kan du se at vi har opprettet vår første forpliktelse, og den inkluderer teksten vi ga på kommandolinjen. Det er veldig viktig å forstå at denne teksten skal forklare så nøyaktig som mulig hva som ble gjort under denne forpliktelsen. Dette vil hjelpe oss mange ganger i fremtiden.

En nysgjerrig leser som ennå ikke har sovnet, lurer kanskje på hva som skjedde med GitTest.java-filen. La oss finne ut av det nå. For å gjøre dette bruker vi:

git status

Som du ser er den fortsatt "usporet" og venter i kulissene. Men hva om vi ikke vil legge det til prosjektet i det hele tatt? Noen ganger skjer det.

For å gjøre ting mer interessant, la oss nå prøve å endre test_resource.txt-filen vår. La oss legge til litt tekst der og sjekke statusen:

git status

Her kan du tydelig se forskjellen mellom "usporet" og "modifisert" status.

GitTest.java er "usporet", mens test_resource.txt er "modifisert".

Nå som vi har filer i modifisert tilstand, kan vi undersøke endringene som er gjort i dem. Dette kan gjøres ved å bruke følgende kommando:

git diff

Det vil si at du tydelig kan se her hva jeg la til tekstfilen vår: hei verden!

La oss legge til endringene våre i tekstfilen og lage en forpliktelse:

git add test_resource.txt
git commit -m “la til hei ord! til test_resource.txt»

For å se på alle forpliktelser, skriv:

git logg

Som du kan se, har vi nå to commits.

Vi legger til GitTest.java på samme måte. Ingen kommentarer her, bare kommandoer:

git legg til GitTest.java
git commit -m “la til GitTest.java”
git status

Arbeider med .gitignore

Det er klart at vi bare ønsker å beholde kildekoden alene, og ingenting annet, i depotet. Så hva annet kan det være? Som et minimum, kompilerte klasser og/eller filer generert av utviklingsmiljøer.

For å fortelle Git å ignorere dem, må vi lage en spesiell fil. Gjør dette: lag en fil kalt .gitignore i roten av prosjektet. Hver linje i denne filen representerer et mønster som skal ignoreres.

I dette eksemplet vil .gitignore-filen se slik ut:

*.class
target/
*.iml
.idea/

La oss ta en titt:

  • Den første linjen er å ignorere alle filer med filtypen .class
  • Den andre linjen er å ignorere "mål"-mappen og alt den inneholder
  • Den tredje linjen er å ignorere alle filer med filtypen .iml
  • Den fjerde linjen er å ignorere .idea-mappen

La oss prøve å bruke et eksempel. For å se hvordan det fungerer, la oss legge til den kompilerte GitTest.class til prosjektet og sjekke prosjektstatusen:

git status

Det er klart at vi ikke ønsker å legge til den kompilerte klassen ved et uhell i prosjektet (ved å bruke git add -A). For å gjøre dette, lag en .gitignore-fil og legg til alt som ble beskrevet tidligere:

La oss nå bruke en commit for å legge til .gitignore-filen til prosjektet:

git add .gitignore
git commit -m "la til .gitignore-fil"

Og nå sannhetens øyeblikk: vi har en kompilert klasse GitTest.class som er "usporet", som vi ikke ønsket å legge til Git-depotet.

Nå bør vi se effekten av .gitignore-filen:

git status

Perfekt! .gitignore +1 :)

Arbeid med grener

Naturligvis er det upraktisk å jobbe i én gren for ensomme utviklere, og det er umulig når det er mer enn én person på et team. Det er derfor vi har filialer.

En gren er bare en bevegelig peker til forpliktelser.

I denne delen skal vi utforske arbeid i forskjellige grener: hvordan slå sammen endringer fra en gren til en annen, hvilke konflikter som kan oppstå og mye mer.

For å se en liste over alle grenene i depotet og forstå hvilken du er i, må du skrive:

git gren -a

Du kan se at vi bare har en mastergren. Stjernen foran indikerer at vi er i den. Du kan forresten også bruke «git status»-kommandoen for å finne ut hvilken gren vi befinner oss i.

Så er det flere alternativer for å lage grener (det kan være flere - dette er de jeg bruker):

  • opprette en ny filial basert på den vi er i (99 % av tilfellene)
  • opprette en filial basert på en spesifikk forpliktelse (1 % av tilfellene)

La oss lage en gren basert på en spesifikk forpliktelse

Vi vil stole på forpliktelsens unike identifikator. For å finne den skriver vi:

git logg

Vi har fremhevet forpliktelsen med kommentaren "added hello world..." Dens unike identifikator er 6c44e53d06228f888f2f454d3cb8c1c976dd73f8. Vi ønsker å lage en "utviklings"-gren som starter fra denne forpliktelsen. For å gjøre dette skriver vi:

git checkout -b utvikling 6c44e53d06228f888f2f454d3cb8c1c976dd73f8

En gren opprettes med kun de to første commitene fra mastergrenen. For å bekrefte dette, sørger vi først for å bytte til en annen filial og ser på antall forpliktelser der:

git status
git logg

Og som forventet har vi to forpliktelser. Forresten, her er et interessant poeng: det er ingen .gitignore-fil i denne grenen ennå, så vår kompilerte fil (GitTest.class) er nå uthevet med "usporet"-status.

Nå kan vi gå gjennom avdelingene våre igjen ved å skrive dette:

git gren -a

Du kan se at det er to grener: «master» og «utvikling». Vi er for tiden i utvikling.

La oss lage en gren basert på den nåværende

Den andre måten å lage en gren på er å lage den fra en annen. Vi ønsker å lage en filial basert på mastergrenen. Først må vi bytte til det, og neste trinn er å lage en ny. La oss ta en titt:

  • git checkout master — bytt til mastergrenen
  • git status — bekreft at vi faktisk er i mastergrenen

Her kan du se at vi byttet til mastergrenen, .gitignore-filen er i kraft, og den kompilerte klassen er ikke lenger uthevet som "usporet".

Nå lager vi en ny gren basert på mastergrenen:

git checkout -b feature/update-txt-filer

Hvis du er usikker på om denne grenen er det samme som "master", kan du enkelt sjekke ved å kjøre "git log" og se på alle commitene. Det skal være fire av dem.

Konfliktløsning

Før vi utforsker hva en konflikt er, må vi snakke om å slå sammen en gren til en annen.

Dette bildet viser prosessen med å slå sammen en gren til en annen:

Her har vi en hovedgren. På et tidspunkt blir en sekundær gren opprettet av hovedgrenen og deretter modifisert. Når arbeidet er gjort, må vi slå sammen den ene grenen til den andre.

I vårt eksempel opprettet vi grenen feature/update-txt-files. Som indikert av navnet på filialen, oppdaterer vi teksten.

Nå må vi opprette en ny forpliktelse for dette arbeidet:

git add *.txt
git commit -m "oppdaterte txt-filer"
git logg

Nå, hvis vi ønsker å slå sammen funksjonen/update-txt-filene til master, må vi gå til master og skrive "git merge feature/update-txt-files":

git checkout master
git merge feature/update-txt-filer
git logg

Som et resultat inkluderer mastergrenen nå også forpliktelsen som ble lagt til feature/update-txt-filer.

Denne funksjonaliteten ble lagt til, slik at du kan slette en funksjonsgren. For å gjøre dette skriver vi:

git branch -D feature/update-txt-filer

La oss komplisere situasjonen: la oss nå si at du må endre txt-filen igjen. Men nå skal denne filen endres i mastergrenen også. Det vil med andre ord endre seg parallelt. Git vil ikke være i stand til å finne ut hva vi skal gjøre når vi ønsker å slå sammen vår nye kode inn i mastergrenen.

Vi oppretter en ny gren basert på master, gjør endringer i text_resource.txt og oppretter en forpliktelse for dette arbeidet:

git checkout -b feature/add-header

... vi gjør endringer i filen

git add *.txt
git commit -m "la til header til txt"

Gå til hovedgrenen og oppdater også denne tekstfilen på samme linje som i funksjonsgrenen:

git checkout master

… vi oppdaterte test_resource.txt

git add test_resource.txt
git commit -m "la til hovedhode i txt"

Og nå det mest interessante poenget: vi må slå sammen endringer fra funksjonen/add-header-grenen til master. Vi er i mastergrenen, så vi trenger bare å skrive:

git merge feature/add-header

Men resultatet vil være en konflikt i test_resource.txt-filen:

Her kan vi se at Git ikke kunne bestemme på egen hånd hvordan denne koden skulle slås sammen. Det forteller oss at vi må løse konflikten først, og først deretter utføre forpliktelsen.

OK. Vi åpner filen med konflikten i et tekstredigeringsprogram og ser:

For å forstå hva Git gjorde her, må vi huske hvilke endringer vi gjorde og hvor, og deretter sammenligne:

  1. Endringene som var på denne linjen i mastergrenen finnes mellom "<<<<<<< HEAD" og "=======".
  2. Endringene som var i grenen feature/add-header finnes mellom "=======" og ">>>>>>> feature/add-header.

Dette er hvordan Git forteller oss at den ikke kunne finne ut hvordan den skulle utføre sammenslåingen på dette stedet i filen. Den delte denne delen inn i to deler fra de forskjellige grenene og inviterer oss til å løse sammenslåingskonflikten selv.

Greit nok. Jeg bestemmer meg frimodig for å fjerne alt, og etterlater bare ordet "header":

La oss se på statusen til endringene. Beskrivelsen vil være litt annerledes. I stedet for en "modifisert" status, har vi "unfusion". Så kunne vi ha nevnt en femte status? Jeg tror ikke dette er nødvendig. La oss se:

git status

Vi kan overbevise oss selv om at dette er en spesiell, uvanlig sak. La oss fortsette:

git add *.txt

Du kan legge merke til at beskrivelsen foreslår å skrive bare "git commit". La oss prøve å skrive det:

git forplikte

Og akkurat som det gjorde vi det - vi løste konflikten i konsollen.

Dette kan selvsagt gjøres litt enklere i integrerte utviklingsmiljøer. For eksempel, i IntelliJ IDEA er alt satt opp så godt at du kan utføre alle nødvendige handlinger rett innenfor det. Men IDE-er gjør mange ting "under panseret", og vi forstår ofte ikke hva som skjer der. Og når det ikke er forståelse, kan det oppstå problemer.

Arbeider med eksterne depoter

Det siste trinnet er å finne ut noen flere kommandoer som er nødvendige for å fungere med det eksterne depotet.

Som jeg sa, et eksternt depot er et sted hvor depotet er lagret og hvorfra du kan klone det.

Hva slags eksterne depoter finnes det? Eksempler:

  • GitHub er den største lagringsplattformen for repositories og samarbeidsutvikling.
  • GitLab er et nettbasert verktøy for DevOps-livssyklusen med åpen kildekode. Det er et Git-basert system for å administrere kodelagre med sin egen wiki, feilsporingssystem, CI/CD-pipeline og andre funksjoner.
  • BitBucket er en webtjeneste for prosjektvert og samarbeidsutvikling basert på Mercurial og Git versjonskontrollsystemer. På et tidspunkt hadde den en stor fordel fremfor GitHub ved at den tilbød gratis private depoter. I fjor introduserte GitHub også denne muligheten for alle gratis.
  • Og så videre…

Når du arbeider med et eksternt depot, er den første tingen å gjøre å klone prosjektet til ditt lokale depot.

For dette eksporterte vi prosjektet som vi laget lokalt. Nå kan alle klone det for seg selv ved å skrive:

git-klone https://github.com/romankh3/git-demo

Det finnes nå en komplett lokal kopi av prosjektet. For å være sikker på at den lokale kopien av prosjektet er den nyeste, må du trekke prosjektet ved å skrive:

git pull

I vårt tilfelle er ingenting i fjernlageret endret for øyeblikket, så svaret er: Allerede oppdatert.

Men hvis vi gjør noen endringer i det eksterne depotet, oppdateres det lokale etter at vi henter dem.

Og til slutt, den siste kommandoen er å skyve dataene til det eksterne depotet. Når vi har gjort noe lokalt og ønsker å sende det til fjernlageret, må vi først opprette en ny commit lokalt. For å demonstrere dette, la oss legge til noe annet i tekstfilen vår:

Nå er noe ganske vanlig for oss - vi oppretter en forpliktelse for dette arbeidet:

git add test_resource.txt
git commit -m "forberedt txt for å skyve"

Kommandoen for å skyve dette til det eksterne depotet er:

git push

Det var det for nå!

Nyttige lenker

2. Hvordan jobbe med Git i IntelliJ IDEA

I denne delen lærer du hvordan du jobber med Git i IntelliJ IDEA.

Nødvendige innganger:

  1. Les, følg med og forstå forrige del. Dette vil bidra til å sikre at alt er satt opp og klart til bruk.
  2. Installer IntelliJ IDEA. Her skal alt være i orden :)
  3. Sett av en time for å oppnå fullstendig mestring.

La oss jobbe med demoprosjektet som jeg brukte til artikkelen om Git.

Klon prosjektet lokalt

Det er to alternativer her:

  1. Hvis du allerede har en GitHub-konto og ønsker å pushe noe senere, er det bedre å splitte prosjektet og klone din egen kopi. Du kan lese om hvordan du oppretter en gaffel i en annen artikkel under overskriften Et eksempel på gaffelarbeidsflyten .
  2. Klon depotet og gjør alt lokalt uten muligheten til å skyve hele greia til serveren.

For å klone et prosjekt fra GitHub, må du kopiere prosjektlenken og sende den til IntelliJ IDEA:

  1. Kopier prosjektadressen:

  2. Åpne IntelliJ IDEA og velg "Få fra versjonskontroll":

  3. Kopier og lim inn prosjektadressen:

  4. Du vil bli bedt om å opprette et IntelliJ IDEA-prosjekt. Godta tilbudet:

  5. Siden det ikke er noe byggesystem, velger vi "Opprett prosjekt fra eksisterende kilder":

  6. Deretter får du se denne vakre skjermen:

Nå som vi fant ut kloning, kan du ta en titt rundt.

Første blikk på IntelliJ IDEA som et Git UI

Ta en nærmere titt på det klonede prosjektet: du kan allerede få mye informasjon om versjonskontrollsystemet.

Først har vi Versjonskontroll-panelet i nedre venstre hjørne. Her kan du finne alle lokale endringer og få en liste over commits (analogt med "git log").

La oss gå videre til en diskusjon om Log. Det er en viss visualisering som hjelper oss å forstå nøyaktig hvordan utviklingen har gått. For eksempel kan du se at en ny gren ble opprettet med en tilføyd overskrift til txt commit, som deretter ble slått sammen til hovedgrenen. Hvis du klikker på en forpliktelse, kan du se i høyre hjørne all informasjon om forpliktelsen: alle endringer og metadata.

Dessuten kan du se de faktiske endringene. Vi ser også at en konflikt ble løst der. IDEA presenterer også dette veldig godt.

Hvis du dobbeltklikker på filen som ble endret under denne forpliktelsen, vil vi se hvordan konflikten ble løst:

Vi legger merke til at til venstre og høyre har vi de to versjonene av den samme filen som måtte slås sammen til én. Og i midten har vi det endelige sammenslåtte resultatet.

Når et prosjekt har mange grener, forpliktelser og brukere, må du søke separat etter gren, bruker og dato:

Før du setter i gang, er det også verdt å forklare hvordan du forstår hvilken gren vi er i.

I nedre høyre hjørne er det en knapp merket "Git: master". Det som følger etter "Git:" er den gjeldende grenen. Hvis du klikker på knappen, kan du gjøre mange nyttige ting: bytte til en annen gren, opprette en ny, gi nytt navn til en eksisterende, og så videre.

Arbeider med et depot

Nyttige hurtigtaster

For fremtidig arbeid må du huske noen svært nyttige hurtigtaster:

  1. CTRL+T — Få de siste endringene fra fjernlageret (git pull).
  2. CTRL+K — Opprett en forpliktelse / se alle gjeldende endringer. Dette inkluderer både usporede og modifiserte filer (git commit).
  3. CTRL+SHIFT+K — Dette er kommandoen for å skyve endringer til det eksterne depotet. Alle forpliktelser som er opprettet lokalt og ennå ikke er i det eksterne depotet, vil bli presset (git push).
  4. ALT+CTRL+Z — Tilbakestill endringer i en spesifikk fil til tilstanden til den siste commit som ble opprettet i det lokale depotet. Hvis du velger hele prosjektet i øvre venstre hjørne, kan du rulle tilbake endringer i alle filer.

Hva vil vi?

For å få utført arbeid må vi mestre et grunnleggende scenario som brukes overalt.

Målet er å implementere ny funksjonalitet i en egen gren og deretter skyve den til et eksternt depot (da må du også opprette en pull-forespørsel til hovedgrenen, men det er utenfor omfanget av denne leksjonen).

Hva kreves for å gjøre dette?

  1. Få alle gjeldende endringer i hovedgrenen (for eksempel "master").

  2. Fra denne hovedgrenen oppretter du en egen gren for arbeidet ditt.

  3. Implementer den nye funksjonaliteten.

  4. Gå til hovedavdelingen og sjekk om det har vært noen nye endringer mens vi jobbet. Hvis ikke, så er alt bra. Men hvis det var endringer, så gjør vi følgende: gå til arbeidsgrenen og rebase endringene fra hovedgrenen til vår. Hvis alt går bra, så flott. Men det er fullt mulig at det blir konflikter. Som det skjer, kan de bare løses på forhånd, uten å kaste bort tid i det eksterne depotet.

    Lurer du på hvorfor du bør gjøre dette? Det er god oppførsel og forhindrer konflikter i å oppstå etter å ha presset filialen din til det lokale depotet (det er selvfølgelig en mulighet for at konflikter fortsatt vil oppstå, men det blir mye mindre).

  5. Send endringene dine til det eksterne depotet.

Hvordan får jeg endringer fra den eksterne serveren?

Vi la til en beskrivelse i README med en ny forpliktelse og ønsker å få disse endringene. Hvis endringer ble gjort både i det lokale depotet og i det eksterne, er vi invitert til å velge mellom en sammenslåing og en rebase. Vi velger å slå sammen.

Skriv inn CTRL+T :

Du kan nå se hvordan README har endret seg, dvs. endringene fra fjernlageret ble trukket inn, og i nedre høyre hjørne kan du se alle detaljene om endringene som kom fra serveren.

Opprett en ny gren basert på master

Alt er enkelt her.

Gå til nederste høyre hjørne og klikk Git: master . Velg + Ny gren .

La avmerkingsboksen Checkout filial være valgt og skriv inn navnet på den nye filialen. I vårt tilfelle: dette vil være readme-forbedrer .

Git: master vil da endres til Git: readme-improver .

La oss simulere parallelt arbeid

For at konflikter skal dukke opp, må noen skape dem.

Vi vil redigere README med en ny commit gjennom nettleseren, og dermed simulere parallelt arbeid. Det er som om noen gjorde endringer i den samme filen mens vi jobbet med den. Resultatet vil bli en konflikt. Vi fjerner ordet "fully" fra linje 10.

Implementer funksjonaliteten vår

Vår oppgave er å endre README og legge til en beskrivelse til den nye artikkelen. Det vil si at arbeidet i Git går gjennom IntelliJ IDEA. Legg til dette:

Endringene er gjort. Nå kan vi opprette en forpliktelse. Trykk CTRL+K , som gir oss:

Før vi oppretter en forpliktelse, må vi se nærmere på hva dette vinduet tilbyr.

I Commit Message- delen skriver vi tekst knyttet til commit. Deretter må vi klikke på Commit for å opprette den .

Vi skriver at README har endret seg og oppretter commit. Et varsel dukker opp i nedre venstre hjørne med navnet på forpliktelsen:

Sjekk om hovedgrenen er endret

Vi fullførte oppgaven vår. Det fungerer. Vi skrev prøver. Alt er bra. Men før vi skyver til serveren, må vi fortsatt sjekke om det var noen endringer i hovedgrenen i mellomtiden. Hvordan kunne det skje? Ganske enkelt: noen mottar en oppgave etter deg, og at noen fullfører den raskere enn du fullfører oppgaven.

Så vi må gå til mestergrenen. For å gjøre dette, må vi gjøre det som vises i nedre høyre hjørne i skjermbildet nedenfor:

I hovedgrenen trykker du CTRL+T for å få de siste endringene fra den eksterne serveren. Når du ser på endringene, kan du enkelt se hva som skjedde:

Ordet "fully" ble fjernet. Kanskje noen fra markedsføring bestemte at det ikke skulle skrives slik og ga utviklerne en oppgave om å oppdatere det.

Vi har nå en lokal kopi av den nyeste versjonen av masterfilialen. Gå tilbake til readme-improver .

Nå må vi rebase endringene fra mastergrenen til vår. Vi gjør dette:

Hvis du gjorde alt riktig og fulgte med meg, skulle resultatet vise en konflikt i README-filen:

Her har vi også mye informasjon å forstå og suge til oss. Her vises en liste over filer (i vårt tilfelle én fil) som har konflikter. Vi kan velge mellom tre alternativer:

  1. godta din - godta kun endringer fra readme-improver.
  2. godta deres — godta kun endringer fra master.
  3. slå sammen – velg selv hva du vil beholde og hva du vil forkaste.

Det er ikke klart hva som endret seg. Hvis det er endringer i hovedgrenen, må de være nødvendige der, så vi kan ikke bare godta endringene våre. Følgelig velger vi sammenslåing :

Her kan vi se at det er tre deler:

  1. Dette er endringene fra readme-improver.
  2. Det sammenslåtte resultatet. Foreløpig er det det som eksisterte før endringene.
  3. Endringene fra mastergrenen.

Vi må produsere et sammenslått resultat som vil tilfredsstille alle. Når vi ser på hva som ble endret FØR endringene våre, innser vi at de ganske enkelt fjernet ordet "fully". Ok ikke noe problem! Det betyr at vi også vil fjerne det i det sammenslåtte resultatet og deretter legge til endringene våre. Når vi har korrigert det sammenslåtte resultatet, kan vi klikke på Bruk .

Da dukker det opp et varsel som forteller oss at rebasen var vellykket:

Der! Vi løste vår første konflikt gjennom IntelliJ IDEA.

Push endringer til den eksterne serveren

Det neste trinnet er å skyve endringene til den eksterne serveren og opprette en pull-forespørsel. For å gjøre dette, trykk ganske enkelt CTRL+SHIFT+K . Da får vi:

Til venstre vil det være en liste over forpliktelser som ikke har blitt presset til det eksterne depotet. Til høyre vil være alle filene som er endret. Og det er det! Trykk Push og du vil oppleve lykke :)

Hvis push er vellykket, vil du se et varsel som dette i nedre høyre hjørne:

Bonus: opprette en pull-forespørsel

La oss gå til et GitHub-depot og vi ser at GitHub allerede vet hva vi vil ha:

Klikk Sammenlign og trekk forespørsel . Klikk deretter på Opprett pull request . Fordi vi løste konfliktene på forhånd, nå når vi oppretter en pull-forespørsel, kan vi umiddelbart slå den sammen:

Det var det for nå!