Cum de a recupera un scăzut marfa in Git?

Eu folosesc frecvent git stash " și " git marfa pop pentru a salva și restabili schimbări în munca mea de copac. Ieri am avut unele schimbări în munca mea de copac pe care am ascuns-o și mi-a venit, și apoi am făcut mai multe modificări la munca mea de copac. Am'd place să mergeți înapoi și să revizuiască ieri's a ascuns schimbări, dar git marfa pop apare pentru a elimina toate trimiterile la asociat a comis-o.

Eu știu că dacă am folosi git stash apoi .git/ref/stash conține referință a comite folosit pentru a crea marfa. Și .git/busteni/ref/stash conține întreaga marfă. Dar aceste trimiteri sunt plecat după git marfa pop. Știu că a comis este încă în depozit pe undeva, dar eu nu't știu ce a fost.

Există o modalitate ușoară de a recupera ieri's stash comite de referință?

Rețineți că acest lucru nu e't critic pentru mine ziua de azi pentru ca am backup de zi cu zi și poate merge înapoi la ziua de ieri'e de lucru, copac să-mi aduc modificări. Am'm întreb pentru că acolo trebuie să fie o cale mai ușoară!

Comentarii la întrebare (3)
Soluția

Odată ce știi hash de marfa comis-ai scăpat, puteți aplica ca un stash:

git stash apply $stash_hash

Sau, puteți crea o ramură separată cu

git branch recovered $stash_hash

După aceea, poți să faci ce vrei cu instrumente normale. Când ați terminat, doar sufla-sucursala departe.

Găsirea hash

Dacă abia au apărut și terminalul este încă deschis, va încă mai au valoare hash tipărite de `git marfa pop de pe ecran (multumesc, Dolda).

În caz contrar, puteți găsi folosind acest lucru pentru Linux, Unix sau Git Bash pentru Windows:

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

...sau folosind Powershell pentru Windows:

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

Acest lucru vă va arăta toate se angajează la sfaturi de comite grafic care nu mai sunt referite de la orice sucursală sau tag – fiecare pierdut comis-o, inclusiv fiecare ascunde comis-ai creat vreodată, va fi undeva în grafic.

Cel mai simplu mod de a găsi ascunzătoarea comite vrei este probabil să treacă această listă gitk:

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

...sau vezi răspunsul la emragins dacă utilizați Powershell pentru Windows.

Acest lucru va lansa un depozit browser-ul care vă arată fiecare comite în depozit vreodată, indiferent dacă acesta este accesibil sau nu.

Puteți înlocui gitk acolo cu ceva de genulgit log-graficul-oneline --decora` dacă preferați un grafic frumos pe consola peste o separat GUI app.

La fața locului stash se angajează, uita-te pentru comiterea mesaje de acest formular:

        WIP pe somebranch: commithash Unele vechi comite mesaj

Notă: se angajeze mesaj va fi numai în această formă (începând cu "WIP pe") dacă nu a furnizat un mesaj cand ai facut `git rezerva.

Comentarii (23)

Dacă ai n't de aproape de terminal, doar uita-te la ieșire din git marfa pop și'll au ID-ul obiectului de aruncat marfa. În mod normal se pare ca acest lucru:

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

(Rețineți că `git marfa picătură, de asemenea, produce aceeași linie.)

Pentru a obține marfa înapoi, trebuie doar să rulați git branch tmp 2cae03e, și-ai'll să-l ca o ramură. Pentru a o converti la un depozit, a alerga:

git stash apply tmp
git stash

Având-o ca o ramură, de asemenea, vă permite să manipuleze în mod liber; de exemplu, pentru a alege sau a fuziona.

Comentarii (10)

Am vrut doar să menționez acest plus față de soluția acceptată. Nu a fost't imediat evident pentru mine prima data cand am incercat aceasta metoda (poate că ar trebui să-am fost), dar să se aplice marfa din valoarea hash, trebuie doar să utilizați "git marfa aplica ":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Când am fost noi la git, asta era't de clar pentru mine, și am încercat diferite combinații de "git show", "git se aplică", "patch-uri", etc.

Comentarii (1)

Pentru a obține lista de rezerve, care sunt încă în depozit, dar nu poate ajunge mai mult:

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

Dacă ți-a dat un titlu la stash dvs., înlocuiți "WIP" în -grep=WIP la sfârșitul comanda cu o parte din mesajul tau, de exemplu, - grep=Mozaic.

