Blog

Git-aliasten 10 tasoa: edistyneestä eteenpäin

JUN 17, 2024

Kaksiosaisen blogikirjoitukseni ensimmäisessä osassa lähdimme liikkeelle aivan perusteista: esittelin Gitin aliakset, näytin, miten niillä voi korvata pitkiä ja monimutkaisia komentoja, sekä muutamia useimmille käyttäjille tuntemattomia konsepteja, kuten aliaksia, jotka välittävät parametreja itse Gitille, ja lokien edistynyttä muotoilua mukautetuilla pretty-formaateilla.

Jan Krag

Jan has been with us since 2014 as a Continuous Improvement Agent. He is an accredited trainer for Docker and Github and is also a certified life coach. Jan has a truly diverse range of interests. He breeds oriental cats, builds and flies his own kites, collects Rubik’s cubes, and enjoys snowboarding. Wow!

Ennen kuin jatkat pidemmälle, suosittelen vahvasti lukemaan ensin ensimmäisen osan.

Toisessa osassa esittelen vielä edistyneempiä konsepteja ja sukellan Git-alias-ten todella omaperäisiin käyttötapoihin, mukaan lukien suorastaan hulluja esimerkkejä. Lopuksi esittelen myös vaihtoehtoja samojen tarpeiden ratkaisemiseen.

Sukelletaan siis asiaan.

Taso 6: ! Muut kuin Git-komennot

Enemmän hyötyä samalla vaivalla.

Git-alias-ten avulla voimme laajentaa Git-ympäristössä käytettävien komentojen valikoimaa. Tässä ja useimmissa seuraavissa osioissa tarkastellaan sitä, mitä voimme tehdä, kun astumme Git-alikomentojen rajojen ulkopuolelle.

"Bang"-ominaisuus muuttaa merkittävästi Git-alias-ten mahdollisuuksia, sillä sen avulla voimme kutsua shelliä ja suorittaa mitä tahansa järjestelmämme shell-komentoa. Tämä tehdään yksinkertaisesti lisäämällä alias-laajennuksen alkuun huutomerkki eli Unix-/shell-maailman "bang".

Aloitetaan hyvin yksinkertaisesta esimerkistä, joka havainnollistaa konseptin selkeästi ja on myös aidosti hyödyllinen.

Joillakin alustoilla Gitin mukana tulee valmiiksi asennettuna kaksi hyödyllistä GUI-työkalua: Git gui stage- ja commit-toimintoihin sekä Gitk historian tarkasteluun. Mutta miksi git gui on Git-alikomento, kun taas gitk ei ole? Hämmentävää, mutta helppo korjata aliasilla:

Kun kerran puhumme tästä, minulla on ollut samanlainen ongelma. Kun aivoni ovat syvällä Git-tilassa, sormeni kirjoittavat usein "Git" ennen kuin olen päättänyt, mitä komentoa käytän. Sitten päätänkin yhtäkkiä listata kansion tiedostot ja kirjoitan nopeasti ll <enter> (päivittäin käyttämäni shell-alias komennolle ls -al), ja saan yhtäkkiä:

Nyt "kirjoitusvirhe" git ll toimii, mutta samalla paljastuu bang-ominaisuuden erittäin tärkeä varoitus, joka voi olla tilanteesta riippuen sekä siunaus että kirous.

Vaikka git ll -alias näyttää toimivan, se näyttää aina repositorion juurikansion sisällön, vaikka olisin alikansiossa.

Shell-komento pwd tulostaa nykyisen työhakemiston; tämän aliasin avulla näen nopeasti polun, jossa repositorioni sijaitsee.

Tosin tämä nimenomainen ongelma ratkeaisi paremmin tavallisella Git-aliasilla, jolloin uuden shell-istunnon luomista ei tarvittaisi (tosin siitä, kumpi toimii nopeammin, ei vieläkään ole yksimielisyyttä).

Mutta tällä sivuvaikutuksella on ainakin yksi erittäin hyvä käyttötapaus. Joskus, kun olet muista syistä cd:llä siirtynyt syvälle alikansioon, Git statuksen tulostetta on todella ärsyttävää lukea, koska kaikki muut polut tulostetaan suhteessa nykyiseen kansioon. Muutokset näkyvät silloin esimerkiksi näin:

