2011-10-15 2 views
8

.git 디렉토리가없는 작업 디렉토리는 a이고 저장소는 b입니다.) 저장소가 있습니다. ab의 역사 중 일부 개정입니다.작업 디렉토리의 Git 개정판 찾기 .git 디렉토리 누락

어떤 개정이 a과 일치합니까 (b)?

작업 디렉토리에서 모든 개정판으로 diff을 수행하는 셸 스크립트를 생각하고 최소 차이 (희망 사항은 0)를 가진 쉘을 선택했습니다.

그건 원시가 될 것입니다. (그리고 어떻게해야할지 모르겠습니다) 쉬운 방법이 있습니까?

답변

4

커밋마다 diff gitdir workdir | wc -c을 실행하는 스크립트를 작성할 수 있습니다. 그런 다음 결과를 대조하고 가장 작은 차이가있는 커밋 (wc -c으로 측정)이 맨 작업 영역에 가장 가깝다고 말할 수 있습니다. 여기

는 파이썬에서 어떻게 보이는지입니다 :

find_closest_sha1.py :

#!/usr/bin/env python 
import subprocess 
import shlex 
import sys 
import os 
import operator 

gitdir,workdir=map(os.path.realpath,sys.argv[1:3]) 
os.chdir(gitdir) 
proc=subprocess.Popen(shlex.split('git rev-list --all'),stdout=subprocess.PIPE) 
shas,err=proc.communicate() 
shas=shas.split() 
head=shas[0] 
data={} 
for sha1 in shas: 
    subprocess.Popen(shlex.split('git checkout {s}'.format(s=sha1)), 
          stderr=open('/dev/null')).wait() 
    proc=subprocess.Popen(shlex.split('diff {g} {w}'.format(g=gitdir,w=workdir)), 
          stdout=subprocess.PIPE) 
    out,err=proc.communicate() 
    distance=len(out) 
    data[sha1]=distance 
answer=min(data.items(),key=operator.itemgetter(1))[0] 
print('closest match: {s}'.format(s=answer)) 
subprocess.Popen(shlex.split('git checkout {h}'.format(h=head)), 
       stderr=open('/dev/null')).wait() 

예 :

% rsync -a gitdir/ workdir/ 
% cd workdir 
% git checkout HEAD~10 
HEAD is now at b9fcebf... fix foo 

% cd .. 
% /bin/rm -rf workdir/.git 
% find_closest_sha1.py gitdir workdir 
closest match: b9fcebfb170785c19390ebb4a9076d11350ade79 
+0

파이썬 스크립트는 테스트 할 때 완전히 실패했습니다. 완전히 잘못된 커밋을 출력합니다. –

1

pickaxe으로 확인해야하는 개정 수를 줄일 수 있습니다. 작업 디렉토리를 최신 버전과 비교하여 가능한 희소하게 보이는 다른 라인을 선택하십시오. 최신 개정판에 foobar이 포함 된 행이 있지만 작업 디렉토리에는 포함되어 있지 않습니다. 을 실행하면 모두 foobar을 추가 또는 제거하는 커밋을 출력합니다. 이후에 모든 개정이 작업 디렉토리와 다르기 때문에 저장소를 해당 목록의 첫 번째 (최신) 개정으로 다시 이동할 수 있습니다. 올바른 버전을 찾을 때까지 다른 차이점을 반복합니다.

1

git는 콘텐츠 주소 지정이 가능한 파일 저장소를 사용하기 때문에 어딘가에 임의의 트리를 찾을 수 있어야하지만 세부 사항을 알지 못합니다. 분리 된 작업 디렉토리에서 저장소의 작업 디렉토리로 파일을 복사 한 다음 모든 것을 커밋하고 커밋에 의해 생성 된 트리 객체의 해시를 찾아서 같은 트리를 참조하는 기존 커밋을 검색 할 수 있다고 생각합니다. .

이 작업을하려면 분명히 나무가 완벽하게 일치해야하므로 커밋되지 않은 파일 (예 : 개체 파일, 편집기 백업 등)을 가져 오지 않아야합니다.

편집 : 방금 머리글에 트리 개체를 표시하고 해당 트리 해시에 대한 git log --pretty=raw의 출력을 검색하기 위해 git cat-file commit HEAD을 사용하여이 저장소를 시도했지만 작동하지 않았습니다. (해시를 찾지 못했습니다. 역사상). 내가 커밋을했을 때 CRLF 변환에 대한 경고를 많이 받았으므로 문제가되었을 수 있습니다. 즉, git이 텍스트 파일을 mangle로 구성하는 방법에 따라 동일한 트리에 대해 다른 해시를 얻었을 수 있습니다. 누군가 이걸 어떻게 안정적으로 수행하는지 알고 있기 때문에이 커뮤니티 위키를 표시하고 있습니다.

0

가정하면 그에서 나무와 b/.git 무시 설정은 커밋을 만들 때의 설정과 같습니다. 작업 트리에 무시되지 않은 untracked 파일이 없으므로 이와 같이 실행할 수 있어야합니다.

전략은 작업 트리의 자식 id를 다시 만든 다음이 트리가 포함 된 커밋을 검색하는 것입니다.

# work from detached working tree 
cd a 

# Use existing repository and a temporary index file 
GIT_DIR=b/.git 
GIT_INDEX_FILE=/tmp/tmp-index 
export GIT_DIR GIT_INDEX_FILE 

# find out the id of the current working tree 
git add . && 
tree_id=$(git write-tree) && 
rm /tmp/tmp-index 

# find a commit that matches the tree 
for commit in $(git rev-list --all) 
do 
    if test "$tree_id" = "$(git rev-parse ${commit}^{tree})"; then 
     git show "$commit" 
     break 
    fi 
done 

unset GIT_DIR 
unset GIT_INDEX_FILE 
관련 문제