Comanda este grepping pentru "WIP" pentru că implicit comite mesaj pentru un depozit este în formă WIP pe mybranch: [anterior comiterii hash] Mesajul anterior a comis-o.

Comentarii (7)

Am construit o comanda care m-a ajutat să găsesc ascunzătoarea comite:

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

Acesta enumeră toate obiectele din .git/obiecte copac, localizează cele care sunt de tip comite, apoi afișează un rezumat pentru fiecare. Din acest punct a fost doar o chestiune de a privi prin care se angajează să găsească o adecvat "WIP la locul de muncă: 6a9bb2" ("munca" este ramura mea, 619bb2 este un recente comite).

Am act de faptul că, dacă am folosi "git marfa se aplică" în loc de "git marfa pop" I nu't au această problemă, și dacă am folosi "git marfa salva mesaj" apoi comite ar fi fost mai ușor de găsit.

Update: Cu Nathan's idee, acest lucru devine mai scurtă:

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

git fsck --neatins | grep comite ar trebui sa arate sha1, deși lista se întoarce s-ar putea fi destul de mare. git show <sha1> va arăta dacă este comis vrei.

git cherry-pick-m 1 <sha1> va fuziona comite pe ramură de curent.

Comentarii (1)

Dacă doriți să restash o pierdut marfa, aveți nevoie pentru a găsi hash a pierdut marfa în primul rând.

Ca și Aristotel Pagaltzis sugerat o git fsck ar trebui să te ajute.