Hyödynnetään siis "juurikansio"-sivuvaikutusta ja lisätään vaihtoehtoja tavalliselle st-aliasille:

Ne näyttävät status-tulosteen aina suhteessa repositorion juureen.

Git-1

(-s tarkoittaa vain vähemmän laveaa "short"-muotoista tulostetta.)

Huomaa, että vastaava vaikutus voidaan saavuttaa myös käyttämällä status.relativePaths-konfiguraatiomuuttujaa ja tämän blogikirjoituksen ensimmäisen osan "tasolla 5" käsiteltyä -c-ominaisuutta.

Päätetään tämä osio pieneen hauskanpitoon. Jos kirjoitan alitajuisesti Git ennen ll:ää, saatan joskus kirjoittaa Gitin myös ennen kuin päätän käyttää esimerkiksi Git statusta, mikä johtaa ikävään tilanteeseen:

$ git git statusgit: 'git' is not a git command. Joten aivoni keksivät luoda:

Kyllä, tämä saa komennon git git status toimimaan, ja alias-ten rekursiivisen luonteen ansiosta jopa git git git git git status toimii nyt… ainakin teoriassa.

Käytännössä kyse on enemmän hyvästä vitsistä kuin hyvästä ideasta, sillä sillä on kaksi merkittävää seurausta. Ensimmäinen ongelma on, kuten yllä näkyy, että komento suoritetaan nyt repositorion juurikansiosta, mikä voi aiheuttaa sekaannusta. Toinen ongelma on, että se rikkoo varsin tärkeän mahdollisuuden suorittaa git help git, jolla saa varsinaisen Git-komennon ohjesivun. Sen sijaan se tulostaisi nyt paljon vähemmän hyödyllisen:

Taso 7: Git-alias-ten uudelleenkäyttö

Rakenna aiemman päälle … Hyödynnä sitä, mikä oli jo olemassa

Gitin vanhemmissa, 2.20:ta edeltävissä versioissa Git-alias ei voinut viitata toiseen Git-aliakseen. Tämä johti usein moniin samankaltaisiin aliaksiin konfiguraatiotiedostossa, kuten mukautettuja Git log -komentoja käsitellessämme nähtiin.

Ainoa käytettävissä ollut kiertotapa oli hyödyntää bang-ominaisuutta, sillä sen avulla voi aivan hyvin tehdä näin:

Tämä ei kutsu olemassa olevaa aliasta rekursiivisesti, vaan käynnistää uuden shell-istunnon, joka vain sattuu käyttämään Git-aliasia.

Onneksi Git 2.20:stä (2018) lähtien rekursiiviset aliakset ovat olleet sallittuja, ja versiosta 2.30 (Q1 2021) lähtien jopa bash-completion (tab-completion) ymmärtää ja muuntaa ne.

Nyt voin siis käyttää huomattavasti siistimpää Git-konfiguraatiota:

Taso 8: Toiminnon putkittaminen

Unix-komentojen ketjuttaminen lisää hallintaa (tai hulluutta)

Mainitsin aiemmin, että bang-ominaisuus oli mullistava, mutta raapaisimme vasta pintaa. Seuraava askel on huomata, että shellin kutsuminen mahdollistaa useiden komentojen ketjuttamisen.

Yksinkertaisin käyttötapa ovat aliakset, jotka tekevät shellin ja &&-operaattorin avulla useita erillisiä asioita peräkkäin.

Huomautus: Yllä oleva alias on rivitetty luettavuuden vuoksi. Konfiguraatiossa sen on oltava yhdellä rivillä. Lisää tästä myöhemmin.

Voimme jopa käyttää olemassa olevia ympäristömuuttujia tai määrittää uusia muuttujia suoraan aliaksessa.

In case of fire

Tulostin kopion omaan toimistoomme, mikä käynnisti Slackissa pitkän ja humoristisen keskustelun siitä, miksi tämä ei toimisi ja miten sitä pitäisi parantaa.

Lopputuloksena syntyi seuraava loistava alias, joka havainnollistaa hienosti muuttujien käyttöä:

