siisti, lineaarinen git-historia

yksi monista Git-pohjaisista projekteista on lineaarisen toimitushistorian arvo. Itse asiassa monet työkalut ja ohjeet estävät git-työnkulkuja, jotka tähtäävät lineaariseen historiaan. Mielestäni tämä on surullista, koska siisti historia on erittäin arvokas, ja on olemassa suoraviivainen työnkulku, joka takaa lineaarisen historian.

Lineaarinen vs epälineaarinen historia

lineaarinen historia on yksinkertaisesti Git-historia, jossa kaikki toimitukset tulevat toistensa jälkeen. Ts. et löydä haaroja, joilla on itsenäisiä toimitushistorioita.

1 - epälineaarinen-vs-lineaarinen

miksi haluat lineaarisen historian?

siisteyden ja loogisuuden lisäksi lineaarinen historia tulee tarpeeseen, kun:

  • katselen historiaa. Epälineaarista historiaa voi olla hyvin vaikea seurata – joskus siihen pisteeseen asti, että historia on vain käsittämätöntä.
  • taustamuutokset. Esimerkiksi: “did feature a get introduced before or after bugfix B?”.
  • vikojen jäljittäminen. Gitissä on erittäin siisti funktio nimeltä git bisect, jonka avulla voidaan nopeasti löytää, mikä toimitus esitteli vian tai regression. Epälineaarisen historian myötä git bisectistä tulee kuitenkin vaikea tai jopa mahdoton käyttää.
  • perutaan muutoksia. Sano, että löysit regression aiheuttaneen toimituksen tai haluat poistaa ominaisuuden, jonka ei ollut tarkoitus ilmestyä tietyssä julkaisussa. Hyvällä tuurilla(jos koodisi ei ole muuttunut liikaa) voit yksinkertaisesti palauttaa ei-toivotut toimitukset käyttämällä Git revert-ohjelmaa. Kuitenkin, jos sinulla on epälineaarinen historia, ehkä paljon poikittaisten fuusioiden, tämä on huomattavasti vaikeampaa.

on luultavasti vielä kourallinen tilanteita, joissa lineaarinen historia on hyvin arvokas riippuen siitä, miten käytät Git: tä.

piste on: mitä lineaarisempi historiasi on, sitä vähemmän arvokas se on.

epälineaarisen historian syyt

lyhyesti sanottuna jokainen yhdistämistoimi on mahdollinen epälineaarisen historian lähde. Yhdistämistoimituksia on kuitenkin erilaisia.

Yhdistä aihehaarasta masteriksi

kun aihehaarasi on valmis ja haluat integroida sen masteriksi, yleinen tapa on yhdistää aihehaara masteriksi. Ehkä jotain sen suuntaista:

git checkout mastergit pullgit merge --no-ff my-topic-branch

mukava ominaisuus tällä menetelmällä on se, että säilytät tiedot siitä, mitkä toimitukset olivat osa aihehaaraasi (vaihtoehtona olisi jättää pois “–no-ff”, jolloin Git voisi tehdä pikakelauksen yhdistämisen sijaan, jolloin ei ehkä ole yhtä selvää, mikä toimituksista todella kuului aihehaaraasi).

ongelma sulautumisessa Masteriin syntyy, kun aihehaarasi perustuu vanhaan Masteriin Masterin uusimman kärjen sijaan. Tällöin saat väistämättä epälineaarisen historian.

2 - yhdistäminen-vanha-haara

se, onko tämä yleinen ongelma vai ei, riippuu paljolti siitä, kuinka aktiivinen git-arkisto on, kuinka monta kehittäjää työskentelee samanaikaisesti jne.

Yhdistä Masterista aihehaaraksi

joskus haluat päivittää haarasi vastaamaan uusinta Masteria (esim. Masterissa on joitakin uusia ominaisuuksia, jotka haluat saada aihehaaraasi, tai huomaat, ettet voi yhdistää aihehaaraasi masteriksi, koska on ristiriitoja).

yleinen tapa, jota jotkut jopa suosittelevat, on yhdistää mestarin kärki omaan aihehaaraan. Tämä on merkittävä epälineaarisen historian lähde!

3 - merging-master-into-topic

the solution: Rebase!

Git-rebase on erittäin hyödyllinen funktio, jota sinun tulee käyttää, jos haluat lineaarisen historian. Joidenkin mielestä käsite uudelleensyntyminen on kiusallista, mutta se on oikeastaan melko yksinkertainen: toista muutokset (toimitukset) haarassasi uuden toimituksen päällä.

voit esimerkiksi käyttää git-rebasea vaihtamaan aihehaaran juurta vanhasta Masterista uusimman Masterin kärkeen. Olettaen, että aihehaarasi on tarkistettu, voit tehdä:

git fetch origingit rebase origin/master

4 - uudelleenasennus

huomaa, että vastaava yhdistämistoiminto olisi yhdistää master-sivun kärki aihehaaraasi (kuten edellisessä kuvassa). Tuloksena oleva sisältö tiedostot aihe haara olisi sama, riippumatta siitä, jos teet rebase tai yhdistää. Historia on kuitenkin erilainen (lineaarinen vs epälineaarinen!).

