Miten palauttaa pudonnut kätkö Gitissä?

Käytän usein git stash ja git stash pop tallentaakseni ja palauttaakseni muutoksia työpuussa. Eilen minulla oli joitakin muutoksia työpuussa, jotka olin tallentanut ja pannut, ja sitten tein lisää muutoksia työpuuhun. Haluaisin palata takaisin ja tarkastella eilen piilotettuja muutoksia, mutta git stash pop näyttää poistavan kaikki viittaukset siihen liittyvään toimitukseen.

Tiedän, että jos käytän git stash, niin .git/refs/stash sisältää viittauksen komitukseen, jota käytettiin kätkön luomiseen. Ja .git/logs/refs/stash sisältää koko kätkön. Mutta nämä viittaukset häviävät git stash pop:n jälkeen. Tiedän, että komitit ovat yhä jossain arkistossani, mutta en tiedä, mikä se oli.

Onko olemassa helppoa tapaa palauttaa eilisen kätkön commit-viittaus?

Huomaa, että tämä ei ole kriittistä minulle tänään, koska minulla on päivittäiset varmuuskopiot ja voin palata eiliseen työpuuhun saadakseni muutokset. Kysyn, koska täytyy olla helpompi tapa!

Ratkaisu

Kun tiedät pudottamasi kätkön hash-komission, voit soveltaa sitä kätkönä:

git stash apply $stash_hash

Tai voit luoda sille erillisen haaran komennolla

git branch recovered $stash_hash

Sen jälkeen voit tehdä mitä haluat kaikilla tavallisilla työkaluilla. Kun olet valmis, puhalla haara vain pois.

Hashin löytäminen

Jos olet vasta ponnahtanut ja terminaali on vielä auki, sinulla on vielä git stash pop:n tulostama hash-arvo näytöllä (kiitos, Dolda).

Muussa tapauksessa voit löytää sen käyttämällä tätä Linuxissa, Unixissa tai Git Bashissa Windowsissa:

git fsck --no-reflog | awk '/dangling commit/ {print $3}'

...tai käyttämällä Powershelliä Windowsille:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}

Tämä näyttää sinulle kaikki commit-kuvaajasi kärjissä olevat komitukset, joihin ei enää viitata mistään haarasta tai tagista - jokainen kadonnut komitus, mukaan lukien jokainen koskaan luomaasi stash-komitus, on jossain tuossa kuvaajassa.

Helpoin tapa löytää haluamasi stash commit on luultavasti välittää tuo lista gitk:lle:

gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

...tai katso emraginsin vastaus, jos käytät Powershelliä Windowsille.

Tämä käynnistää arkistoselaimen, joka näyttää sinulle kaikkien arkiston kaikkien aikojen yksittäisten sitoumusten riippumatta siitä, onko se tavoitettavissa vai ei.

Voit korvata gitk siellä jollakin kuten git log --graph --oneline --decorate, jos haluat mieluummin kauniin graafin konsolissa kuin erillisen GUI-sovelluksen.

Löydät kätköjen komennukset etsimällä tämän muotoisia komennusviestejä:

        WIP on somebranch: commithash Jokin vanha commit-viesti.

Huomautus: Commit-viesti on tässä muodossa (alkaen "WIP on") vain, jos et antanut viestiä, kun teit git stash.

Kommentit (23)

Rakensin juuri komennon, joka auttoi minua löytämään kadonneen kätköni commit:

for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less

Tämä listaa kaikki objektit .git/objects-puussa, etsii ne, jotka ovat tyyppiä commit, ja näyttää sitten yhteenvedon jokaisesta objektista. Tästä eteenpäin oli vain katsottava commitit läpi löytääkseen sopivan "WIP on work": 6a9bb2" ("work" on haarani, 619bb2 on tuore commit).

Huomaan, että jos käyttäisin "git stash apply" "git stash pop" sijasta, minulla ei olisi tätä ongelmaa, ja jos käyttäisin "git stash save message", komitusta olisi ehkä ollut helpompi löytää.

Päivitys: Nathanin idean avulla tästä tulee lyhyempi:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
Kommentit (0)

git fsck --unreachable | grep commit pitäisi näyttää sha1:n, vaikka sen palauttama lista saattaa olla melko suuri. git show näyttää, onko kyseessä haluamasi commit.

git cherry-pick -m 1 yhdistää commitin nykyiseen haaraan.

Kommentit (1)