it-swarm-eu.dev

Jak se vrátit k poklesu skrýš v Git?

Často používám git stash a git stash pop k uložení a obnovení změn v pracovním stromu. Včera jsem měl nějaké změny ve svém pracovním stromu, který jsem měl schovaný a vyskakoval, a pak jsem udělal více změn v pracovním stromu. Chci se vrátit a zkontrolovat včerejší změny, ale git stash pop se zdá, že odstraní všechny odkazy na přidružené potvrzení.

Vím, že když použiju git stash pak .git/refs/stash obsahuje odkaz na závazek použitý pro vytvoření skrýše. A .git/logs/refs/stash obsahuje celou skrýš. Ale tyto odkazy jsou pryč po git stash pop. Vím, že ten dar je někde v mém úložišti, ale nevím, co to bylo.

Existuje snadný způsob, jak obnovit včerejší stash odkaz?

Všimněte si, že to není pro mě dnes rozhodující, protože mám denní zálohy a můžu se vrátit ke včerejšímu pracovnímu stromu, abych získal své změny. Ptám se, protože tam musí být snadnější způsob!

1489
Greg Hewgill

Jakmile znáte hash stash, který jste zrušili, můžete jej použít jako skrýš:

git stash apply $stash_hash

Nebo můžete pro něj vytvořit samostatnou větev

git branch recovered $stash_hash

Poté můžete dělat, co chcete, se všemi běžnými nástroji. Až budete hotovi, odfoukněte větev.

Nalezení hash

Pokud jste to jen vyskočili a terminál je stále otevřený, budete mít stále ještě hodnotu hash vytištěnou git stash pop na obrazovce (díky, Dolda).

V opačném případě jej můžete použít pro Linux, Unix nebo Git Bash pro Windows:

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

... nebo pomocí Powershell pro Windows:

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

To vám ukáže všechny příkazy v tipech vašeho grafu, který již není odkazován z žádné větve nebo značky - každý ztracený závazek, včetně všech stash commitů, které jste kdy vytvořili, bude někde v daném grafu.

Nejjednodušším způsobem, jak najít požadovaný příkaz, je pravděpodobně tento seznam předat gitk:

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

... nebo viz odpověď z emragins pokud používáte Powershell pro Windows.

Spustí se prohlížeč úložiště, který zobrazuje každý jednotlivý záznam v úložišti , bez ohledu na to, zda je dostupný nebo ne.

Můžete nahradit gitk tam něco jako git log --graph --oneline --decorate pokud dáváte přednost grafu Nice na konzole přes samostatnou aplikaci GUI.

Chcete-li naskenovat skryté potvrzení, podívejte se na potvrzovací zprávy tohoto formuláře:

WIP zapnuto somebranchcommithash Některé staré zprávy

Poznámka : Zpráva o potvrzení bude pouze v tomto formuláři (počínaje "WIP zapnuta"), pokud jste nezadali zprávu, když jste udělali git stash.

2402

Pokud jste terminál neuzavřeli, stačí se podívat na výstup z git stash pop a budete mít ID objektu o upuštěné skrýši. Obvykle to vypadá takto:

$ git stash pop
[...]
Dropped refs/[email protected]{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)

(Všimněte si, že git stash drop také produkuje stejný řádek.)

Chcete-li získat tento skrýt zpět, stačí spustit git branch tmp 2cae03e, a dostanete to jako pobočku. Chcete-li převést soubor na skrytou, spusťte:

git stash apply tmp
git stash

Mít to jako větev také vám umožní volně manipulovat s ním; například, aby si to vybral nebo sloučil.

664
Dolda2000

Jen jsem chtěl zmínit tento dodatek k přijatému řešení. Nebylo mi hned jasné, kdy jsem tuto metodu poprvé vyzkoušela (možná to mělo být), ale použít skrýš z hodnoty hash, stačí použít „git stash apply“:

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Když jsem byl nový na git, nebylo to pro mě jasné a snažil jsem se o různé kombinace "git show", "git apply", "patch" atd.