tämä kuulostaa ihan hyvältä ja hyvältä. On kuitenkin olemassa pari varoitusta, joissa on rebase, että sinun pitäisi olla tietoinen.

Varoitus 1: uudelleenjärjestely luo uusia toimituksia

haaran uudelleenjärjestely luo itse asiassa uusia toimituksia. Uusilla toimituksilla on erilaiset SHA:t kuin vanhoilla toimituksilla. Tämä ei yleensä ole ongelma, mutta joudut vaikeuksiin, jos käynnistät uudelleen haaran, joka on olemassa paikallisen arkiston ulkopuolella (esim.jos haarasi on jo olemassa Originissa).

jos siirtäisit uudelleenperustetun haaran etätietokantaan, joka jo sisältää saman haaran (mutta jossa on vanha historia), sinun tulisi:

  1. on pakko painaa haaraa (esim. git push --force-with-lease), koska Git ei muuten salli uuden historian työntämistä olemassa olevaan haaraan. Tämä käytännössä korvaa tietyn etähaaran historian uudella historialla.
  2. saattaa tehdä jonkun toisen hyvin onnettomaksi, koska heidän paikallinen versionsa annetusta haarasta ei enää vastaa etähaaran haaraa, mikä voi johtaa kaikenlaisiin vaikeuksiin.

yleensä on vältettävä sivukonttorin historian kirjoittamista etäyhteydellä (yksi poikkeus on kirjoittaa uudelleen koodikatselmuksen kohteena olevan sivukonttorin historia – riippuen siitä, miten koodikatselmusjärjestelmäsi toimii – mutta tämä on eri keskustelu).

jos haluat käynnistää uudelleen haaran, joka jaetaan muiden kanssa etäyhteydellä, yksinkertainen työnkulku on luoda uusi haara, jonka asetat uudelleen alkuperäisen haaran sijaan. Olettaen, että olet my-topic-branch tarkistettu, voit tehdä:

git checkout -b my-topic-branch-2git fetch origingit rebase origin/mastergit push -u origin my-topic-branch-2

…ja sitten käske my-topic-branch työtä tekeviä jatkamaan my-topic-branch-2 työtä sen sijaan. Vanha haara on silloin käytännössä vanhentunut, eikä sitä tule yhdistää takaisin Masteriin.

Varoitus 2: ristiriitojen ratkaiseminen uudelleenjärjestelyssä voi olla työläämpää kuin yhdistämisessä

jos yhdistämisoperaatiossa ilmenee ristiriita, kaikki ristiriidat ratkaistaan osana yhdistämistoimitusta.

kuitenkin rebase-operaatiossa voit mahdollisesti saada ristiriidan jokaiselle sen haaran pysyvälle toimitukselle, jonka aktivoit.

itse asiassa huomaat monta kertaa, että jos saat ristiriidan toimituksessa, kohtaat toisiinsa liittyviä (hyvin samankaltaisia) konflikteja haarasi myöhemmissä toimituksissa yksinkertaisesti siksi, että aihealueen toimitukset ovat yleensä toisiinsa liittyviä (esim.muokkaamalla samoja koodin osia).

paras tapa minimoida ristiriidat on seurata, mitä Masterissa tapahtuu, ja välttää antamasta aihehaaraa pyörimään liian pitkään ilman uudelleensyntymistä. Pienten konfliktien käsittely edessä aina silloin tällöin on helpompaa kuin käsitellä ne kaikki yhdessä suuressa onnellisessa konfliktisotkussa lopussa.

jotkut varoitukset Githubin käyttäjille

GitHub on loistava monessa asiassa. Se on fantastinen Git hosting, ja se on ihana web-käyttöliittymä koodin selaaminen, mukava Markdown toiminnallisuus, Gist, jne.

Pull-pyynnöissä sen sijaan on muutamia funktioita, jotka aktiivisesti estävät lineaarisen Git-historian. Olisi erittäin tervetullutta, jos GitHub todella korjaisi nämä asiat, mutta siihen asti sinun pitäisi olla tietoinen puutteista:

“Merge pull request” mahdollistaa ei-lineaariset sulautumat hallitsemaan

voi olla houkuttelevaa painaa vihreää, ystävällisen näköistä “Merge pull request” – painiketta yhdistääksesi aihehaaran masteriksi. Varsinkin kun siinä lukee “tämä haara on ajan tasalla kantahaaran kanssa. Yhdistäminen voidaan suorittaa automaattisesti”.

GitHub merge pull request

mitä GitHub todella sanoo Tässä, että haara voidaan yhdistää Masteriin ilman ristiriitoja. Se ei tarkista, perustuuko pull request-haara uusimpaan Masteriin.

