Git에서 삭제 한 지점을 복구 할 수 있습니까?


1066

를 실행 git branch -d XYZ하면 지점을 복구하는 방법이 있습니까? delete branch 명령을 실행하지 않은 것처럼 되돌아 갈 수있는 방법이 있습니까?


4
허용 된 답변에 대해 정말 멋진 메모는 지점이 원래 삭제 된 경우에도 작동한다는 것입니다! 실수로 원산지가 삭제 된 후 더 이상 로컬에 없었던 여러 지점을 복구했습니다.
theblang

답변:


1955

예, git reflog삭제 된 분기의 끝에서 커밋에 대한 SHA1 을 수행 하고 찾을 수 있어야합니다 git checkout [sha]. 일단 커밋 git checkout -b [branchname]을 마치면 지점을 다시 만들 수 있습니다 .


이 압축 형 / 한-라이너 버전에 대해서는 @Cascabel이 제공합니다.

한 단계로 수행 할 수 있습니다.

git checkout -b <branch> <sha>

477
한 단계로 수행 할 수 있습니다 git checkout -b <branch> <sha>..
Cascabel

200
빠른 팁-지점을 방금 삭제 한 경우 터미널에 "삭제 된 지점 <your-branch> (이 <sha>)"가 표시됩니다. 그리고 아주 쉬운 방법입니다 <sha>. 그냥 사용하십시오 . 예 : 위에서 언급 한대로 –git checkout -b <branch> <sha>
Snowcrash

6
예, 터미널에서 위로 스크롤하면됩니다 (네가하지 않는 한 CMD+K)
neaumusic

42
기본적으로 축약되는 git reflog --no-abbrev전체를 보려면 사용 하십시오 <sha>.
jkulak

5
나 같은 사람은 삭제 된 지점의 그늘을 찾는 데 어려움을 겪었습니다 git checkout remotes/origin/deleted_branch.
Jeff Irwin

161

도달 할 수없는 커밋은 대부분 reflog에 있습니다. 따라서 가장 먼저 시도해야 할 것은 명령을 사용하여 reflog를 보는 것입니다 (에 대한 refloggit reflog표시 함 HEAD).

커밋이 여전히 존재하는 특정 브랜치의 일부인 경우 더 쉬운 방법은 명령을 사용하는 것 git reflog name-of-my-branch입니다. 당신이 밀어 강제 경우는 예를 들어, 리모컨으로도 작동합니다 (추가 조언 : 항상 선호하는 git push --force-with-lease더 나은 실수를 방지하고 더 복구 할 것을 대신).


커밋이 reflog에없는 경우 (아마도 reflog 에 쓰지 않는 타사 도구에 의해 삭제 되었기 때문에) 그런 명령을 사용하여 찾은 커밋의 sha로 분기를 재설정하여 분기를 성공적으로 복구했습니다. 모든 매달려있는 커밋으로 파일을 만듭니다) :

git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

두 번 이상 사용해야하거나 어딘가에 저장하려면 해당 명령으로 별칭을 만들 수도 있습니다 ...

git config --global alias.rescue '!git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt'

와 함께 사용 git rescue

찾은 커밋을 조사하기 위해 일부 명령을 사용하여 커밋을 표시 할 수 있습니다.

커밋 메타 데이터 (작성자, 작성 날짜 및 커밋 메시지)를 표시하려면

git cat-file -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

diff도 보려면 :

git log -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

커밋을 찾았 으면 다음과 같이 커밋에 대한 분기를 만듭니다.

git branch commit_rescued 48540dfa438ad8e442b18e57a5a255c0ecad0560

Windows 하에서 GUI를 좋아 하는 사용자의 경우 => => 기능을 사용하여 GitExtensions 를 사용하여 커밋 (및 커밋되지 않은 스테이징 파일)을 쉽게 복구 할 수 있습니다RepositoryGit maintenanceRecover lost objects...