252
Wade

Chcete-li získat seznam skrytých položek, které jsou stále ve vašem úložišti, ale které již nejsou k dispozici:

git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP

Pokud jste svůj titul skryli, nahraďte na konci příkazu slovo „WIP“ v -grep=WIP části zprávy, např. -grep=Tesselation.

Příkaz je grepping pro "WIP", protože výchozí zpráva o potvrzení pro stash je ve tvaru WIP on mybranch: [previous-commit-hash] Message of the previous commit.

79
Senthil A Kumar

Právě jsem zkonstruoval příkaz, který mi pomohl najít ztracenou výplatu:

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

Zobrazí seznam všech objektů ve stromu .git/objects, vyhledá ty, které jsou typu commit, a pak zobrazí souhrn každého z nich. Od této chvíle to byla jen otázka prohledání závazků najít vhodné "WIP na práci: 6a9bb2" ("práce" je moje větev, 619bb2 je nedávný závazek).

Všiml jsem si, že kdybych použil "git stash apply" namísto "git stash pop", neměl bych tento problém, a kdybych použil "git stash save message ", pak by mohlo být snazší nalezení.

Aktualizace: S Nathanovým nápadem se toto zkracuje:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
71
Greg Hewgill

git fsck --unreachable | grep commit by měl zobrazovat sha1, i když seznam, který vrací, může být poměrně velký. git show <sha1> se ukáže, zda se jedná o potvrzení, které chcete.

git cherry-pick -m 1 <sha1> sloučí potvrzení do aktuální větve.

38
Nathan Jones

Pokud chcete restash ztracené skrýš, musíte najít hash své ztracené skrýš první.

Jak Aristotle Pagaltzis navrhl, git fsck by vám měl pomoci.

Osobně používám svůj alias log-all, který mi ukazuje každý závazek (zpětně se zaváže) mít lepší přehled o situaci:

git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)

Pokud hledáte pouze zprávy „WIP on“, můžete provést ještě rychlejší vyhledávání.

Jakmile znáte svůj sha1, jednoduše změníte svůj ukrytý reflog a přidáte starou skrýš:

git update-ref refs/stash ed6721d

Pravděpodobně budete raději mít přidruženou zprávu, takže -m

git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d

A budete to chtít použít i jako alias:

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1
27
Colin Hebert

Windows PowerShell ekvivalent pomocí gitk:

gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })

Existuje pravděpodobně efektivnější způsob, jak to udělat v jednom potrubí, ale to dělá práci.

19
emragins

Líbilo se mi to Aristotelovu přístupu, ale nelíbilo se mi používat GITK ... jak jsem zvyklý používat GIT z příkazové řádky.

Namísto toho jsem si vzal visící spáchání a výstup kód do souboru DIFF pro kontrolu v editoru kódu.

git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff

Nyní můžete nahrát výsledný soubor diff/txt (jeho domovský adresář) do txt editoru a zobrazit aktuální kód a výsledný SHA.

Pak stačí použít

git stash apply ad38abbf76e26c803b27a6079348192d32f52219
16
Shaheen Ghiassy

V OSX s git v2.6.4 jsem náhodou spustil git stash drop, pak jsem ho našel tím, že jsem šel dolů pod kroky

Pokud znáte název účtu, pak použijte:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>

jinak najdete ID z výsledku ručně:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show

Pak, když zjistíte, že id-id právě stiskl git stash, použijte {commit-id}

Doufám, že to pomůže někomu rychle

12
Can Tecim

Proč se lidé ptají na tuto otázku? Protože o reflogu ještě nevědí ani nerozumí.

Většina odpovědí na tuto otázku dává dlouhé příkazy s možnostmi téměř nikdo si nebude pamatovat. Takže lidé přicházejí do této otázky a kopírovat pastu, co si myslí, že potřebují, a zapomenout téměř okamžitě po.

