커밋 개체들이 아직 .git 디렉토리 아래에 남아 있기 때문에 복구가 그다지 어렵지 않다 (시간이 흐르면 - 며칠? 한달? 정확히 모르겠으나 아주 짧진 않다 - 가비지 컬렉션에 의해 없어지니 주의)
어떻게든 해당 커밋 개체를 찾았으면, 그 개체를 다시 현재 브랜치에 연결하고 다시 git-reset 으로 브랜치 포인터를 이동시켜서 해결할 수 있겠다. 아래 링크들 참고.
주인장이 실제로 겪은 사례.
(저장소 만들고) $ git init Initialized empty Git repository in d:/Temp/git/.git/ ( d1 디렉토리와, 그 아래 file1 을 만든 후 커밋) $ mkdir d1 $ echo "hello" > d1/file1 $ git add d1 $ git ci -m "first commit" [master (root-commit) be77038] first commit The file will have its original line endings in your working directory. 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 d1/file1 ( d2 디렉토리와, 그 아래 file2 를 만든 후 add로 index에 추가하고) $ mkdir d2 $ echo "hello 2" > d2/file2 $ git add d2 $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: d2/file2 # ( 여기서 실수 ) $ git reset --hard HEAD HEAD is now at be77038 first commit $ ls d1 ( d2 디렉토리가 날아갔다 )
(그런데, 이 상황 재현은 막상 아래 복구 과정에서는 내가 경험했던 대로 결과가 나오지 않는다. 즉 제대로 재현이 안 됨)
조금 더 수정한 후에 커밋하는 게 좋겠다고 생각해서, 일단 만들어진 인덱스, 즉 stage 영역을 이전 상태로 되돌릴려고 했다. 이 경우는 git-reset의 옵션으로 --mixed 를 주거나, --mixed가 기본값이니까 아예 옵션을 적지 말았어야 했다. (아니면 그냥 무시하고 더 작업한 다음에 git-add를 해도 되는 거긴 한데, 이 때 뭐가 씌웠는지ㅋ) 그러나 --hard 옵션을 주는 바람에 작업 디렉토리가 통채로 현재 HEAD가 가리키는 상태로 되돌아가버렸고, 새로 추가한 d2 디렉토리와 그 내용들이 사라져 버렸다.
지워진 디렉토리가 사실 썩 중요한 것도 아니었고, 커밋을 하지 않은 상태라서 살리는 게 녹록치 않을 것 같아 포기하려 했는데, 트위터에 날렸다고 한마디 했더니 git-fsck를 써 보라는 리플을 받고1 문서 좀 뒤지면서 시도해 봄
$ git fsck --lost-found Checking object directories: 100% (256/256), done. Checking objects: 100% (627/627), done. dangling blob 0c6abc2d5faabc05babf319996ed80620797999f dangling tree b5bff3dcdc0f8fa00c9bfa2be1f64f7af5feec3f
$ git show 0c6a #!perl use 5.010; use strict; use warnings; ...
$ git show b5bf tree b5bf 20120403_sparse_matrix/ ... 20120526_montecarlo/ <-- 사라진 디렉토리 ... advent_calendar_2012_lotus/ <-- 사라진 디렉토리 ...
$ git cat-file -p b5bf ... 040000 tree 0842f02ec6dadb851ec2439c5fdfd643f6e3e877 20120526_montecarlo ... $ git cat-file -p 0842 040000 tree 8b3468edc53b977fde3f5e2ae423009fa487c9e0 _Inline 100644 blob f22308643a862993af01681ef5a5e8fcfebe88fe sphere.pl 100644 blob ff9098d4b4b4a16ed54d418a3ec43b8c4f5cffbc test.c 100644 blob 04f766def6dcd4a1d297a84bc25cd9df385373bc test.o $ git cat-file -p f223 #!/usr/bin/env perl use Inline C; use strict; ...
$ git read-tree b5bf $ git status # On branch master # Changes to be committed: ... # new file: 20120526_montecarlo/sphere.pl ... # Changes not staged for commit: ... # deleted: 20120526_montecarlo/sphere.pl ...
$ git read-tree -u -m b5bf $ git status # On branch master # Changes to be committed: ... # new file: 20120526_montecarlo/sphere.pl ... $ ls ... 20120526_montecarlo <-- 살아났다 ...