Todellinen voima tulee kuitenkin esiin, kun viemme tämän askeleen pidemmälle ja alamme käyttää Unix-putkia yhden komennon tulosteen välittämiseen toiselle.

Määritän ensin nopean remoteurl-aliaksen, joka helpottaa Git remoten URL-osoitteen hakemista. Mutta entä jos kloonasin repositorion ssh:llä ja URL on muodossa "git@", kun haluan käyttää sitä repositorion verkkosivun löytämiseen?

Lähetetään ensimmäisen komennon tuloste sedille, joka hakee ja korvaa tekstiä sekä vaihtaa git@:n  https://:ksi.

Viimeistellään tämä lisäämällä alias, joka lähettää tulosteen suoraan leikepöydälle Macin pbcopy-komennolla. (Windowsissa voisimme tehdä saman clip-komennolla.)

Vastaavasti voimme käyttää muita shellin ominaisuuksia, kuten tulosteen uudelleenohjaamista tiedostoihin. Joskus haluan luoda repositorioihini .mailmap-tiedoston. Sen avulla voi esimerkiksi "yhdistää" joidenkin osallistujien vanhan sähköpostiosoitteen uuteen tai varmistaa, että käyttäjän eri tavoin kirjoitetut nimet yhdistetään.

Hyväksi lähtökohdaksi mailmapille tarvitsen listan tekijöistä sekä heidän nimistään ja sähköpostiosoitteistaan vakiomuodossa "Jan Krag <jan.krag@example.com>", hieman samaan tapaan kuin git shortlog -sne tuottaa, mutta ilman ensimmäistä numerosaraketta.

Tätä varten keksin seuraavat aliakset:

[alias]mm   = "!git log  --format='%aN ' | sort -u"mmm  = "!git mm >> .mailmap"mmme = "!git mmm && code .mailmap"

Log tulostaa jokaisen commitin tekijän ja sähköpostiosoitteen, minkä jälkeen shellin sort-komennon "unique"-valitsin poistaa duplikaatit ja lajittelee tulosteen. Ensimmäinen alias tulostaa tiedot konsoliin, kun taas toinen uudelleenohjaa tulosteen ja luo .mailmap-tiedoston tai lisää siihen sisältöä.

Kolmas on kiireisen käyttäjän kätevä versio, joka avaa uuden .mailmap-tiedoston heti VSCode-editorissani. Yhdistämme siis samaan aliakseen putket, uudelleenohjaukset ja &&-ominaisuuden.

Taso 9: Funktiot

Bash-funktiot ovat parhaita!

Nostetaan taas tasoa siinä, mitä voimme tehdä. Nyt kun käytössämme on tämä shell-konteksti, voimme hyödyntää myös funktioiden määrittelyä. Miksi haluaisin tehdä niin, saatat kysyä? Se tekee monimutkaisista aliaksista jonkin verran selkeämpiä, mutta tärkeintä on mahdollisuus lukea komentoriviargumentteja ja käyttää niitä hallitummin.

Tavallisissa aliaksissa voit lisätä aliaksen perään haluamiasi valitsimia ja argumentteja, jotka lisätään laajennuksen jälkeen. Esimerkiksi edellisen kirjoituksen Git slog -aliastani voi aivan hyvin käyttää muodossa git slog -3 tai git slog --all. Mutta entä jos haluan luoda aliaksen, jossa tarvitsen saman argumentin useassa kohdassa?

Yksinkertainen esimerkki tästä on aliakseni, jolla poistetaan haara sekä paikallisesti että remotesta:

Huomaa syntaksi. Shell-kontekstissani aloitan määrittelemällä funktion f(), joka suorittaa lauseet avaavasta {:sta viimeiseen }:-merkkiin.

Lopuksi kutsun funktiota sen nimellä f. Hienoa on, että voimme nyt välittää funktiolle argumentteja, jotka ovat funktion laajuudessa käytettävissä "paikkaparametreina" yhdestä alkaen numeroituina. ${1} viittaa siis yksinkertaisesti ensimmäiseen argumenttiin, jonka käyttäjä antaa funktiota kutsuessaan, ja kuten esimerkistä näet, voimme käyttää parametria niin monta kertaa kuin haluamme.