Chtěl bych každému poradit s touto otázkou, aby zkontroloval reflog (git reflog), ne o nic víc. Jakmile uvidíte, že seznam všech potvrzuje, existuje sto způsobů, jak zjistit, jaký závazek hledáte, a vybrat si z něj nebo vytvořit pobočku. V procesu jste se dozvěděli o reflogu a užitečných možnostech různých základních příkazů git.

11
RobbyD

Chci přidat k přijatému řešení další dobrý způsob, jak projít všemi změnami, když buď nemáte k dispozici gitk, nebo ne pro výstup X.

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

for h in `cat tmp_commits`; do git show $h | less; done

Pak se dostanete všechny rozdíly pro ty hashe zobrazeny jeden po druhém. Stiskem 'q' se dostanete k dalšímu rozdílu.

10
Phil

V jednoduchém příkazovém okně (Windows 7 v mém případě) jsem nemohl dostat žádnou z odpovědí na práci ve Windows. awk, grep a Select-string nebyly rozpoznány jako příkazy. Zkusil jsem jiný přístup:

  • první spuštění: git fsck --unreachable | findstr "commit"
  • kopírovat výstup do poznámkového bloku
  • najít nahrazení "nedosažitelný commit" pomocí start cmd /k git show

bude vypadat něco takového:

start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e

  • uložit jako soubor .bat a spustit jej
  • skript otevře spoustu příkazových oken, zobrazujících každý commit
  • pokud jste našli ten, který hledáte, spusťte: git stash apply (your hash)

nemusí být nejlepším řešením, ale pracoval pro mě

9
kromakollision

Tento nedostupný povel můžete vypsat zapsáním tohoto příkazu do terminálu -

git fsck --unreachable

Zkontrolovat nedostupný hash hash -

git show hash

Nakonec platí, pokud najdete skrytou položku -

git stash apply hash
9
Vivek Kumar

Přijatá odpověď Aristotlea ukáže všechny dosažitelné kompromisy, včetně kompromisů typu non-stash. Filtrování šumu:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3

To bude zahrnovat pouze provize, které mají přesně 3 rodičovské provize (které bude mít skrýš) a jejichž zpráva bude obsahovat "WIP on".

Mějte na paměti, že pokud jste uloženou zásilku uložili se zprávou (např. git stash save "My newly created stash"), přepíše se výchozí zpráva „WIP zapnuto ...“.

Můžete zobrazit více informací o každém potvrzení, např. zobrazit zprávu o potvrzení nebo ji předat git stash show:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3 | \
xargs -n1 -I '{}' bash -c "\
  git log -1 --format=medium --color=always '{}'; echo; \
  git stash show --color=always '{}'; echo; echo" | \
less -R
9
Brad Feehan

Obnoveno pomocí následujících kroků:

  1. Identifikovat smazaný hash kód:

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

  2. Cherry Vyberte Stash:

    git cherry-pick -m 1 $ stash_hash_code

  3. Vyřešte konflikty, pokud používáte:

    git mergetool

Pokud používáte gerrit, můžete mít navíc problémy se zprávou o potvrzení. Změňte své změny před následujícími alternativami:

  1. Použijte tvrdý reset na předchozí potvrzení a poté tuto změnu potvrďte.
  2. Můžete také skrýt změnu, rebase a znovu.
4
Abhijeet

Co jsem sem přišel hledat, je, jak se vlastně dostat skrýš zpět, bez ohledu na to, co jsem se odhlásil. Zejména jsem něco ukrýval, pak jsem si odhlásil starší verzi, pak to vyskočilo, ale ta skrýš byla v tomto časovém bodě ne-op, takže skrýš zmizel; Nemohl jsem prostě udělat git stash a zatlačit ho zpět do zásobníku. To fungovalo pro mě:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/[email protected]{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

Při zpětném pohledu jsem měl používat git stash apply ne git stash pop. Dělal jsem bisect a měl jsem malou patch, který jsem chtěl použít v každém kroku bisect. Teď to dělám:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.
4
Ben