Dažnai naudoju git stash
ir git stash pop
, kad išsaugočiau ir atkurčiau pakeitimus savo darbo medyje. Vakar savo darbo medyje turėjau keletą pakeitimų, kuriuos buvau išsaugojęs ir ištraukęs, o tada padariau daugiau pakeitimų savo darbo medyje. Norėčiau grįžti atgal ir peržiūrėti vakarykščius pakeitimus, bet git stash pop
, atrodo, pašalina visas nuorodas į susijusį pakeitimą.
Žinau, kad jei naudoju git stash
, tada .git/refs/stash turi nuorodą į tą pakeitimą, kuris buvo panaudotas stehui sukurti. O .git/logs/refs/stash yra visa saugykla. Tačiau po git stash pop
šios nuorodos išnyksta. Aš žinau, kad šis pakeitimas vis dar yra kažkur mano saugykloje, bet nežinau, koks jis buvo.
Ar yra paprastas būdas susigrąžinti vakarykštės stash commit nuorodą?
Atkreipkite dėmesį, kad šiandien man tai nėra kritiškai svarbu, nes turiu kasdienes atsargines kopijas ir galiu grįžti į vakarykštį darbinį medį, kad atsiimčiau savo pakeitimus. Klausiu, nes turi būti lengvesnis būdas!
Sužinoję numestos slėptuvės įsipareigojimo hash, galite jį taikyti kaip slėptuvę:
git stash apply $stash_hash
Arba galite sukurti atskirą šaką su
git branch recovered $stash_hash
Po to galite daryti, ką tik norite, naudodami visus įprastus įrankius. Kai baigsite, šaką tiesiog išmeskite.
Jei ką tik išskleidėte šaką ir terminalas vis dar atidarytas, ekrane vis dar matysite git stash pop
atspausdintą hash vertę (ačiū, Dolda).
Priešingu atveju ją galite rasti naudodami šią funkciją "Linux", "Unix" arba "Git Bash", skirtą "Windows":
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
...arba naudodami "Powershell", skirtą "Windows":
git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}
Tai parodys jums visus įsipareigojimus, esančius jūsų įsipareigojimų grafiko viršūnėse, į kuriuos nebėra nuorodų iš jokios šakos ar žymos - kiekvienas prarastas įsipareigojimas, įskaitant kiekvieną kada nors sukurtą slėptuvės įsipareigojimą, bus kažkur šiame grafike.
Lengviausias būdas rasti norimą "stash commit" tikriausiai yra perduoti šį sąrašą gitk
:
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
...arba žr. emragins atsakymą, jei naudojate "Powershell for Windows".
Taip bus paleista saugyklos naršyklė, kurioje bus rodomi visi kada nors saugykloje esantys įrašai, nepriklausomai nuo to, ar jie pasiekiami, ar ne.
Jei pageidaujate gražaus grafiko konsolėje, o ne atskiros grafinės sąsajos programos, galite pakeisti gitk
kažkuo panašiu į git log --graph --oneline --decorate
.
Norėdami pastebėti "stash" pakeitimus, ieškokite tokios formos pranešimų apie pakeitimus:
WIP on somebranch: commithash Some old commit message
Pastaba: WIP on"WIP on"), jei atlikdami git stash
nepateikėte pranešimo.
Ką tik sukonstravau komandą, kuri padėjo man surasti prarastą slėptuvės įsipareigojimą:
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
Ji išvardija visus .git/objects medyje esančius objektus, suranda commit tipo objektus ir parodo kiekvieno iš jų santrauką. Nuo šio momento tereikėjo peržiūrėti įsipareigojimus ir rasti tinkamą "WIP on work": 6a9bb2" ("work" yra mano šaka, 619bb2 yra naujausias pakeitimas).
Pažymiu, kad jei vietoj "git stash apply" naudočiau "git stash pop", šios problemos nekiltų, o jei naudočiau "git stash save message", tada tą pakeitimą būtų lengviau rasti.
Atnaujinimas: Pasinaudojus Nathan'o idėja, tai tampa trumpiau:
for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
git fsck --unreachable | grep commit
turėtų parodyti sha1, nors sąrašas gali būti gana didelis. git show <sha1>
parodys, ar tai yra norimas įsipareigojimas.
git cherry-pick -m 1 <sha1>
sujungs šį pakeitimą į dabartinę šaką.