잘못된 git push -f origin master에서 복구하려면 어떻게해야합니까?


답변:


54

Git은 일반적으로 아무것도 버리지 않지만 여기서 복구하는 것은 여전히 ​​까다로울 수 있습니다.

소스가 올바른 경우 --force옵션 을 사용하여 원격으로 푸시 할 수 있습니다. Git은 당신이 지시하지 않는 한 어떤 브랜치를 삭제하지 않을 것입니다. 실제로 커밋을 잃어버린 경우 커밋 복구대한 유용한 가이드를 참조하십시오 . 원하는 커밋의 SHA-1을 알고 있다면 괜찮을 것입니다.

최선의 방법 : 모든 것을 백업하고 로컬 저장소에 아직 무엇이 있는지 확인하십시오. 가능하면 리모컨에서도 똑같이하십시오. git fsck복구 할 수 있는지 확인하기 위해 사용 하고 무엇보다도 실행하지 마십시오git gc .

무엇보다도 --force, 정말로 진심이 아니라면 옵션을 사용하지 마십시오 .


64
원격 브랜치가 원래 어디에 있었는지 확인하기 위해 reflog를 살펴볼 수 있습니다. 예 : git reflog show remotes/origin/master. 당신은 거기에서 당신의 푸시를 볼 수있을 것입니다; 이전 줄의 커밋은 당신이 그것을 엉망으로 만들기 전에 있었던 곳입니다. 그런 다음 해당 개정판 (사용 --force)을 원래 위치로 푸시하고 원래 위치로 돌아갈 수 있습니다!
Cascabel

@ 데이비드 : 오. 리포지토리가 없다고 질문에 언급하지 않았습니다. (물론 절대로하고 싶지 않은 일입니다.)하지만 푸시 한 곳에서 파일 시스템 액세스 권한이있는 경우에도이 모든 작업을 수행 할 수 있습니다.
Cascabel

1
@David : 이케 스. 그런 종류의 것을 피하기 위해 프롬프트의 일부로 현재 디렉토리를 갖는 것이 항상 좋습니다.
Cascabel

1
@Jefromi 나는 당신이 말한 것이 실제 답이 있다고 생각합니다. 구버전 ( git fetch오랜 시간 동안 편집 하지 않았 음)이라도 GitHub 측의 reflog를 표시하고 복구 할 수 있습니다!
nh2

1
@Jefromi의 답변은 어디에 있습니까? 이 댓글 스레드 외부에서이 페이지에 언급 된 사용자를 볼 수 없습니다.
Don McCurdy

47

커밋 해시를 알고 있다면 간단합니다. 브랜치를 다시 만드십시오.

5794458...b459f069 master -> master (forced update)

원격 분기를 삭제합니다.

git push origin :master

그런 다음 다음 명령으로 분기를 다시 만듭니다.

git checkout 5794458
git branch master
git push origin master

28

해결책은 이미 여기에 언급되어 있습니다.

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master

감사합니다. 이것은 저에게 효과적이었습니다. 마스터 삭제 권한이 없어 승인 된 댓글이 실패했습니다.
Andi

예, git reflog show remotes/origin/mastergit reflog가 필요한 경우 (위의 @Cascabel에서 언급했듯이)
Josiah Yoder

2
올바른 답변에 연결해 주셔서 감사합니다.
Noitidart

6

강제 푸시가 발생한 로컬 리포지토리에 있지 않은 경우 원본 / 마스터 수준에서 복구 할 방법이 없습니다. 당신이하지만 운이 사용하기에 충분한 GitHub의 또는 기업에 대한 GitHub의를 , 당신은에보고 할 수 있습니다 REST의 API를 패치, 예를 들어 커밋 손실 검색 :

  1. 이벤트 나열 및 커밋 sha1 긴 형식 찾기

https://api.github.com/repos/apache/logging-log4j2/events

  1. 손실 된 커밋을 다운로드하고 json 경로 .files [] / patch에서 관련 패치를 검색합니다.

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. 로컬로 적용하고 다시 푸시

git apply patch.patch && git commit -m "restored commit"&& git push origin master


4

이전 푸시가 로컬 리포지토리에서 제공되지 않은 경우 손실 된 커밋을 복구하거나 손실 된 커밋을 파악하는 또 다른 방법은 CI 머신을 살펴 보는 것입니다.

