Git에서 커밋을 복구하려면 어떻게해야합니까?


답변:


587

git reflog당신의 친구입니다. 해당 목록에서 원하는 커밋을 찾으면 다시 커밋 할 수 있습니다 (예 :) git reset --hard e870e41.

(변경 사항을 커밋하지 않은 경우 ... 문제가있을 수 있습니다. 일찍 커밋하고 자주 커밋하십시오!)


5
살펴보십시오 git log HEAD@{1}. 그것이 올바른 일련의 커밋처럼 보이면 할 수 있습니다 git reset HEAD@{1}.
Amber

4
코드가 (git add를 사용하여) 스테이징 된 경우에만 코드가 git로 유지되고와 같은 명령을 사용하여 쉽게 다시 찾을 수 있습니다 git fsck --lost-found.
랜디

2
리베이스 할 때 유지해야 할 커밋을 실수로 삭제했습니다. 이로 인해 몇 시간 분량의 작업을 다시 수행 할 수 없었습니다.
josephting

27
이것은 내 생명을 구했습니다.
Lutaaya Huzaifah Idris

6
이것은 나의 정신을 구했다 : D
Frank Fajardo

117

대답하기 전에 배경을 추가하여 이것이 무엇인지 설명해 봅시다 HEAD.

First of all what is HEAD?

HEAD단순히 현재 분기의 현재 커밋 (최신)에 대한 참조입니다. 주어진 시간에
하나만있을 수 있습니다 HEAD(제외 git worktree).

의 내용은 HEAD내부에 저장 .git/HEAD되며 현재 커밋의 40 바이트 SHA-1을 포함합니다.


detached HEAD

HEAD히스토리에서 이전 커밋을 가리키는 최신 커밋-의미가 아닌 경우 호출 detached HEAD됩니다.

여기에 이미지 설명을 입력하십시오

명령 행에서 다음과 같이 표시됩니다 HEAD. 현재 분기의 끝을 가리 키지 않으므로 분기 이름 대신 SHA-1이 표시됩니다 .

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


분리 된 HEAD에서 복구하는 방법에 대한 몇 가지 옵션 :


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

원하는 커밋을 가리키는 새 분기를 체크 아웃합니다.
이 명령은 주어진 커밋을 체크 아웃합니다.
이 시점에서 분기를 작성하고이 시점부터 작업을 시작할 수 있습니다.

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

당신은 항상 사용할 수 있습니다 reflog.
git reflog 변경 사항을 표시 HEAD하고 원하는 reflog 항목을 체크 아웃하면 HEAD이 커밋으로 다시 설정됩니다 .

HEAD가 수정 될 때마다 reflog

git reflog
git checkout HEAD@{...}

원하는 커밋으로 돌아갑니다.

여기에 이미지 설명을 입력하십시오


git reset --hard <commit_id>

HEAD를 원하는 커밋으로 "이동"하십시오.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • 참고 : ( Git 2.7 이후 )도 사용할 수 있습니다 git rebase --no-autostash.

git revert <sha-1>

지정된 커밋 또는 커밋 범위를 "실행 취소"합니다.
reset 명령은 지정된 커밋에서 변경 한 내용을 "실행 취소"합니다.
실행 취소 패치가 포함 된 새로운 커밋은 커밋되지만 원래 커밋도 기록에 남아 있습니다.

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

이 스키마는 어떤 명령이 무엇을 수행하는지 보여줍니다.
보시 reset && checkout다시피을 수정하십시오 HEAD.

여기에 이미지 설명을 입력하십시오


2
당신은 영웅입니다
dylanh724

4
그로 인해 많은 시간을 절약 할 수있었습니다. 타임 스탬프 없이는 확실히 알 수 없었기 때문에 "git reflog --date = iso"를 사용하여 각 항목의 날짜 / 시간을 확인했습니다.
MetalMikester

1
나를 위해, git reset --hard <commit_id>일을 제거 HEAD했습니다! 그래픽 표현의 경우 +1 !!
reverie_ss

언급 git reflog <branchname>할 것 : 지점 이름을 알고 있다면 : 하나의 지점의 변경 사항을 볼 수 있기 때문에 매우 유용 할 수 있습니다.
Markus Schreiber

35

삭제 된 커밋을 얻는 다른 방법은 git fsck명령을 사용하는 것입니다.

git fsck --lost-found

마지막 줄에서와 같이 출력됩니다.

dangling commit xyz

reflog다른 답변에서 제안한 것과 동일한 커밋인지 확인할 수 있습니다 . 이제 우리는 할 수 있습니다git merge

git merge xyz

참고 : 매달려있는 커밋에 대한 참조를 제거 하는 명령을 이미 실행 한 경우
커밋을 다시 가져올 수 없습니다 .fsckgit gc


3
이것은 분기를 가져오고 실수로 다른 분기를 재설정 할 때와 같이 최근에 커밋을 지적하지 않은 경우 작동하는 유일한 대답입니다.
TamaMcGlinn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.