Katsotaan toista yksinkertaista esimerkkiä:

[alias] # Lisää GitHub-repo helposti uutena remotena ghremote= "!f(){ git remote add $1 https://github.com/$2.git; }; f"

Tässä esimerkissä käytän funktiota en argumentin uudelleenkäyttöön, vaan siksi, että haluan ottaa vastaan useita argumentteja ja käyttää niitä tietyissä kohdissa aliaksen sisällä.

Saatat huomata, että tässä esimerkissä paikkaparametreja käytetään ilman aaltosulkeita. Tarkoitus on vain havainnollistaa, että bashin sääntöjen mukaan aaltosulkeita tarvitaan vain yli yhdeksän oleville paikkaparametreille, joten valinta on sinusta kiinni.

Kokeillaan tätä ghremote-aliasta:

Taso 10: Yli äyräiden

Monirivisen muotoilun esittely.

Olemme aiemmin nähneet muutamia esimerkkejä aliaksista, joista tulee konfiguraatioon hyvin pitkiä rivejä ja jotka ovat siksi lähes "lukukelvottomia". On kuitenkin mahdollista tehdä oikeita monirivisiä aliaksia. Lisää vain kenoviiva rivin loppuun, sillä se ohittaa rivinvaihdon.

Tämä ei kuitenkaan varsinaisesti vastaa kysymykseen: "kannattaako niin tehdä?"

Jossain vaiheessa tulevat vastaan rajat sille, mikä aliaksissa on järkevää, ja silloin kannattaa harkita vaihtoehtoja, jotka esittelen "tasolla 11". Tämä on kuitenkin blogikirjoitus aliaksista, joten venytetään rajoja hieman, ja voit tehdä oman arviosi.

Aloitetaan tämä osio melko monimutkaisella mutta toisinaan hyödyllisellä esimerkillä, jota en aio selittää yksityiskohtaisesti.

swm-aliaksen symbolic-ref-kikan yhdistäminen tähän oletushaaran löytämiseksi jää harjoitustehtäväksi sinulle, hyvä lukija.

Selitettävää ei juuri enää ole, joten katsotaan vain muutamaa esimerkkiä, jotka voivat innostaa sinua kirjoittamaan omia aliaksia.

"Haluan vain avata tämän repon verkkosivun."

Mutta mitä tehdä, jos Git remote käyttää SSH:ta?

Katsotaan, miten sitä käytetään:

git-1

Mitkä tiedostot saavat eniten huomiota?

Löysin tämän alun perin Michael Walesin blogikirjoituksesta .gitconfigista ja muokkasin sitä hieman omien mieltymysteni mukaiseksi.

[alias]churn = !git -p log --all -M -C --name-only\      --format='format:' $@ \        | sort \        | grep -v '^$' \        | uniq -c \        | sort -r \        | awk 'BEGIN {print count,file} {print $1 , $2}'

Ja käytössä git-katas-repossa:

$ git churn42 README.md24 basic-commits/README.md21 basic-branching/README.md19 ignore/README.md19 basic-staging/README.md17 submodules/README.md17 3-way-merge/README.md16 configure-git/README.md15 Overview.md14 ff-merge/README.md

Miksi minun täytyy tietää, miten jatketaan?

Pidän usein Git-koulutuksia, ja aina kun puhumme merge-/rebase-konfliktien ratkaisemisesta, minulla on kyseenalainen ilo esitellä:

git merge --continuegit rebase --continuegit cherry-pick --continuegit revert --continue

Jossain vaiheessa aloin ihmetellä: ”Miksi ihmeessä minun käyttäjänä täytyy määrittää, mitä jatkan, kun Git tietää aivan selvästi olevansa merge-, rebase- tai muussa vastaavassa tilassa? Miksei olisi vain continue-komentoa, joka tekee oikean asian?”

