2010-06-30 3 views
20

제 동료가 mkdir $VERSION 접근법을 사용했기 때문에 일부 소스 코드를 받았고 git을 사용하기로 결정했습니다. 코드의 과거는 현재 중요하지 않은 것처럼 보이지만 개발 프로세스를 더 잘 이해하기 위해서는 여전히 git 컨트롤을 사용하고 싶습니다. 따라서 :git 저장소에 과거를 추가하는 방법은 무엇입니까?

기존 버전을 내 기존 git repo에 삽입하는 편리한 방법은 무엇입니까? 현재 원격 저장소가 없으므로 기록을 다시 작성하는 데 신경을 쓰지 않지만 원격 저장소를 고려한 솔루션은 훨씬 더 복잡하지 않으면 선호됩니다. 디렉토리 또는 아카이브 파일 기반 기록을 기반으로 더 이상 상호 작용이 필요하지 않은 스크립트의 보너스 포인트입니다.

+1

또한 [Git에서 첫 번째/root/initial 커밋을 수정/수정/변경 하시겠습니까?] (http://stackoverflow.com/q/2119480/456814), [Git으로 프로젝트의 첫 번째 커밋을 변경 하시겠습니까?] (http://stackoverflow.com/q/2246208/456814), [힘내 : 처음/처음/루트 커밋 전에 커밋을 추가하는 방법?] (http://stackoverflow.com/q/16762160/456814). –

+0

@Cupcake 감사합니다. 귀하의 링크에 대한 알림을 보지 못했습니다. –

답변

21

이전 스냅 샷을 가져 오는 경우 Git's contrib/fast-import directory의 도구 중 일부가 유용합니다. 이미 디렉토리에 각 오래된 스냅 샷이있는 경우 또는, 당신은 같은 것을 할 수 있습니다 일단

cd work && git fetch ../import master:old-history 

:

# Assumes the v* glob will sort in the right order 
# (i.e. zero padded, fixed width numeric fields) 
# For v1, v2, v10, v11, ... you might try: 
#  v{1..23}  (1 through 23) 
#  v?{,?}  (v+one character, then v+two characters) 
#  v?{,?{,?}} (v+{one,two,three} characters) 
#  $(ls -v v*) (GNU ls has "version sorting") 
# Or, just list them directly: ``for d in foo bar baz quux; do'' 
(git init import) 
for d in v*; do 
    if mv import/.git "$d/"; then 
     (cd "$d" && git add --all && git commit -m"pre-Git snapshot $d") 
     mv "$d/.git" import/ 
    fi 
done 
(cd import && git checkout HEAD -- .) 

는 그런 다음 작업 저장소로 오래된 역사를 가져 오기 당신은 이전 리포지토리와 Git 기반 히스토리 모두를 동일한 리파지토리에 가지고 있습니다. 이식 작업과 대체 작업을위한 몇 가지 옵션이 있습니다.

그래프트는 다양한 기존 커밋의 상위를 편집 (일시적으로)하기위한 저장소 별 메커니즘입니다. 이식은 $GIT_DIR/info/grafts 파일 (gitrepository-layout manpage의 "info/grafts"에 설명되어 있음)에 의해 제어됩니다. 장소에 이식 (원래 초기 부모님이 없었, 이식 한 부모 준 커밋), 당신은을 통해 검색하고 확장의 역사를 볼 수있는 모든 일반 망할 놈의 도구를 사용할 수 있습니다와

INITIAL_SHA1=$(git rev-list --reverse master | head -1) 
TIP_OF_OLD_HISTORY_SHA1=$(git rev-parse old-history) 
echo $INITIAL_SHA1 $TIP_OF_OLD_HISTORY_SHA1 >> .git/info/grafts 

(예 git log 커밋 후 이전 기록을 보여 주어야합니다).

그래프트의 주요 문제점은 저장소에 제한되어 있다는 것입니다. 그러나 그들이 역사의 영구적 인 부분으로 결정했다면 git filter-branch을 사용하여 (.git 디렉토리의 tar/zip 백업을 먼저 수행하십시오.) git filter-branch은 원래의 refs,하지만 때로는 일반 백업을 사용하는 것이 더 쉽습니다).

