질문자 :Greg Hewgill
저는 작업 트리에서 변경 사항을 저장하고 복원하기 위해 git stash
및 git stash pop
을 자주 사용합니다. 어제 나는 작업 트리에 몇 가지 변경을 가했고, 그 다음에는 작업 트리에 더 많은 변경을 가했습니다. 돌아가서 어제의 숨긴 변경 사항을 검토하고 싶지만 git stash pop
은 연결된 커밋에 대한 모든 참조를 제거하는 것으로 보입니다.
git stash
를 사용하면 .git/refs/stash에 stash 를 만드는 데 사용된 커밋에 대한 참조가 포함된다는 것을 알고 있습니다. 그리고 .git/logs/refs/stash에는 전체 숨김이 포함되어 있습니다. 그러나 이러한 참조는 git stash pop
이후에 사라졌습니다. 커밋이 여전히 내 저장소 어딘가에 있다는 것을 알고 있지만 그것이 무엇인지 모르겠습니다.
어제의 숨김 커밋 참조를 복구하는 쉬운 방법이 있습니까?
매일 백업이 있고 변경 사항을 가져오기 위해 어제의 작업 트리로 돌아갈 수 있기 때문에 이것이 오늘 나에게 중요하지 않다는 점에 유의하십시오. 더 쉬운 방법이있을 것 같아서 묻습니다!
드롭한 stash 커밋의 해시를 알게 되면 이를 stash로 적용할 수 있습니다.
git stash apply $stash_hash
또는 다음을 사용하여 별도의 분기를 만들 수 있습니다.
git branch recovered $stash_hash
그 후에는 모든 일반 도구로 원하는 모든 작업을 수행할 수 있습니다. 끝나면 가지를 날려 버리십시오.
해시 찾기
방금 팝핑하고 터미널이 여전히 열려 git stash pop
에 의해 인쇄된 해시 값이 계속 표시됩니다 (Dolda에게 감사드립니다).
그렇지 않으면 Linux, Unix 또는 Windows용 Git Bash에서 다음을 사용하여 찾을 수 있습니다.
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
...또는 Windows용 Powershell 사용:
git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }
이렇게 하면 더 이상 분기나 태그에서 참조되지 않는 커밋 그래프의 끝 부분에 있는 모든 커밋이 표시됩니다. 생성한 모든 stash 커밋을 포함하여 모든 손실된 커밋은 해당 그래프의 어딘가에 있을 것입니다.
원하는 숨김 커밋을 찾는 가장 쉬운 방법은 아마도 해당 목록을 gitk
에 전달하는 것입니다.
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
...또는 Windows용 Powershell을 사용하는 경우 emragins의 답변을 참조하세요.
이렇게 하면 도달 가능한지 여부에 관계없이 리포지토리의 모든 단일 커밋을 보여주는 리포지토리 브라우저가 시작됩니다.
별도의 GUI 앱보다 콘솔의 멋진 그래프를 선호하는 경우 git log --graph --oneline --decorate
와 같은 gitk
를 대체할 수 있습니다.
숨김 커밋을 찾으려면 다음 형식의 커밋 메시지를 찾으십시오.
WIP on somebranch : commithash 일부 오래된 커밋 메시지
참고 git stash
를 수행할 때 메시지를 제공하지 않은 경우에만 이 형식("WIP on"으로 시작)으로 표시됩니다.
Aristotle Pagaltzis터미널을 닫지 않은 경우 git stash pop
의 출력을 보면 드롭된 stash의 개체 ID가 표시됩니다. 일반적으로 다음과 같습니다.
$ git stash pop [...] Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)
( git stash drop
도 같은 줄을 생성합니다.)
해당 숨김을 다시 얻으려면 git branch tmp 2cae03e
실행하면 됩니다. 그러면 분기로 얻을 수 있습니다. 이것을 숨김으로 변환하려면 다음을 실행하십시오.
git stash apply tmp git stash
분기로 사용하면 자유롭게 조작할 수도 있습니다. 예를 들어 체리를 선택하거나 병합합니다.
Dolda2000허용된 솔루션에 이 추가 사항을 언급하고 싶었습니다. 이 방법을 처음 시도했을 때 즉시 명확하지 않았지만(아마도 그랬어야 함) 해시 값에서 숨김을 적용하려면 "git stash apply"를 사용하면 됩니다.
$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219
내가 git을 처음 접했을 때 이것은 나에게 명확하지 않았고 "git show", "git apply", "patch" 등의 다른 조합을 시도하고 있었습니다.
Wade아직 저장소에 있지만 더 이상 연결할 수 없는 숨김 목록을 가져오려면:
git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP
숨김에 제목을 지정한 경우 명령 끝의 -grep=WIP
-grep=Tesselation
.
숨김에 대한 기본 커밋 메시지가 mybranch의 WIP 형식이기 때문에 명령은 "WIP"에 대해 grepping입니다 WIP on mybranch: [previous-commit-hash] Message of the previous commit.
Senthil A Kumar방금 잃어버린 숨김 커밋을 찾는 데 도움이되는 명령을 구성했습니다.
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
이것은 .git/objects 트리의 모든 객체를 나열하고 커밋 유형의 객체를 찾은 다음 각 객체의 요약을 표시합니다. 이 시점에서 적절한 "WIP on work: 6a9bb2"를 찾기 위해 커밋을 살펴보는 문제였습니다("work"는 제 브랜치이고 619bb2는 최근 커밋입니다).
"git stash pop" 대신 "git stash apply"를 사용하면 이 문제가 발생하지 않으며 "git stash save message "를 사용하면 커밋을 더 쉽게 찾을 수 있습니다.
업데이트: Nathan의 아이디어로 이것은 더 짧아집니다.
for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
Greg Hewgillgitk를 사용하는 Windows PowerShell에 해당:
gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })
하나의 파이프에서 이 작업을 수행하는 더 효율적인 방법이 있을 수 있지만 이것이 제대로 작동합니다.
emraginsgit fsck --unreachable | grep commit
은 sha1을 표시해야 하지만 반환하는 목록은 상당히 클 수 있습니다. git show <sha1>
원하는 커밋인지 표시합니다.
git cherry-pick -m 1 <sha1>
은 커밋을 현재 분기에 병합합니다.
Nathan Jones잃어버린 보관함을 다시 보관하려면 먼저 잃어버린 보관함의 해시를 찾아야 합니다.
Aristotle Pagaltzis가 제안한 대로 git fsck
가 도움이 될 것입니다.
개인적으로 나는 상황을 더 잘 볼 수 있도록 모든 커밋(복구 가능한 커밋)을 보여주는 log-all
git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)
"WIP on" 메시지만 찾는 경우 더 빠른 검색을 수행할 수 있습니다.
sha1을 알면 stash reflog를 변경하여 이전 stash를 추가하기만 하면 됩니다.
git update-ref refs/stash ed6721d
아마도 관련 메시지를 선호할 것이므로 -m
git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d
그리고 이것을 별칭으로 사용하고 싶을 수도 있습니다.
restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1
Colin Hebert터미널에서 이 명령을 작성하여 연결할 수 없는 모든 커밋을 나열할 수 있습니다.
git fsck --unreachable
연결할 수 없는 커밋 해시 확인 -
git show hash
마지막으로 숨겨진 아이템을 찾으면 신청하세요~
git stash apply hash
Vivek Kumar나는 Aristotle의 접근 방식을 좋아했지만 GITK를 사용하는 것을 좋아하지 않았습니다... 명령줄에서 GIT를 사용하는 데 익숙했기 때문입니다.
대신, 매달린 커밋을 가져와서 코드 편집기에서 검토할 수 있도록 코드를 DIFF 파일로 출력했습니다.
git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff
이제 결과 diff/txt 파일(홈 폴더에 있음)을 txt 편집기에 로드하고 실제 코드와 결과 SHA를 볼 수 있습니다.
그럼 그냥 사용
git stash apply ad38abbf76e26c803b27a6079348192d32f52219
Shaheen Ghiassygit v2.6.4가 설치된 OSX에서 실수로 git stash drop을 실행한 다음 아래 단계로 이동하여 찾았습니다.
숨김의 이름을 알고 있으면 다음을 사용하십시오.
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>
그렇지 않으면 다음을 사용하여 수동으로 결과에서 ID를 찾을 수 있습니다.
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show
그런 다음 commit-id를 찾으면 git stash apply {commit-id}를 누르십시오.
이것이 누군가를 빨리 돕기를 바랍니다.
Can Tecim내가 가장 좋아하는 것은 이 한 줄짜리입니다.
git log --oneline $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )
이것은 기본적으로 이 답변 과 동일한 아이디어이지만 훨씬 짧습니다. 물론 --graph
를 추가하여 나무와 같은 디스플레이를 얻을 수 있습니다.
목록에서 커밋을 찾으면 다음을 사용하여 적용하십시오.
git stash apply THE_COMMIT_HASH_FOUND
나에게 --no-reflogs
사용하면 잃어버린 숨김 항목이 표시되었지만 --unreachable
(다른 많은 답변에서 볼 수 있듯이)은 표시되지 않았습니다.
Windows를 사용 중일 때 git bash에서 실행하십시오.
크레딧: 위 명령에 대한 세부 정보는 https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf에서 가져왔습니다.
Adrian W사람들은 왜 이런 질문을 할까요? 그들은 아직 reflog에 대해 알지 못하거나 이해하지 못하기 때문입니다.
이 질문에 대한 대부분의 답변은 거의 아무도 기억하지 못할 옵션이 포함된 긴 명령을 제공합니다. 그래서 사람들은 이 질문에 와서 필요하다고 생각하는 것을 복사하여 붙여넣고 거의 즉시 잊어버립니다.
이 질문이 있는 모든 사람에게 reflog(git reflog)를 확인하는 것이 좋습니다. 그 이상은 아닙니다. 모든 커밋 목록을 보면 찾고 있는 커밋을 찾아 선택하거나 브랜치를 만드는 100가지 방법이 있습니다. 이 과정에서 reflog와 다양한 기본 git 명령에 대한 유용한 옵션에 대해 배웠습니다.
RobbyD간단한 명령 창(제 경우에는 Windows 7)에서 Windows에서 작동하는 답변을 얻을 수 없었습니다. awk
, grep
및 Select-string
은 명령으로 인식되지 않았습니다. 그래서 다른 접근 방식을 시도했습니다.
- 첫 번째 실행:
git fsck --unreachable | findstr "commit"
- 출력을 메모장에 복사
- "unreachable commit"을
start cmd /k git show
다음과 같이 보일 것입니다:
start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e
- .bat 파일로 저장하고 실행
- 스크립트는 각 커밋을 보여주는 많은 명령 창을 엽니다.
- 찾고 있는 것을 찾았다면 다음을 실행하십시오:
git stash apply (your hash)
최선의 해결책은 아니지만 나를 위해 일했습니다.
Koen사용 가능한 gitk가 없거나 출력용 X가 없을 때 모든 변경 사항을 처리할 수 있는 또 다른 좋은 방법을 허용된 솔루션에 추가하고 싶습니다.
git fsck --no-reflog | awk '/dangling commit/ {print $3}' > tmp_commits for h in `cat tmp_commits`; do git show $h | less; done
그런 다음 해당 해시에 대한 모든 diff가 차례로 표시됩니다. 다음 diff로 이동하려면 'q'를 누르십시오.
PhilAristotle이 수락한 답변은 비-stash-like 커밋을 포함하여 도달 가능한 모든 커밋을 보여줍니다. 노이즈를 필터링하려면:
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
여기에는 정확히 3개의 상위 커밋(stash에 있음)이 있고 메시지에 "WIP on"이 포함된 커밋만 포함됩니다.
메시지와 함께 숨김을 저장한 경우(예: git stash save "My newly created stash"
) 기본 "WIP on..." 메시지가 무시됩니다.
각 커밋에 대한 자세한 정보를 표시할 수 있습니다. 예를 들어 커밋 메시지를 표시하거나 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
Brad Feehan간단한 2단계로 이를 달성할 수 있습니다.
잃어버린 은닉 목록 --> 모든 은닉이 휴지통에 들어간 프로젝트에 대해 이 명령을 실행합니다.
git fsck --연결 불가능 | 그렙 커밋 | 컷 -d ' ' -f3 | xargs git log --merge --no-walk
잃어버린 은닉을 원래 위치로 되돌려 보내십시오 --> 두 번째 은닉의 커밋 해시를 사용합시다.
git update-ref refs/stash 4b3fc45c94caadcc87d783064624585c194f4be8 -m "복구된 보관함"
Abhi다음 단계를 사용하여 복구했습니다.
삭제된 숨김 해시 코드를 식별합니다.
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
체리 선택 보관함:
자식 체리 선택 -m 1 $stash_hash_code
다음을 사용하여 충돌이 있는 경우 해결:
자식 병합 도구
또한 gerrit를 사용하는 경우 커밋 메시지에 문제가 있을 수 있습니다. 다음 대안을 따르기 전에 변경 사항을 저장하십시오.
- 이전 커밋으로 하드 리셋을 사용한 다음 이 변경 사항을 다시 커밋합니다.
- 변경 사항을 숨기고 리베이스하고 다시 커밋할 수도 있습니다.
Abhijeet내가 여기에서 찾은 것은 내가 체크아웃한 것과 상관없이 실제로 은닉물을 되찾는 방법입니다. 특히, 나는 무언가를 숨긴 다음 이전 버전을 체크 아웃 한 다음 팝업했지만 이전 시점에서는 숨김이 작동하지 않았으므로 숨김이 사라졌습니다. 스택에 다시 푸시하기 git stash
를 할 수는 없었습니다. 이것은 나를 위해 일했습니다.
$ 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.
git stash pop
아닌 git stash apply
사용했어야 했습니다. 나는 bisect
bisect
단계에서 적용하고 싶은 작은 패치가 있었습니다. 지금 나는 이것을하고있다 :
$ git reset --hard; git bisect good; git stash apply $ # Run tests $ git reset --hard; git bisect bad; git stash apply etc.
Bengit fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP
이것을 한 번 시도하십시오
Kostandin Vllahu터미널에서 커밋을 보려면 관심 있는 항목만 필터링하면 됩니다.
git log --oneline --all --grep="^WIP on .*: [a-f0-9]\+" --grep="^On [^ ]*:" --grep="^index on [^ ]*:" $( env LANG=C git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
이것은 Aristotle Pagaltzis 답변을 기반으로합니다.
Treviño아래 프로세스를 단계별로 따를 수 있습니다.
1- 도달할 수 없는 모든 커밋을 나열하려면 아래를 사용하십시오. git fsck --unreachable
2- git show hash로 연결할 수 없는 커밋 해시 표시
3- 모든 로그를 복사하면 도달할 수 없는 blob, 커밋, 트리와 같은 로그를 볼 수 있습니다.
4- 커밋 해시가 있는 로그와 함께 git stash 적용 git stash apply [해시 교체]
Lovekush Vishwakarma출처 : http:www.stackoverflow.com/questions/89332/how-to-recover-a-dropped-stash-in-git