삭제 된 준비된 파일을 쉽게 복구하는 비슷한 명령 : https://stackoverflow.com/a/58853981/717372


2
큰 도움. 지역 리포지토리에는 없었던 커밋이 없어졌습니다. 첫 번째 명령은 서버에서 찾도록 도와주었습니다. +1
Sean Adkinson 2016 년

1
그 자식 구조 별칭은 신의 선물입니다! 기여해 주셔서 감사합니다!
72A12F4E

2
당신은 내 생명을 구했습니다.
Jed Lynch

Patrick Koorevaar의 답변은 마지막으로 삭제 된 분기 커밋 <sha>을 모르기 때문에 도움이되었습니다.
Monir Khan

@ 모니르 칸 그리고? 무엇을 결론을 내립니까? Patrick의 대답은 단지 내 명령의 복사 / 붙여 넣기입니다 (오류 : 커밋을 필터링하는 것을 잊어 버렸습니다).
Philippe

45

GUI를 사용하려면 gitk를 사용하여 전체 작업을 수행 할 수 있습니다.

gitk --reflog

이렇게하면 분기가 삭제되지 않은 것처럼 분기의 커밋 기록을 볼 수 있습니다. 이제 가장 최근 지점에 대한 커밋을 마우스 오른쪽 버튼으로 클릭하고 메뉴 옵션을 선택하십시오 Create new branch.


28

가장 많이 투표 된 솔루션은 실제로 요청 된 것보다 많은 기능을 수행합니다.

git checkout <sha>
git checkout -b <branch>

또는

git checkout -b <branch> <sha>

커밋을 잊어 버린 모든 최근 변경 사항과 함께 새 지점으로 이동하십시오. 특히 브랜치를 잃은 후 "패닉 모드"에있을 때는 의도하지 않을 수 있습니다.

깨끗하고 간단한 솔루션 은 one-liner 인 것처럼 보입니다 ( <sha>with 를 찾은 후 git reflog).

git branch <branch> <sha>

현재 지점이나 커밋되지 않은 변경 사항은 영향을받지 않습니다. 대신에 새 분기 만 생성됩니다 <sha>.

팁이 아닌 경우에도 여전히 작동하며 더 짧은 지점을 얻게 <sha>되며 새 지점 이름으로 다시 시도 할 수 있습니다 .

마지막으로 성공적으로 복원 된 분기의 이름을 다른 이름으로 바꿀 수 있습니다.

git branch -m <restored branch> <final branch>

말할 것도없이, 성공의 열쇠는 올바른 커밋을 찾는 것이 었 <sha>으므로 커밋의 이름을 현명하게 지정하십시오. :)


14

tfe answer 추가 : git-resurrect.sh 스크립트 contrib/는 Git 소스 영역 (git.git 리포지토리에 있음)에 도움이 될 수 있습니다.

git-resurrect <name>이라는 분기 팁의 흔적을 찾으려고 <name>시도하여 부활 시키려고합니다. 현재 reflog에서 체크 아웃 메시지와 -r병합 메시지를 검색 합니다. -m및을 사용하면 -t모든 심판의 기록이 Merge <name> into other/ Merge <other> into <name>(각각) 커밋 주제를 스캔하여 다소 느리지 만 다른 사람들의 주제 분기를 부활시킬 수 있습니다.


1
/ usr / lib / git-core /를 PATH에 추가해야했지만 지금은 나를 위해 일했습니다. 그러나 그것은 내가
바랐던

10

다음 명령을 사용하여 삭제 된 분기를 찾아서 검색했습니다. 첫 번째 단계는 gcb의 설명입니다.

$ git fsck --full --no-reflogs --unreachable --lost-found > lost
$ cat lost | cut -d\  -f3 > commits
$ cat commits | xargs -n 1 git log -n 1 --pretty=oneline