git filter-branch --tag-name-filter cat -- --all 
rm .git/info/grafts 

교체기구 (힘내 1.6.5 +) 최신이지만, 이들은 당 명령 기반 (git --no-replace-objects …)에서 비활성화 될 수 있고 쉽게 공유 푸시 할 수있다. 대체물은 개별 객체 (얼룩, 나무, 커밋 또는 주석이 달린 태그)에서 작동하므로 메커니즘도 더 일반적입니다. 교체 메커니즘은 git replace manpage에 설명되어 있습니다. 때문에 일반성은 "prepending이"설정이 좀 더 참여하고있다 (우리는 새로운이 대신 새로운 부모를 이름의 커밋 만들어야합니다) :

# the last commit of old history branch 
oldhead=$(git rev-parse --verify old-history) 
# the initial commit of current branch 
newinit=$(git rev-list master | tail -n 1) 
# create a fake commit based on $newinit, but with a parent 
# (note: at this point, $oldhead must be a full commit ID) 
newfake=$(git cat-file commit "$newinit" \ 
     | sed "/^tree [0-9a-f]\+\$/aparent $oldhead" \ 
     | git hash-object -t commit -w --stdin) 
# replace the initial commit with the fake one 
git replace -f "$newinit" "$newfake" 

공유이 교체 자동 없습니다.대체물을 공유하려면 refs/replace의 일부 또는 전체를 푸시해야합니다.

git push some-remote 'refs/replace/*' 

당신은 대체 영구적 자식 필터 - 지점 사용하기로 결정한 경우 (이식에서와 같이 동일, 먼저 .git 디렉토리의 타르/우편 백업을) :

git filter-branch --tag-name-filter cat -- --all 
git replace -d $INITIAL_SHA1 
+0

덕분에이 기능은 작은 테스트 하위 집합에 유용합니다 (현재 대체품을 사용 중입니다). –

+0

이것은 나를 위해 문제가되지 않습니다. 순간,하지만 어쨌든 물어 보겠습니다 :'git filter-branch'ing 이전에 replace-option을 사용하면 히스토리가 다시 쓰이지 않아 쉽게 공유 할 수 있습니다. –

+2

* git filter branch *를 사용하지 않으면 접목이나 치환이 실제로 기록을 다시 쓰지 않습니다. (기록을 다시 작성한 것처럼 마치 DAG에 영향을줍니다.) 대체의 이점은 1) 커맨드 라인 인자 또는 환경 변수에 의해 사용 불가하게 될 수있다. 2) 푸시/페치 될 수있다. 3) 커밋의 부모 "attritubes"뿐만 아니라 모든 객체에서 작동한다. 대체물 푸시 기능을 사용하면 일반적인 Git 프로토콜을 사용하여 쉽게 공유 할 수 있습니다 (이식편 항목을 공유 할 수 있지만 푸시/푸치가 아닌 "대역 외"메커니즘을 사용하여 전파해야 함). –

1

가장 쉬운 접근법은 당연히 새로운 git repo를 생성하고, 먼저 역사를 커밋 한 다음, 이전 repo의 패치를 다시 적용하는 것입니다. 그러나 자동화로 시간을 절약 할 수있는 솔루션을 선호합니다.

2

하는 경우 저장소에서 커밋을 변경하고 싶지 않은 경우 그래프트를 사용하여 커밋에 대한 부모 정보를 무시할 수 있습니다. 이것은 Linux 커널 repo가 ​​Git을 사용하기 전에 역사를 얻는 것입니다.

이 메시지 : http://marc.info/?l=git&m=119636089519572은 내가 찾을 수있는 최상의 문서가있는 것 같습니다.

당신은 pre-git 히스토리와 관련된 커밋 시퀀스를 만든 다음 .git/info/grafts 파일을 사용하여 Git이 그 커밋의 마지막 커밋을 Git을 사용하여 생성 한 첫 번째 커밋의 부모로 사용하게한다.

+1

+1 아 그래, 알겠습니다, 고마워요. 이것은 [Chris Johnsen의 답변]에서 접목 옵션으로 자세하게 설명되어 있습니다 (http://stackoverflow.com/questions/3147097/how-to-prepend-the-past-to-a-git-repository/3148117#3148117). –

관련 문제