Muistaakseni tein niin kuin ennen ChatGPT:tä tehtiin: etsin netistä ja löysin bash-skriptin, joka tekee tämän. Kuten seuraavassa luvussa todetaan, se on luultavasti myös järkevä ratkaisu, mutta fanina tein sen, mikä piti tehdä, ja toteutin sen pelkkänä alias-komentona. Voin siis esitellä tämän hirvityksen, joka todella ilmentää överiksi vetämisen henkeä:

Git-alias-komentojen jakaminen

Tämän osion lopuksi jaan kanssasi ”pyhän graalin” alias-komentoni, jonka kehitin noin kymmenen vuotta sitten kovalla työllä ja päättäväisyydellä.

Halusin ratkaista esimerkiksi alias-komentojen jakamisen Slackissa työkavereille. Jos haluan antaa nopean alias-komennon vähemmän kokeneelle Git-käyttäjälle, on turhan monimutkaista joutua joka kerta selittämään, miten globaali config-tiedosto löytyy ja sitä muokataan, mihin alias-koodi tiedostossa lisätään ja niin edelleen.

Olisi paljon selkeämpää lähettää suoraan sopiva git config –global alias.foo "do this Git thing" -komento, jonka vastaanottaja voi ajaa sellaisenaan. Yksinkertaiset alias-komennot kirjoitan ulkomuistista, mutta jo hieman monimutkaisemmissa, lainausmerkkejä ja ehkä muuttujia sisältävissä aliaksissa oikean muodon saaminen ei ole aivan yksinkertaista. Siksi sain idean tehdä exportalias-alias-komennon. En arvannutkaan, kuinka vaikeaa tämän saaminen oikein olisi, ja yksi onnistumiskriteereistä oli matkan varrella se, että sen pitäisi pystyä viemään myös itsensä. En ole testannut sitä taistelukentällä aivan kaikilla hulluimmilla monirivisillä alias-komennoilla, mutta niissä tapauksissa jakaisin joka tapauksessa .gitconfig-katkelman.

Jätin tämän tarkoituksella ilman rivinvaihtoja varmistaakseni, että se on vietävässä muodossa.

Kokeillaan sitä tämän kirjoituksen aiemmin esitellyllä, ei aivan yksinkertaisella alias-komennolla – sellaisella, joka sisältää sekä erikoismerkkejä että escapattuja lainausmerkkejä.

Taso 11: Bonuskierros

Onko hulluudella rajaa?

Tässä viimeisessä bonusosiossa esittelen muutamia vaihtoehtoisia tapoja laajentaa Gitin toiminnallisuutta – vaihtoehtoja, jotka voivat osoittautua järkevämmiksi kuin koko sivun mittaiset moniriviset alias-komennot.

Omat ohjelmat

Ensimmäinen oivallus on, että Git on rakennettu viisaasti: mikä tahansa PATHissa oleva ohjelma nimeltä git-something muuttuu git something -komennoksi.

Tämä tarkoittaa, että voisimme toteuttaa osan pidemmistä alias-komennoistamme yksinkertaisena bash-skriptinä. Miksi tällä on väliä? Osittain siksi, että vältät suuren osan .gitconfig-tiedoston rajoissa pysymisen muotoiluvaivasta, kuten rivinvaihtojen escape-käsittelyn ja tarpeettoman lainausmerkkien säätämisen.

Toinen etu on, että voimme kirjoittaa paremmin ”oikeita” skriptejä, joissa on asianmukainen argumenttien käsittely, virheenkäsittely, käyttöohjetekstit ja niin edelleen.

Git ei itse asiassa edes edellytä Bashin käyttöä. Voit kirjoittaa uudet Git-komentosi millä tahansa kielellä, vaikka kannattaa ehkä pitäytyä kielessä, jolla on hyvä Git-kirjasto, kuten Pythonissa, Javassa tai Go:ssa.

Git-laajennuspaketit

Jos voimme kirjoittaa omia Git-komentoja PATHissa olevina ohjelmina, voimme myös kirjoittaa ja jakaa kokonaisia kokoelmia niitä. On jopa avoimen lähdekoodin projekteja, jotka tarjoavat tällaisia ”Git-laajennuksia” joko tiettyihin tarkoituksiin tai yleisinä ”hyödyllisten” komentojen kokoelmina.

