[첫화면으로]Git/복구

마지막으로 [b]

1. 커밋까지 한 상태에서 git-reset --hard 옵션으로 덮어써 버린 경우

커밋 개체들이 아직 .git 디렉토리 아래에 남아 있기 때문에 복구가 그다지 어렵지 않다 (시간이 흐르면 - 며칠? 한달? 정확히 모르겠으나 아주 짧진 않다 - 가비지 컬렉션에 의해 없어지니 주의)

어떻게든 해당 커밋 개체를 찾았으면, 그 개체를 다시 현재 브랜치에 연결하고 다시 git-reset 으로 브랜치 포인터를 이동시켜서 해결할 수 있겠다. 아래 링크들 참고.

2. 인덱스까지만 만든 상태에서 git-reset --hard 옵션으로 덮어써 버린 경우

주인장이 실제로 겪은 사례.

2.1. 상황 재현

(저장소 만들고)
$ 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 디렉토리와 그 내용들이 사라져 버렸다.

2.2. 복구 방법

지워진 디렉토리가 사실 썩 중요한 것도 아니었고, 커밋을 하지 않은 상태라서 살리는 게 녹록치 않을 것 같아 포기하려 했는데, 트위터에 날렸다고 한마디 했더니 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    <-- 살아났다
...

3. 참고

4. Comments

이름:  
Homepage:
내용:
 

컴퓨터분류
각주:
1. Twitter:am0c님 감사합니다
2. 거 참 같은 일을 하는 방법이 여러 가지로구나

마지막 편집일: 2012-5-27 6:28 pm (변경사항 [d])
2725 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기