모든 커밋 (또는 일련의 연속 커밋) 후에 마스터 브랜치를 테스트하는 작업이 있다면, 마지막으로 테스트 한 것을 볼 수 있습니다. 이것이 복원해야 할 커밋입니다.

CI 머신은이 복구를 수행 할 수있는 저장소의 로컬 복제본을 유지할 수도 있습니다.

출처 : 지속적인 제공 : 빌드, 테스트 및 배포 자동화를 통한 신뢰할 수있는 소프트웨어 릴리스 (Addison-Wesley Signature Series (Fowler))


3

예, 이후 커밋을 복구 할 수 있습니다. git push -f your_branch

문서의 텍스트 :

지정된 시간보다 오래된 항목을 정리합니다. 이 옵션을 지정하지 않으면 구성 설정 gc.reflogExpire에서 만료 시간을 가져 오며 기본값은 90 일입니다. --expire = 연령에 관계없이 모든 항목을 정리합니다. --expire = 접근 가능한 항목의 정리를 끄지 않습니다 (그러나 --expire-unreachable 참조).

따라서 다음을 수행 할 수 있습니다.

1- git reflog

여기에 이미지 설명 입력

2- 당신은 Head_Number를 선택하여 복구를 원하십니까 git reset –hard HEAD@{HEAD-NUMBER}

여기에 이미지 설명 입력

3-이 머리에 대한 모든 커밋을 볼 수 있습니다. git cherry -v branch_name

4- 결국 강제로 밀어야합니다. git push -f branch_name

또는

1- GIT 클라이언트 (인터페이스)에서 SHA 수 가져 오기

git reset --hard commit_SHA

2- 강제 밀기

git push -f your_branch

도움이 되었기를 바랍니다


2

하나의 파일에 대한 마지막 푸시를 실행 취소하면서 동일한 작업을 수행했습니다. 결국 저장소의 원래 상태로 돌아갑니다. Linux에서 로컬 사본이 있으므로 Linus의 git 명령을 사용했습니다. 다행히도 그 사본은 여전히 ​​손상되지 않았습니다.

내가 한 것은 (로컬 리포지토리의 복사본을 광적으로 몇 개 더 만든 후) :

git add .
git status

(오리진 / 마스터가 68 개의 커밋보다 앞서 있다고 말했습니다. 좋아요 ... 내가 삭제 한 모든 커밋이었습니다)

git remote set-url origin <GIT_SSH_URL>
git push

그리고 모든 것이 내가 강하게 밀기 전의 방식으로 복원되었습니다. 기억해야 할 가장 중요한 것은 git checkout을하지 않는 것입니다. 강하게 밀고 나서. 그러나 가장 좋은 방법은 푸시 옵션을 비활성화하는 것입니다. 다시는 사용하지 않습니다. 나의 교훈을 배웠다 !!


0

여기에서 결정을 읽을 수 있습니다 https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

두 번째는 나를 도왔다. 나는이 명령을 잘못했다

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

이 명령 후에 나는 세 개의 커밋을 잃었습니다. 그들을 복구하기 위해 나는 잘못 'git pull'한 터미널을 보았고 거기에서 다음과 같은 출력을 보았습니다.

60223bf ... 0b258eb 일부 분기-> 원산지 / 일부 분기

두 번째 해시 0b258eb는 정확히 필요한 것입니다. 그래서이 해시를 가져 와서

git push --force origin 0b258eb:some-branch

0

저와 같이 정말 나쁜 상황에 처한 사람들의 경우 (예 : bad object실행할 때 오류 가 발생하는 경우 git reset --hard) :

마지막 수단으로 GitHub API에서 모든 파일을 가져 오는 treesaver라는 스크립트를 작성 했습니다 . 사용 방법은 다음과 같습니다.

  1. treesaver스크립트를 복제하십시오 cd.
  2. SHA에 액세스하여 복원 할 트리 문자열을 찾습니다 https://api.github.com/repos/<your_username_or_org>/<repo>/events.
  3. payload푸시 이벤트에 해당 하는 속성 commit에서 되돌리려 는 을 찾아 해당 url.
  4. 아래 commit.tree에서 treeurl.
  5. 을 실행 python3 main.py <tree_url> <path_to_save_to>합니다.

예를 들어, 제 경우에는 다음을 실행합니다.

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

물론 PR도 환영합니다.

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