Yksi suurimmista tällaisista yleiskokoelmista on https://github.com/tj/git-extras, joka asennettuna lisää työkalupakkiisi yli 70 uutta komentoa. Niihin kuuluu myös itseään mainostava git extras, joka listaa ne kaikki. Sen voi asentaa useimmilla yleisillä paketinhallintaohjelmilla tai kloonata manuaalisesti, jos se ei ole mahdollista, esimerkiksi:$sudo apt-get install git-extras

tai

En listaa kaikkia 70 komentoa, mutta tässä muutama poiminta:

  • git-abort: Keskeytä მიმდინარე Git-toiminto.

  • git-alias: Määritä, hae ja näytä aliakset.

  • git-magic: Automatisoi add/commit/push-rutiinit.

  • git-repl: Gitin read-eval-print-loop.

  • git-standup: Palauta mieleen, mitä teit edellisenä työpäivänä.

Toinen tutustumisen arvoinen laajennuspaketti on Git Pastiche. Se sisältää huomattavasti pienemmän valikoiman komentoja, jotka ovat ehkä hieman matalamman tason komentoja, mutta pidän erityisesti komennoista git stats ja git activity, joista on ajoittain paljon hyötyä.

Tässä yhteydessä kannattaa ehkä mainita myös, että Gitin "ydinlaajennuksena" pitämämme Git LFS, eli Git Large File Storage, on niin ikään toteutettu tällä konseptilla laajennuksena ja kirjoitettu Go-kielellä. Git LFS:n ydinkomento on vain git-lfs-suoritustiedosto, joka puolestaan ohjaa kaikki lfs-alikomennot muille Go-ohjelmille.

Ohje

Lopuksi käsittelen lyhyesti ohjeita. Jos haluat panostaa omiin Git-komentoihisi kunnolla, kuten "git extras" ja muut ovat tehneet, voit tarjota omia ohjesivuja.

Kun kirjoitat git help mycustom, Git tarkistaa, löytyykö järjestelmästäsi mycustomin man-sivu. Man-sivujen luominen ei kuulu tämän blogikirjoituksen aihepiiriin, mutta aiheesta on helppo löytää hyviä ohjeita.

Git-aliasten kohdalla olet ehkä huomannut, että esimerkiksi git help st tulostaa vain seuraavan:

Tästä voi olla hyötyä tai sitten ei, tarpeistasi riippuen.

Tällaisten perusaliasten kohdalla, eli kun alias ei kutsu bashia, voit käyttää myös muotoa git st --help. Se avaa aliaksen varsinaisen komennon normaalin ohjesivun, tässä tapauksessa komennon git status.

Kiitokset ja vastuuvapauslausekkeet

Tämän kirjoituksen esimerkit ovat peräisin yli vuosikymmenen aikana kertyneestä henkilökohtaisesta Git-kokoelmastani. Osaa niistä on muokattu kunkin osion havainnollistamistarkoitukseen.

Aliasten alkuperästä sen verran, että osan olen kirjoittanut itse omiin tarpeisiini, ja osan olen saanut kollegoiltani, Git-koulutusteni osallistujilta ja ystäviltäni. Osan olen löytänyt vuosien varrella verkosta ja joko kopioinut sellaisenaan tai mukauttanut omaan käyttöön. Yleisesti näitä jaetaan yhteisöllisessä hengessä, joten toivon tämän kuuluvan "fair use" -periaatteen piiriin.

Viime aikoina olen alkanut lisätä configiini kommentteja hyvin monimutkaisten aliasten yhteyteen ja kertoa, mistä olen ne löytänyt. Silti näiden koodiesimerkkien alkuperää on vaikea jäljittää, koska muut toimivat kuten minäkin: lainaavat jostain ja muokkaavat tarpeen mukaan.

Jos löysit tästä blogikirjoituksesta aliaksen, jonka alkuperäiseksi tekijäksi katsot itsesi, kerro minulle. Mainitsen sinut lähteenä tai poistan aliaksen pyynnöstäsi.

Muista tutustua myös tämän blogikirjoituksen ensimmäiseen osaan, jos et ole vielä tehnyt niin!

  • Software development
  • DevOps
  • CI/CD

Subscribe to our newsletter