your programing

git reset --hard HEAD ~ 1을 실행 취소하려면 어떻게해야합니까?

lovepro 2020. 9. 27. 13:31
반응형

git reset --hard HEAD ~ 1을 실행 취소하려면 어떻게해야합니까?


다음 명령으로 인한 변경 사항을 취소 할 수 있습니까? 그렇다면 어떻게?

git reset --hard HEAD~1

Pat Notz가 맞습니다. 며칠 이내에 커밋을 되돌릴 수 있습니다. git은 최신 blob을 제거하도록 명시 적으로 지시하지 않는 한 약 한 달 정도 후에 가비지 수집 만 수행합니다.

$ git init
Initialized empty Git repository in .git/

$ echo "testing reset" > file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo "added new file" > file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file

예제에서 하드 리셋의 결과로 file2가 제거되었지만 reflog를 통해 리셋 할 때 제자리에 다시 놓인 것을 볼 수 있습니다.


원하는 것은 복원 할 커밋의 sha1을 지정하는 것입니다. reflog ( git reflog) 를 검사 한 다음 다음을 수행 하여 sha1을 얻을 수 있습니다.

git reset --hard <sha1 of desired commit>

그러나 너무 오래 기다리지 마십시오 ... 몇 주 후에 git은 결국 해당 커밋을 참조되지 않은 것으로보고 모든 blob을 삭제합니다.


답변은 위의 자세한 답변에 숨겨져 있습니다.

$> git reset --hard HEAD@{1}

( git reflog show 출력 참조 )


Git이 아직 가비지 수집하지 않은 경우 복구 할 수 있습니다.

매달린 커밋에 대한 개요를 얻으십시오 fsck.

$ git fsck --lost-found
dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

rebase로 매달린 커밋을 복구하십시오.

$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

저처럼 운이 좋다면 텍스트 편집기로 돌아가서 '실행 취소'를 누르세요.

나는 그것이 정말로 적절한 대답이 아니라는 것을 압니다. 그러나 그것은 저를 반나절 동안의 작업을 구해주었습니다. 그래서 다른 누군가에게도 똑같이 할 수 있기를 바랍니다!


내가 아는 한 --hard커밋되지 않은 변경 사항을 버립니다. 이들은 git에 의해 추적되지 않기 때문에. 하지만 discarded commit.

$ git reflog

다음을 나열합니다.

b0d059c HEAD@{0}: reset: moving to HEAD~1
4bac331 HEAD@{1}: commit: added level introduction....
....

어디 4bac331입니다 discarded commit.

이제 머리를 해당 커밋으로 이동하십시오.

$ git reset --hard 4bac331

IRL 사례의 예 :

$ git fsck --lost-found

Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob 025cab9725ccc00fbd7202da543f556c146cb119
dangling blob 84e9af799c2f5f08fb50874e5be7fb5cb7aa7c1b
dangling blob 85f4d1a289e094012819d9732f017c7805ee85b4
dangling blob 8f654d1cd425da7389d12c17dd2d88d318496d98
dangling blob 9183b84bbd292dcc238ca546dab896e073432933
dangling blob 1448ee51d0ea16f259371b32a557b60f908d15ee
dangling blob 95372cef6148d980ab1d7539ee6fbb44f5e87e22
dangling blob 9b3bf9fb1ee82c6d6d5ec9149e38fe53d4151fbd
dangling blob 2b21002ca449a9e30dbb87e535fbd4e65bac18f7
dangling blob 2fff2f8e4ea6408ac84a8560477aa00583002e66
dangling blob 333e76340b59a944456b4befd0e007c2e23ab37b
dangling blob b87163c8def315d40721e592f15c2192a33816bb
dangling blob c22aafb90358f6bf22577d1ae077ad89d9eea0a7
dangling blob c6ef78dd64c886e9c9895e2fc4556e69e4fbb133
dangling blob 4a71f9ff8262701171d42559a283c751fea6a201
dangling blob 6b762d368f44ddd441e5b8eae6a7b611335b49a2
dangling blob 724d23914b48443b19eada79c3eb1813c3c67fed
dangling blob 749ffc9a412e7584245af5106e78167b9480a27b
dangling commit f6ce1a403399772d4146d306d5763f3f5715cb5a    <- it's this one

$ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

commit f6ce1a403399772d4146d306d5763f3f5715cb5a
Author: Stian Gudmundsen Høiland <stian@Stians-Mac-mini.local>
Date:   Wed Aug 15 08:41:30 2012 +0200

    *MY COMMIT MESSAGE IS DISPLAYED HERE*

diff --git a/Some.file b/Some.file
new file mode 100644
index 0000000..15baeba
--- /dev/null
+++ b/Some.file
*THE WHOLE COMMIT IS DISPLAYED HERE*

$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

First, rewinding head to replay your work on top of it...
Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.

대부분의 경우 그렇습니다.

명령을 실행할 때 저장소의 상태에 따라의 효과는 git reset --hard사소한 것부터 실행 취소, 기본적으로 불가능한 것까지 다양합니다.

아래에는 다양한 가능한 시나리오와 그로부터 복구 할 수있는 방법이 나열되어 있습니다.

내 모든 변경 사항이 커밋되었지만 이제 커밋이 사라졌습니다!

이 상황은 일반적으로에서 git reset와 같이 인수로 실행할 때 발생합니다 git reset --hard HEAD~. 걱정하지 마세요. 쉽게 복구 할 수 있습니다!

방금 뛰고 git reset그 이후로 다른 작업을 수행하지 않은 경우이 한 줄짜리 줄을 사용하여 원래 위치로 돌아갈 수 있습니다.

git reset --hard @{1}

이렇게하면 마지막으로 수정되기 전의 상태에 관계없이 현재 분기가 재설정됩니다 (귀하의 경우 분기에 대한 가장 최근 수정은 실행 취소하려는 하드 재설정이 될 것입니다).

그러나,이 경우 리셋 이후 지점에 다른 수정 한, 한 - 라이너 이상 작동하지 않습니다. 대신 브랜치에 적용된 최근 변경 사항 (재설정 포함) 목록을 보려면 실행해야합니다 . 해당 목록은 다음과 같습니다.git reflog <branchname>

7c169bd master@{0}: reset: moving to HEAD~
3ae5027 master@{1}: commit: Changed file2
7c169bd master@{2}: commit: Some change
5eb37ca master@{3}: commit (initial): Initial commit

이 목록에서 "실행 취소"할 작업을 찾습니다. 위의 예에서는 "reset : moving to HEAD ~"라는 첫 번째 줄이됩니다. 그런 다음 해당 작업 이전 (아래) 커밋 표현을 복사합니다 . 우리의 경우에는 master@{1}(또는 3ae5027둘 다 동일한 커밋을 나타냄) 실행 git reset --hard <commit>하여 현재 분기를 해당 커밋으로 다시 재설정합니다.

로 변경 사항을 준비 git add했지만 커밋하지 않았습니다. 이제 내 변경 사항이 사라졌습니다!

복구하기가 조금 더 까다 롭습니다. git 에는 추가 한 파일의 복사본이 있지만 이러한 복사본은 특정 커밋에 연결되지 않았으므로 변경 사항을 한 번에 복원 할 수 없습니다. 대신 git의 데이터베이스에서 개별 파일을 찾아 수동으로 복원해야합니다. 을 사용하여이 작업을 수행 할 수 있습니다 git fsck.

이에 대한 자세한 내용 은 스테이징 영역에서 커밋되지 않은 파일로 git reset --hard 실행 취소를 참조하세요 .

으로 스테이징 git add하지 않았고 커밋 하지 않은 작업 디렉토리의 파일을 변경했습니다 . 이제 내 변경 사항이 사라졌습니다!

어 오. 나는 당신에게 이것을 말하기 싫지만 당신은 아마도 운이 좋지 않을 것입니다. 자식은 추가하거나 커밋하고 따라하지 않는 것이 변경 저장하지 않습니다 에 대한 문서를git reset :

--단단한

색인 및 작업 트리를 재설정합니다. 이후 작업 트리에서 추적 된 파일에 대한 변경 사항 <commit>은 무시됩니다.

그것은 당신이있을 가능성이 있습니다 디스크 복구 유틸리티 또는 전문 데이터 복구 서비스의 일종으로 변경 사항을 복구 할 수 있지만, 아마도 그것의 가치보다 더 많은 문제가있어이 시점에서.