이제 커밋 주석을 기반으로 git commit id (GIT-SHA)를 찾아서 아래 명령에서 사용하십시오. 이전에 찾은 GIT-SHA로 NEW-BRANCH라는 새 지점을 체크 아웃하십시오.

$ git checkout -b NEW-BRANCH GIT-SHA

대단히 감사합니다. 이름을 검색하는 데 약간의 시간이 걸렸지 만 그만한 가치가 있습니다. 커밋 메시지 문자열을 검색하는 방법이 있다면 훨씬 좋습니다.
Monir Khan

9

리플 로그가없는 경우 (예 : reflog를 사용하지 않는 Bare Repository에서 작업 중이고 복구하려는 커밋이 최근에 생성 되었기 때문에 다른 옵션은 최근에 생성 된 커밋 객체를 찾아서 살펴 보는 것입니다.

.git/objects디렉토리 내부에서 다음을 실행하십시오.

find . -ctime -12h -type f | sed 's/[./]//g' | git cat-file --batch-check | grep commit

지난 12 시간 동안 생성 된 모든 객체 (커밋, 파일, 태그 등)를 찾아 커밋 만 표시하도록 필터링합니다. 이를 확인하는 것은 빠른 과정입니다.

Jakub의 답변에 언급 된 git-ressurect.sh 스크립트를 먼저 시도해보십시오 .


1
좋은 대안 아이디어! 그래도 명령에 오류가 발생합니다. 문제는 "12h"부분 (실제로 "h")에 있습니다. "h"를 제거하면 정상적으로 작동합니다. 보낸 사람 man find: "-ctime n-파일 상태가 n * 24 시간 전에 마지막으로 변경되었습니다." 따라서 지난 12 시간 동안 예상되는 동작을 갖도록 12에서 0.5로 변경해야합니다.
pagliuca

1
여기서 OS X 10.8을 사용하고 있으므로 위의 '찾기'플래그는 제공되는 버전을 기반으로합니다.
Robert Knight

1
네, 문제가 버전에 있는지 확인하십시오! 그래서 나는 당신의 대답을 처음부터 찬성했습니다! 방금 사람들이 매개 변수가 다를 수 있음을 알았습니다.
pagliuca

9

들어 GitHub의 힘내없는 사용자가 설치 :

GitHub 웹 사이트 에서 복원 하려면 해당 API사용하여 리포 관련 이벤트 목록을 얻을 수 있습니다.

먼저

  • 해당 SHA 찾기 (커밋 해시) :

    curl -i https://api.github.com/repos/PublicUser/PublicRepo/events

    ... 또는 개인 저장소 :

    curl -su YourUserName https://api.github.com/repos/YourUserName/YourProject/events

    (GitHub 비밀번호를 묻는 메시지가 나타납니다)

    • 리포지토리에 2 단계 인증이 필요한 경우 아래에서이 답변에 대한 의견을 참조하십시오.

다음

  • GitHub 로 이동하여 새로운 임시 브랜치를 생성하십시오.이 지점은 영원히 삭제됩니다 ( Chrome 이 바람직합니다).

   • 지점으로 이동하여 삭제하십시오.

   •   같은 페이지에서 다시로드하지 않고 DevTools, 네트워크 패널을 엽니 다. 이제 준비하십시오 ...

   • 복원을 클릭하십시오. 새로운 "라인"을 볼 수 있습니다. 마우스 오른쪽 버튼으로 클릭하고 "cURL로 복사"를 선택하고이 텍스트를 편집기에 저장하십시오.

   • 복사 된 코드 줄 끝에 다음을 추가하십시오 -H "Cookie=".

이제 다음과 같은 것을 얻을 수 있습니다 :

    curl 'https://github.com/UserName/ProjectName/branches?branch=BranchSHA&name=BranchName' -H 'Cookie:' -H 'Origin: https://github.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US' -H 'User-Agent: User-Agent' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Accept: */*' -H 'Referer: https://github.com/UserName/ProjectName/branches' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --data 'utf8=%E2%9C%93&authenticity_token=token' --compressed

마지막 단계

  • "BranchSHA"를 SHA-hash로 바꾸고 BranchName을 원하는 이름으로 바꿉니다 (BTW, 웹에서 지점의 이름을 바꾸는 것이 좋습니다). 당신이 너무 느리지 않은 경우, 당신은 어쨌든이 요청을해야합니다. 예를 들어 터미널에 복사하여 붙여 넣기 만하면됩니다.

추신

이것이 "가장 간단한 솔루션"이나 "올바른"솔루션이 아닐 수도 있지만 누군가 유용하다고 생각되는 경우에 제공됩니다.


1
위의 내용은 의존하지 않는 몇 가지 중 하나 git reflog이므로 예를 들어 원격 지점을 삭제하고에서 수행 한 컴퓨터에 대한 액세스 권한을 잃어 버렸을 때 유용했습니다 reflog. 참고 때 Github에서의 OAuth에 또는 이중 인증을 사용하여curl 명령의 형식이된다 : curl -u username:token https://api.github.com/user또는curl -H "Authorization: token TOKEN" https://api.github.com/repos/USER_OR_ORG_NAME/REPO_NAME/events
TT--

@ TT-- 와우, 도와 줘서 다행입니다! 과에 대한 귀하의 기여에 감사 인증 토큰 :
맥심 Mazurok

8

다른 지점에서 삭제할 지점에 도달 할 수 있는지 이해하면 다음을 사용하여 안전하게 삭제할 수 있습니다

git branch -d [branch]

그리고 당신의 작업은 손실되지 않습니다. 브랜치는 스냅 샷이 아니라 그에 대한 포인터입니다. 따라서 분기를 삭제하면 포인터가 삭제됩니다.

다른 지점에 도달 할 수없는 지점을 삭제해도 작업이 손실되지 않습니다. 물론 커밋 해시를 확인하는 것만 큼 쉽지는 않지만 여전히 할 수는 있습니다. 그래서 Git은을 사용하여 도달 할 수없는 분기를 삭제할 수 없습니다 -d. 대신에 사용해야합니다

git branch -D [branch]

이것은 Scott Chacon의 Git에 관한 비디오를 반드시 봐야하는 부분입니다. 지점에 대해 이야기 할 때 58:00 분을 확인하고 삭제하는 방법을 확인하십시오.

GitHub의 Scott Chacon과 함께 Git 소개


7
이것이 어떻게 질문에 대답하는 데 도움이됩니까?
Dmitri Zaitsev

6
지점에 내용을 보유하지 않지만 실제로는 포인터라고 묻는다. 브랜치를 삭제하는 것을 두려워 할 필요는 없습니다. 삭제 된 브랜치와 같은 커밋을 가리키는 새 브랜치를 만들 수 있습니다. 와우! 나는이 질문을 할 때 여전히 기억합니다. 2012 년으로 거슬러 올라갑니다!
fabiopagoti

1
마지막으로 세 화면을 스크롤하여 문제를 해결 한 답변을 찾으십시오. 분기를 삭제하면 단순한 포인터가 삭제됩니다. 여기서 데이터 손실 상황이 없으며 복구해야 할 유일한 것은 그것이 가리키는 위치입니다. 직접가는 답변 reflog은 과잉입니다.
RomainValeri

5

Bitbucket Cloud로 이동하기 전에이 모든 것을 로컬에서 수행하고 리포지토리가 원하는 상태인지 확인하십시오. 현재 저장소를 복제하고 이러한 솔루션을 먼저 테스트하는 것이 좋습니다.

  1. 지점을 방금 삭제 한 경우 터미널에 다음과 같은 내용이 표시됩니다.
    Deleted branch <your-branch> (was <sha>)

분기를 복원하려면 다음을 사용하십시오.

    git checkout -b <branch> <sha>

머리 꼭대기의 '샤'를 모르는 경우 다음을 수행 할 수 있습니다.

  1. 다음을 사용하여 삭제 된 분기의 끝에서 커밋의 'sha'를 찾으십시오.
    git reflog
  1. 브랜치를 복원하려면 다음을 사용하십시오.
    git checkout -b <branch> <sha>

커밋이 참조 로그에없는 경우 :

  1. 다음과 같은 명령을 사용하여 발견 한 커밋의 sha로 분기를 재설정하여 분기를 복구 할 수 있습니다.
    git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

2. 다음 중 하나를 사용하여 각 커밋을 표시 할 수 있습니다.

    git log -p <commit>
    git cat-file -p <commit>

4

삭제 된 분기를 복구하려면 먼저 참조 기록을 살펴보고

git reflog -n 60

여기서 n은 마지막 n 커밋을 나타냅니다. 그런 다음 적절한 머리를 찾아 그 머리로 가지를 만듭니다.

git branch testbranch HEAD@{30}

4

나는 원치 않는 커밋을 지우려고 원격에서 브랜치를 리베이스하고 내가 원하는 올바른 커밋을 선택했습니다. 물론 SHA를 잘못 썼습니다 ...

다음은 내가 찾은 방법입니다 (대부분 대답에 대한 인터페이스 / 상호 작용이 더 쉽습니다).

먼저 로그에 느슨한 커밋 목록을 생성하십시오. 가비지 수집기에 의해 덤프 될 수 있으므로 가능한 빨리이 작업을 수행하고 작동을 중지하십시오.

git fsck --full --no-reflogs --unreachable --lost-found > lost

이것은 lost당신이보아야 할 모든 커밋 이있는 파일을 만듭니다 . 우리의 삶을 단순화하기 위해 SHA 만 잘라 봅시다.

cat lost | cut -d\  -f3 > commits

이제 commits커밋해야 할 모든 커밋 이있는 파일이 생겼습니다.

Bash를 사용한다고 가정하면 마지막 단계는 다음과 같습니다.

for c in `cat commits`; do  git show $c; read; done

이것은 각각의 diff와 commit 정보를 보여줄 것입니다. 그리고을 누를 때까지 기다립니다 Enter. 이제 원하는 것을 모두 적어 놓고 체리 픽 (pick-pick)하세요. 완료 후 Ctrl-C 만하면됩니다.



1

먼저 git batch로 이동하여 다음과 같이 프로젝트로 이동하십시오.

cd android studio project
cd Myproject
then type :
git reflog

모든 변경 사항 목록이 있으며 참조 번호는 심판 번호를 가져 와서
안드로이드 스튜디오 또는 git betcha에서 체크 아웃 합니다. 다른 솔루션은 심판 번호를 가져 와서 안드로이드 스튜디오로 이동하여 git branches를 클릭 한 다음 체크 아웃 태그 또는 참조 번호를 지난 개정을 클릭하면 분기가 있습니다.


1

tfe의 답변에 추가하면 커밋이 가비지 수집되지 않는 한이 프로세스를 사용하여 복구 할 수 있습니다. 힘내 분기는 단순히 커밋 트리에서 특정 커밋에 대한 포인터입니다. 그러나 포인터를 삭제하고 해당 브랜치의 커밋이 기존의 다른 브랜치로 병합되지 않으면 git 은이를 커밋 수집으로 처리하고 가비지 수집 중에 제거하여 주기적으로 자동으로 실행될 수 있습니다.

브랜치가 기존 브랜치에 병합되지 않았고 가비지 수집 된 경우 브랜치가 기존 브랜치에서 분기 된 시점까지 모든 커밋이 느슨해집니다.


1

관련 문제 : "삭제 된 분기를 확인하는 방법"을 검색 한 후이 페이지를 방문했습니다.

많은 오래된 지점을 삭제하는 동안 실수로 새로운 지점 중 하나를 삭제했지만 복구 할 이름을 몰랐습니다.

최근에 삭제 된 분기를 확인하려면 다음을 수행하십시오.

Git URL로 가면 다음과 같이 보입니다.

https://your-website-name/orgs/your-org-name/dashboard

그러면 최근 과거에 삭제 한 내용의 피드를 볼 수 있습니다.


확실한. 위의 답변은 GitHub에 대한 것입니다. 로컬로 GitHub를 설치했습니다. 질문 해 주셔서 감사합니다.
Manohar Reddy Poreddy

1

지점을 삭제하는 컴퓨터 에서이 작업을 수행했습니다.

git reflog

응답:

74b2383 (develope) HEAD@{1}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{2}: checkout: moving from develope to master
74b2383 (develope) HEAD@{3}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{4}: reset: moving to HEAD
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{5}: clone: from http://LOCALGITSERVER/myBigProject/Android.git

이 명령으로 지점을 검색합니다.

git checkout -b newBranchName 74b2383


0

그냥 사용 git reflog하면 sha나를 위해 돌아 오지 않았습니다 . 오직commit id (8 개 문자 길이와 샤 인 방법 이상)

그래서 나는 git reflog --no-abbrev

그런 다음 위에서 언급 한 것과 동일하게 수행하십시오. git checkout -b <branch> <sha>


당신은 항상 약식 8 문자 샤를 사용할 수 있습니다, 당신은 전체 샤를 사용할 필요가 없습니다
Michael Dreher

0

당신이 ... VSCode를 사용하는 경우 당신은 그것을 삭제하기 전에 어떤 점에서 서버와 지사를 동기화 ...

자식 분기 삭제는 서버의 복사본이 아닌 로컬 복사본 만 삭제합니다. 먼저 Git 패널 (왼쪽 툴바의 git 아이콘)에서 분기를 살펴보고 분기가 "origin / your_branch_name"아래에 있는지 확인하십시오. 그렇다면 해당 코드를 선택하면 코드를 다시 가져와야합니다 (다른 곳에서 즉시 복사 / 붙여 넣기 / 저장하는 것이 좋습니다).

"origin / your_branch_name"이 표시되지 않으면 GitLens 확장을 설치하십시오. 이를 통해 서버 리포지토리를 시각적으로 탐색하고 서버와 동기화 된 복사본을 찾을 수 있습니다. 리포지토리가 여러 개인 경우 리포지토리를 GitLens에 표시하려면 원하는 리포지토리에서 파일을 하나 이상 열어야 할 수도 있습니다. 그때:

  1. GitLens 패널을 엽니 다

  2. 저장소를 확장하십시오

  3. 카테고리 / 기여자 / 리모트 / 스 태쉬 / 등의 카테고리 목록이 표시되어야합니다.

"지점"또는 "원격-> 출처"에서 YourLostTreasure를 찾으십시오. 바라건대, 원하는 이름의 브랜치를 보게 될 것입니다. 확장하면 브랜치에서 변경된 파일을 볼 수 있습니다. 파일 이름을 두 번 클릭하여 연 다음 해당 코드를 즉시 백업하십시오.

잃어버린 지점을 즉시 보지 못하면 주위를 찌르고 유망한 것을 발견하면 즉시 열어서 코드를 가져옵니다. TheGoldenBranch를 찾을 때까지 꽤 많이 찔렀다가 심지어 코드가 마지막 하나 또는 두 개의 저장을 누락했습니다 (아마도 지점 병합-그러나 실수로 클릭하기 전에 서버에 동기화하지 못했을 수 있습니다 분기 삭제). 처음 지점을 찾았을 때 이름이 정확한지 확실하지 않았기 때문에 검색이 불필요하게 길어졌으며 첫 번째 지점을 다시 찾는 데 시간이 걸렸습니다. (따라서 Carpum을 Carpum 한 다음 계속 살펴보십시오.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.