Eu personal folosesc mi `log-toate alias-ul care arată-mi fiecare commit (recuperabile se angajează), pentru a avea o vedere mai bună a situației :

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

Puteți face o căutare chiar mai repede daca're în căutarea doar pentru "WIP pe" mesaje.

Odată ce-ți cunoști sha1, puteți schimba pur și simplu ascunde reflog pentru a adăuga vechi stash :

git update-ref refs/stash ed6721d

Te'll prefera, probabil, să aibă asociat un mesaj atât de un -m

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

Și tu'll chiar doriți să utilizați acest lucru ca un alias :

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

Windows PowerShell echivalente folosind gitk:

gitk-toate $(git fsck ... nu-reflog | Selectați-String "(marionetă comite )(.*)" | %{ $_.Linie.Split(&#39; &#39;)[2] })

Există, probabil, un mod mai eficient de a face acest lucru într-o singură țeavă, dar acest lucru are loc de muncă.

Comentarii (0)

Mi-a placut Aristotel's de abordare, dar nu't ca folosind GITK... ca am'm folosit pentru a folosind GIT de la linia de comandă.

În schimb, mi-am luat cununi de comite și de ieșire codul într-un fișier DIFF pentru revizuire în editorul de cod.

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

Acum aveți posibilitatea să încărcați până rezultat dif/fișier txt (în folderul acasă) în txt editor și vedea codul actual și rezultă SHA.

Apoi, utilizați doar

git stash apply ad38abbf76e26c803b27a6079348192d32f52219
Comentarii (0)

Puteți lista toate neatins comite prin scris această comandă în terminal

git fsck --unreachable

Verifica neatins comite hash -

git show hash

În cele din urmă se aplică dacă veți găsi ascuns element -

git stash apply hash
Comentarii (0)

De ce oamenii pun această întrebare? Pentru că ei don't știu sau înțeleg reflog.

Cele mai multe răspunsuri la această întrebare dă comenzi lungi cu opțiuni aproape nimeni nu va aminti. Așa că oamenii vin în această întrebare și copy paste orice cred ei că au nevoie și să uitați de el aproape imediat după.

I-aș sfătui pe toată lumea cu această întrebare pentru a verifica reflog (git reflog), nu cu mult mai mult decât asta. Odată ce ați vedea lista cu toate comite există o sută de moduri de a afla ce se angajeze're în căutarea pentru și de a alege sau de a crea o sucursală la ea. În procesul te'll au aflat despre reflog și opțiuni utile pentru diverse bază git comenzi.

Comentarii (3)

În OSX cu git v2.6.4, sunt doar git marfa picătură accidental, apoi am găsit-o printr-o troaca pașii de mai jos

Dacă știi numele de marfa apoi utilizați:

$ git fsck --neatins | grep comite | cut-c 20- | xargs git show | grep -B 6 -2 <numele de marfa>

în caz contrar, veți găsi ID-ul de rezultatul de manual cu:

$ git fsck --neatins | grep comite | cut-c 20- | xargs git show

Atunci când veți găsi comis-id lovit doar git marfa aplica {a comis-id}

Sper că acest lucru ajută cineva repede

Comentarii (0)

Vreau pentru a adăuga la soluția acceptată o altă modalitate buna de a merge prin toate modificările, atunci când nici nu't au gitk disponibile sau nu X pentru ieșire.

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

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

Atunci veți obține toate diff pentru cei hash-uri afișate una după alta. Apăsați 'q' pentru a ajunge la următoarea dif.

Comentarii (0)

Nu puteam't oricare dintre răspunsurile pentru a lucra pe Windows într-o simplă fereastră de comandă (Windows 7 in cazul meu). awk, grep " și " Selectați-string fost't recunoscut ca comenzi. Așa că am încercat o abordare diferită:

  • primul termen: git fsck --neatins | findstr exe "comit"
  • copie de ieșire la notepad
  • find replace "de neatins comite" cu start cmd /k git show

va arata ceva de genul asta:

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

  • salvare ca .bat fișierul și rulați-l
  • script-ul va deschide o gramada de comandă windows, care arată fiecare comite
  • dacă ați găsit unul care vă're în căutarea pentru, a alerga: git marfa se aplică (hash)

nu poate fi cea mai bună soluție, dar a lucrat pentru mine

Comentarii (1)

La răspunsul acceptat de către Aristotel va arăta toate accesibile comite, inclusiv non-marfa-ca comite. Pentru a filtra zgomotul:

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

Acest lucru va include doar se angajează, care au exact 3-mamă se angajează (pe care o marfa va avea), și al cărui mesaj include "WIP pe".

Păstrați în minte, că dacă ți-ai salvat marfa cu un mesaj (de exemplu, git marfa salva "Mea nou-create ascunde"), acest lucru va suprascrie implicit "WIP pe..." mesaj.

Puteți afișa mai multe informații despre fiecare comite, de exemplu, afișarea comite mesaj, sau se trece la git rezerva 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
Comentarii (0)

Preferata mea este aceasta o-liner:

git log --oneline  $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )

Aceasta este în esență aceeași idee ca acest răspuns dar mult mai scurt. Desigur, puteți adăuga încă --grafic pentru a obține un copac-cum ar fi de afișare.

Când ați găsit comite în listă, se aplică cu

git stash apply THE_COMMIT_HASH_FOUND

Pentru mine, folosind ... nu-reflogs a făcut dezvăluie pierdut stash de intrare, dar --neatins (cum se găsesc în multe alte răspunsuri) nu.

Rulați-l pe git bash, atunci când sunt sub Windows.

Credite: detalii despre comenzile de mai sus sunt luate de la https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf

Comentarii (0)

Ceea ce am venit aici în căutarea pentru este cum să obțineți de fapt marfa înapoi, indiferent de ceea ce am verificat. În special, am avut de ascuns ceva, apoi a verificat o versiune mai veche, apoi crucificat, dar marfa nu-op la asta mai devreme moment de timp, astfel încât marfa a dispărut; I n't doar git stash` să-l împingă înapoi pe stiva. Aceasta a lucrat pentru mine:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{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.

În retrospectivă, mi-ar fi fost folosind git marfa aplicanugit marfa pop. Am fost a face obisectoareași a avut un mic patch care am vrut să se aplice la fiecarebisectoarea` pas. Acum am'm a face acest lucru:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.
Comentarii (2)

L-a recuperat cu ajutorul următorii pași:

  1. Identificarea șters de rezerva cod hash:

gitk-toate $( git fsck ... nu-reflog | awk '/marionetă comite/ {print $3}' )

  1. Să-și Aleagă Marfa:

git cherry-pick-m 1 $stash_hash_code

  1. Rezolva Conflictele dacă utilizați:

git mergetool

În plus, s-ar putea fi având probleme cu comită mesaj dacă utilizați gerrit. Te rog Ascunde modificările înainte de a urma următoarele alternative:

  1. Utilizarea hard reset anterior a comis-o și apoi revenim la această schimbare.
  2. De asemenea, puteți ascunde schimba, rebazare și dedice.
Comentarii (1)