아직 저장소를 가비지 수집하지 않은 경우 (예 : git repack -d또는을 사용 git gc하지만 가비지 수집도 자동으로 발생할 수 있음) 커밋은 여전히 ​​존재합니다. 더 이상 HEAD를 통해 도달 할 수 없습니다.

의 출력을 살펴보면 커밋을 찾을 수 있습니다 git fsck --lost-found.

최신 버전의 Git에는 "reflog"라는 것이 있는데, 이는 ref에 대한 모든 변경 사항의 로그입니다 (저장소 내용에 대한 변경 사항과 반대). 따라서 예를 들어 HEAD를 전환 할 때마다 (즉 git checkout분기를 전환 할 때마다 ) 기록됩니다. 그리고 물론 git resetHEAD도 조작 했으므로 기록되었습니다. , like @대신 기호를 사용하여 저장소의 이전 상태에 액세스 할 수있는 것과 유사한 방식으로 ref의 이전 상태에 액세스 할 수 있습니다 .~git reset HEAD@{1}

HEAD @ {1}와 HEAD ~ 1의 차이점을 이해하는 데 시간이 좀 걸렸으므로 여기에 약간의 설명이 있습니다.

git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog

따라서 HEAD~1"현재 HEAD@{1}HEAD가 가리키는 커밋 전에 커밋으로 이동" 의미 하고 "현재 HEAD가 가리키는 커밋 이전에 HEAD가 가리키는 커밋으로 이동" 의미합니다.

그러면 잃어버린 커밋을 쉽게 찾아서 복구 할 수 있습니다.


대답하기 전에 배경을 추가하고 이것이 무엇인지 설명합니다 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 HEAD --hard <commit_id>

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

# 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.
  • Note: (Since Git 2.7)
    you can also use the git rebase --no-autostash as well.


git revert <sha-1>

"Undo" the given commit or commit range.
The reset command will "undo" any changes made in the given commit.
A new commit with the undo patch will be commited while the original commit will remain in the history as well.

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

This schema illustrate which command does what.
As you can see there reset && checkout modify the HEAD.

여기에 이미지 설명 입력


I know this is an old thread... but as many people are searching for ways to undo stuff in Git, I still think it may be a good idea to continue giving tips here.

When you do a "git add" or move anything from the top left to the bottom left in git gui the content of the file is stored in a blob and the file content is possible to recover from that blob.

So it is possible to recover a file even if it was not committed but it has to have been added.

git init  
echo hello >> test.txt  
git add test.txt  

Now the blob is created but it is referenced by the index so it will no be listed with git fsck until we reset. So we reset...

git reset --hard  
git fsck  

you will get a dangling blob ce013625030ba8dba906f756967f9e9ca394464a

git show ce01362  

will give you the file content "hello" back

To find unreferenced commits I found a tip somewhere suggesting this.

gitk --all $(git log -g --pretty=format:%h)  

I have it as a tool in git gui and it is very handy.


I've just did a hard reset on wrong project. What saved my life was Eclipse's local history. IntelliJ Idea is said to have one, too, and so may your editor, it's worth checking:

  1. Eclipse help topic on Local History
  2. http://wiki.eclipse.org/FAQ_Where_is_the_workspace_local_history_stored%3F

git reflog

  • Find your commit in the list then copy and paste:

git cherry-pick <the sha>


Made a tiny script to make it slightly easier to find the commit one is looking for:

git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'

Yes, it can be made considerably prettier with awk or something like it, but it's simple and I just needed it. Might save someone else 30 seconds.


If you are using a JetBrains IDE (anything IntelliJ based), you can recover even your uncommited changes via their "Local History" feature.

파일 트리에서 최상위 디렉토리를 마우스 오른쪽 버튼으로 클릭하고 컨텍스트 메뉴에서 "로컬 히스토리"를 찾은 다음 "히스토리 표시"를 선택하십시오. 그러면 최근 편집 한 내용을 찾을 수있는보기가 열리고 다시 돌아 가려는 개정판을 찾은 후 마우스 오른쪽 버튼으로 클릭하고 "되돌리기"를 클릭합니다.

참고 URL : https://stackoverflow.com/questions/5473/how-can-i-undo-git-reset-hard-head1

반응형