Blog

Git autostash

MAY 25, 2016

Pidin hiljattain Gitin peruskoulutusta, ja sain Mercurialia käyttäviltä osallistujilta kiinnostavan kysymyksen. Vapaasti muotoiltuna:

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!

Miksi git ei voi….?

Miksi en voi tehdä pullia, kun työtilassani on tallentamattomia muutoksia, vaikka Mercurial pystyy siihen suoraan ilman lisäasetuksia?

Vastasin heti, että näin Git suojaa käyttäjää mahdollisesti haitallisilta ja ennen kaikkea peruuttamattomilta muutoksilta. Git suhtautuu oletusarvoisesti hyvin varovaisesti kaikkiin tiedostojärjestelmäsi tallentamattomia muutoksia muokkaaviin toimenpiteisiin, jos Git ei pysty palauttamaan muutoksia ennalleen. Tätä pidetään yleensä ominaisuutena.

Tunnettu ”kiertotapa” eli mahdollinen työnkulku on tallentaa muutokset stashiin ennen pullia (komennolla git stash save) ja palauttaa ne sitten (komennolla git stash pop).

Vaikuttaa ilmeiseltä, että tämän automatisointi git-aliasilla olisi helppoa, mutta se ei olekaan aivan yksinkertaista, sillä git stash ei epäonnistu hallitusti silloin, kun paikallisia muutoksia ei ole.

Git autostash

Koulutuksen jälkeen pohdin asiaa hieman ja tutustuin Gitin viimeisimpiin muutoksiin. Kävi ilmi, että Git tukee tätä nykyään, joten ajattelin, että aiheesta kannattaisi kirjoittaa lyhyt blogikirjoitus.

Gitin versiosta 2.6 lähtien git rebase sisältää ominaisuuden eli valinnan nimeltä autostash.

git rebase -dokumentaatiosta:

--autostash --no-autostash Automatically create a temporary stash before the operation begins, and apply it after the operation ends. This means that you can run rebase on a dirty work-tree. However, use with care: the final stash application after a successful rebase might result in non-trivial conflicts.

Manuaalinen tapa

Ensimmäisenä vaiheena tämä mahdollistaa seuraavan prosessin:

git fetch, jota seuraa: git rebase --autostash

Tämä tallentaa automaattisesti kaikki paikalliset muutokset stashiin, ”tekee järkevän asian” (eli rebaseaa paikalliset commitit saapuvien committien päälle) ja palauttaa sitten muutoksesi.

Valitettavasti git pull -komennossa ei ole vastaavaa valintaa, ei edes käytettäessä komentoa git pull --rebase, mutta älä lannistu.

Git configin käyttö

Onneksi, eikä yllättäen, git sisältää vastaavan konfigurointiominaisuuden nimeltä pull.rebase.

Koska git pull --rebase käyttää taustalla git rebasea, se noudattaa tätä konfigurointiparametria.

Tämä tarkoittaa, että voit suorittaa:

git config rebase.autoStash true

Tämän jälkeen git pull --rebase hoitaa automaattisen stashauksen tästä eteenpäin.

Kaikki mukaan

Jos haluat sitoutua rebase-käytäntöön pysyvästi, voit yhdistää sen pull.rebase true -konfigurointivalintaan:

git config --global pull.rebase true git config --global rebase.autoStash true

Tämän seurauksena kaikki git pull -komennot käyttävät aina rebase-prosessia sekä paikallisten muutosten automaattista stashausta ja palautusta. Melko kätevää…

Mahdolliset konfliktit

Tässä vaiheessa on syytä mainita ilmeinen ja väistämätön tilanne: stashiin tallennetut muutokset voivat olla ristiriidassa joidenkin saapuvien, pullattujen muutosten kanssa.

Tuloste näyttäisi tällöin jotakuinkin tältä:

✗ git pull Created autostash: 094ad5c HEAD is now at d39c25c repo1 - readme First, rewinding head to replay your work on top of it... Fast-forwarded master to 6b6e1d4262fd5bc8d2b974f81222003a6c67fea6. Applying autostash resulted in conflicts. Your changes are safe in the stash. You can run "git stash pop" or "git stash drop" at any time.

Lopputuloksena git pelaa varman päälle. Se jättää työtilasi konfliktitilaan, jonka voit ratkaista tuttuun tapaan suosikkieditorillasi tai merge-työkalullasi. Samalla stash säilyy turvassa siltä varalta, että haluat esimerkiksi tehdä hard resetin ja yrittää uudelleen:

➜ git stash list stash@{0}: autostash

Käytä sen sijaan aliasta

Jos et halua sitoutua tähän työnkulkuun etkä halua suorittaa monivaiheisia komentoja git fetch ja git rebase --autostash, voit luoda sopivan aliaksen.

Yksi ehdotus on:

git config --global alias.up '!git fetch && git rebase --autostash FETCH_HEAD'

Voit sitten käyttää komentoa git up tarpeen mukaan, kun haluat päivittää rebase + autostash -menettelyllä.

  • DevOps
  • CI/CD

Subscribe to our newsletter