toisin sanoen, jos haluat lineaarisen historian, sinun on itse varmistettava, että pull request-haara on uudelleenasennettu uusimman Masterin päälle. Sikäli kuin voin kertoa, GitHub web-käyttöliittymän kautta ei ole saatavilla tällaista tietoa (ellet käytä “suojattuja haaroja” – katso alla), joten sinun on tehtävä se paikalliselta Git-asiakkaaltasi.

vaikka pull-pyyntö olisi oikein reballattu, ei ole mitään takeita siitä, että GitHub-web-käyttöliittymän yhdistämistoiminto olisi atominen (ts. joku voi ajaa muutoksia Masteriin ennen yhdistämistoimintasi läpimenoa-eikä GitHub valita).

joten oikeastaan ainoa tapa varmistaa, että haarasi ovat kunnolla uudelleenasetettuja uusimman Masterin päälle, on tehdä yhdistämistoiminto paikallisesti ja työntää tuloksena olevaa Masteria käsin. Jotain sen suuntaista:

git checkout mastergit pullgit checkout my-pullrequest-branchgit rebase mastergit checkout mastergit merge --no-ff my-pullrequest-branchgit push origin master

jos olet epäonninen ja joku onnistuu työntämään muutoksia hallitsemaan veto-ja työntötoimintojesi välillä, työntötoimintasi evätään. Tämä on kuitenkin hyvä asia, sillä se takaa, että toimintasi on atomista. Vain git reset --hard origin/master ja toista yllä olevat vaiheet, kunnes se menee läpi.

Huom: Respect your project guidelines W. r. t. code Review and testing. Esim.Jos suoritat automaattisia testejä (builds, staattinen analyysi, unit tests, …) osana pull-pyyntöä, sinun pitäisi luultavasti lähettää uudelleen alennettu haarasi (joko käyttämällä git push-f: ää tai avaamalla uusi PR) sen sijaan, että vain päivittäisit päähaaran manuaalisesti.

suojatut haarat-toiminto kannustaa sulautumaan Masterista

jos käytät suojattuja haaroja ja tilatarkistuksia GitHub-projektissasi, saat itse asiassa suojan pull request-haaran yhdistämisestä Masteriin, ellei se perustu viimeisimpään Masteriin (luulen, että perusteluna on, että PR-haarassa tehtyjen tilatarkistusten pitäisi olla voimassa master-haaraan yhdistämisen jälkeen).

kuitenkin … jos pull request-haara ei perustu uusimpaan Masteriin, sinulle esitetään ystävällinen painike “Update branch”, jossa on teksti “this branch is out-date with the base branch. Yhdistä viimeisimmät muutokset Masterista tähän haaraan”.

github-update-branch

tässä vaiheessa paras vaihtoehto on siirtää haaraa paikallisesti ja pakottaa se vetopyyntöön. Jos olet my-pullrequest-branch kirjautunut ulos, älä:

git fetch origingit rebase origin/mastergit push -f

valitettavasti GitHubin vetopyynnöt eivät pelaa hyvin ylivoimapunnerruksilla, joten osa koodin kertaustiedoista saattaa hukkua prosessissa. Jos tämä ei ole hyväksyttävää, harkitse uuden vetopyynnön luomista (toisin sanoen siirrä uudelleensovitettu haarasi uuteen etähaaraan ja luo vetopyyntö uudesta haarasta).

Conclusion

If you care about a linear history:

  • siirrä aihehaarasi uusimman Masterin päälle ennen kuin yhdistät sen masteriksi.
  • älä yhdistä Masteria aihehaaraasi. Siirrä sen sijaan.
  • kun jaat aihehaarasi muiden kanssa, Luo uusi haara aina, kun haluat siirtää sen uudelle tasolle (my-topic-branch-2, my-topic-branch-3, …).
  • jos käytät GitHub pull-pyyntöjä, ole tietoinen:
    • “Merge” – painike ei takaa, että PR-haara perustuu uusimpaan Masteriin. Siirrä annosta tarvittaessa sivuun manuaalisesti.
    • jos käytät suojattuja haaroja, joissa on tilatarkistus, älä koskaan paina “Päivitä haara” – painiketta. Aseta annos uudelleen manuaalisesti.

jos et välitä liikaa lineaarisesta Git history-onnellinen yhdistäminen!

toivelista GitHubille

teille GitHubilla työskenteleville henkilöille: lisää tuki työnkulkujen palauttamiselle pull-pyyntöihin (nämä voivat olla opt-in-arkiston vaihtoehtoja).

  • lisää mahdollisuus poistaa Yhdistämispainike/ – toiminto käytöstä pull-pyynnöissä, jos haara ei perustu uusimpaan Masteriin (tämän ei pitäisi edellyttää tilatarkistusten käyttöä).
  • Lisää “päivitä uusimpaan Masteriin” – painike. Monissa tapauksissa tämän pitäisi olla konfliktitonta toimintaa, joka voidaan helposti tehdä web-käyttöliittymän kautta.
  • säilytä pull-pyyntöhistoria (toimituksia, kommentteja, …) uudelleensyntymisen / pakottamisen jälkeen.

Leave a Reply