베어 git 저장소를 일반 저장소로 어떻게 변환합니까?


81

베어 git 저장소가 있지만 ssh (사용자 경험과 같은 파일 관리자에서)를 통해 컨텐츠에 액세스하고 찾아 볼 필요가 있습니다.

나는 그것을 복제 할 수 있다고 가정합니다.

git clone -l <path_to_bare_repo> <new_normal_repo>

그러나 내 저장소의 크기는 약 20GB이며 복제 할 공간이 없습니다. 베어 저장소를 제자리에서 변환하여 작업 복사본을 만드는 방법이 있습니까?


5
테스트되지 않았지만 베어 저장소의 내용을 .git디렉토리 bare에 넣고 구성 의 매개 변수를 false로 설정하면 git checkout파일을 가져올 수있는 일반 저장소처럼 동작해야합니다 .
— Noufal Ibrahim

당신이 "내용을 찾아"무슨 뜻인지에 따라, 당신은 아마 당신이 사용하는 베어의 repo에서 원하는 모든 것을 할 수 git show와git cat-file
— 윌리엄 Pursell

유용한 힌트 주셔서 감사합니다. 그래도 경험과 같은 파일 관리자가 더 필요합니다 (질문 편집).
— nyi

파일 시스템이 하드 링크를 지원하고 동일한 파일 시스템으로 복제하는 경우 clone -l은 모든 개체를 하드 링크하기 때문에 더 이상 디스크 공간을 차지하지 않습니다. 그러나 다른 사람들이 언급했듯이 체크 아웃을위한 공간이 필요합니다.
— Neil Mayhew 2014

1
귀하의 경우 베어 저장소는 디스크 공간 20GB의를 차지, 얼마나 더 작업 트리 필요 것? 당신이 할 정말 그렇게 많은 공간이?
— ADTC

답변:


113

참고 : 나는 이것을 매우 간단한 1- 커밋 저장소 에서 테스트했습니다 . 이것을 다시 확인하고 man 페이지를 읽고 StackOverflow에서 찾은 조언을 따르기 전에 항상 백업 해 두십시오. (백업하지?)

--bare저장소를 베어가 아닌 것으로 변환하려면 다음을 수행하십시오.

  1. .git저장소의 최상위 수준에 폴더를 만듭니다 .
  2. 방금 만든 저장소 관리 항목 ( HEAD branches config description hooks info objects refs등)을 이동합니다 .git.
  3. git config --local --bool core.bare false로컬 git-repository를 non-bare로 변환하려면 실행하십시오 .
  4. ( Tamas Pap의 의견을 통해 ) # 3 단계 후에는 브랜치 master(또는 메인 브랜치)에 있고 모든 파일이 삭제되고 삭제가 준비 되었음을 알 수 있습니다 . 그것은 정상입니다. 그냥 수동으로 체크 아웃 master, 또는을 git reset --hard, 그리고 당신이 완료됩니다.
  5. ( Royi 가보고 한 문제를 해결하기 위해 ) 섹션 에서 .git/config줄 fetch = +refs/heads/*:refs/remotes/origin/*을 추가하여 파일을 편집 합니다 . 그렇지 않으면 다른 원산지의 분기를 볼 수 없습니다 .url = <...>[remote "origin"]git fetchorigin/master

이 단계의 반대 방향에있는 이 질문에 , "보통 자식 - 변환이 저장소 베어하기"- 특정 주에서 이 대답 (어느 방향으로, 나는 가정에서) 위의 단계가한다고, 다른 을하고부터 git-clone. 그것이 당신과 관련이 있는지 확실하지 않지만 git clone질문에서 언급 했습니다.


2
나는 모두 작성했지만 여전히 파일을 푸시 할 때 표시되지 않습니다. 그것은 무엇 일 수 있습니까 (또한 denyCurrentBranch를 무시하도록 전환했습니다)?
— Royi

감사합니다! 어느 날 직장에 들어 와서 다른 곳에 여러 개의 워크 트리가있는 메인 저장소가 자신이 "베어"라고보고하는 것을 발견했습니다. 다른 모든 작업 트리는 괜찮 았습니다. 결혼하지 않는 방법을 몰랐지만이 답변을 찾았고 훌륭하게 작동했습니다.
— davidbak

17

약간 다른 시나리오가 있습니다.

해결책:

  • 해당 컨텐츠의 베어 저장소를 .git디렉토리 에 복제하십시오 .
    git clone --bare https://github.com/user/project .git
  • 비 베어 리포지토리로 표시 :
    git config --local --bool core.bare false
  • 인덱스를 (A 이후, 그렇지 않으면, 모든 삭제 된 믿고 다시 .git 베어 의 repo 파일 '을 포함하지 않는 index'.)
    git reset HEAD -- .
    복원합니다 그 .git/index.

이전에 얻은 콘텐츠를 보존하면서 베어 저장소를 베어가 아닌 저장소로 효과적으로 변환했습니다. 전체 스크립트 내가 년 동안 사용하고는 단계를 포함한다 :

cd /path/to/current/worktree

# That creates a .git directly at the right place
git clone --bare /url/of/repo .git

# restore the link between the local repo and its upstream remote repo
git config --local --bool core.bare false
git config --local remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch origin
git branch -u origin/master master

# reset the index (not the working tree)
git reset HEAD -- .

하지만 난 정찰 할 허용 솔루션 합니다 (에 도움이 git reset추가 단계 로 ADTC는 ) 간단합니다.


베어 리포지토리가 줄 끝이 다른 시스템에서 생성 된 경우 이러한 단계를 수행 한 후에도 수정 된 파일을 볼 수 있다는 점도 주목할 가치가 있습니다. 나는 그것이 정상이라고 믿습니다. 자식은 줄 바꿈을 수정하려고합니다. 이유가 확실하지 않습니다.
— Juno Woods

그래서 기본적으로 GitHub 저장소를 맨손으로 복제하고 맨손이 아닌 것으로 전환하고 수동으로 "비 저장소"의 모든 파일을 넣고 인덱스를 재설정합니까? 처음에 맨손이 아닌 것으로 저장소를 복제하는 것과 어떻게 다릅니 까? 비 베어 클론 프로세스는 어쨌든 모든 파일을 체크 아웃합니다. 그리고 정말로 원한다면 체크 아웃 한 파일을 "non-repo"의 파일로 바꿀 수 있습니다.
— ADTC

@ADTC의 목표는 .git처음에 아카이브 (비 자식)로 만든 작업 트리 (당신이 알고있는 저장소)에서 하위 폴더 를 가져 오는 것입니다. 체크 아웃을하고 있던 폴더가 비어 있지 않기 때문에 비 베어 리포지토리를 체크 아웃 할 수 없습니다. git clone --no-checkout하위 폴더에서 맨손이 아닌 작업을 수행하면 .git한 수준 위로 이동해야 했습니다. 베어 클론을 사용하면 .git원하는 위치 에 하위 폴더 를 직접 만들 수있었습니다 . 스크립트는 여기에서 볼 수 있습니다 : github.com/VonC/compileEverything/blob/…
— VonC

"체크 아웃을하던 폴더가 비어 있지 않기 때문에 베어가 아닌 저장소를 체크 아웃 할 수 없었습니다." 아직 커밋되지 않은 변경 사항을 포함하는 비 git 작업 트리가 있으며 Git 지원 작업 트리로 변환 한 후 커밋하려고합니까? 예, 그런 사용 사례에서 작동합니다. 개인적으로 빈 폴더에 복제하고 먼저 두 개를 비교합니다 (외부 도구 사용). 하지만 그건 나뿐입니다.
— ADTC

@ADTC 없음 : 나는 할 수 없습니다 "아직 커밋되지 않은 변경 사항이 포함되지 않은 자식 작업 트리"를 가지고있다. 나는 아무것도 저지르고 싶지 않습니다 . 내가 할 이 것은 환매 특약의 정확한 작업 트리입니다 : 모든없는 그이다 .git. 나는 .git베어 클론을 통해 그 .git폴더를 베어가 아닌 폴더로 변환하고 git resetgit이 작업 트리가 이미 거기에 있음을 깨닫도록 만듭니다. 이것이 바로 github.com/VonC/compileEverything/blob/…이하 는 일입니다.
— VonC

11

답변의 정보를 단순화하고 결합하려면 :

베어 리포지토리를 일반 .git 폴더와 다른 세 가지 차이점이 있습니다.

  • core.bare는 구성 파일에서 true로 설정됩니다.
  • 인덱스 파일과 작업 트리가 존재하지 않습니다.
  • "원본"원격지에 대한 기본 참조 사양이 생성되지 않습니다.

따라서 베어 리포지토리를 새 폴더의 .git 하위 폴더로 간단히 이동할 수 있습니다.

mkdir clone
mv bare.git clone/.git

core.bare 변경 :

cd clone
git config --local --bool core.bare false

확인하기 위해 기본 원점 refspec을 추가 git fetch하고 git push평소와 같은 기본값을 선택합니다 :

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

그리고 인덱스 파일과 작업 트리를 생성합니다.

git checkout master

실수로 잘못된 위치에 입력 된 경우 파일을 생성하는 git checkout것보다 권장 git reset합니다.


9

원래 포스터의 질문은 간단한 방식으로 작업을 수행 할 공간이 부족하다는 것입니다. 충분한 공간이있는 경우 답은 훨씬 간단합니다.

git clone foo.git foo

내가 이것을 피하고 싶은 이유는 저장소가 커지면 git clone이 때때로 죽을 때입니다. 베어 리포지토리의 rsync를 수행 한 다음 변환하고 싶습니다.
— Sridhar Sarnobat 19

@SridharSarnobat 후 허용 대답에 설명 된 작업 일을 고려 : stackoverflow.com/a/10637882/377270을 - 충분한 여유 공간을 가진 사람들이 사물에게 쉬운 방법을 할 수 있도록 내가 여기에 한 줄 답변을했습니다.
— sarnold

6

디스크 공간이 부족한 경우 일반 저장소로 변환하여 작업 트리를 확장하는 것이 문제가 될 수 있지만 베어 저장소의 내용을 변환하지 않고 찾아 볼 수 있습니다. git cat-file -p <commit-sha>커밋에 사용 하여 참조하는 트리를 확인하십시오. git cat-file -p <blob-sha>Blob에서 참조하는 파일의 내용을 보려면 사용 합니다. 사용 git show <sha>:path샤 중 하나 인 커밋 또는 나무 경로에서 블롭의 내용을 볼 수 있습니다.


1
당신 말이 맞지만 더 편리하게 찾아 볼 필요가 있습니다 (ssh를 통한 파일 관리자에서). 따라서 나는 증가 된 디스크 공간을 가지고 살아야합니다.
— nyi

1
사실 이것은 진짜 문제입니다 (+1). 작업 트리는 종종 디스크 공간의 절반을 차지합니다. 부분적으로는 git 히스토리가 공격적으로 압축되기 때문입니다.
— jpaugh

3

cd 베어 레포로

  1. 어느 한 쪽:
git config core.bare false
git reset --hard
  1. 또는
git clone X.git X

(X라는 이름의 일반 git repo를 제공합니다)


이것이 가장 간단한 해결책이며 2019 년에 이것이 작동하는지 확인할 수 있습니다 (첫 번째 접근 방식).
— Sridhar Sarnobat 19

내가 잊은 작은 메모 하나만 (모든 답변에 적용) 원격 URL을 설정하기 위해 처음 푸시 할 때 구성 파일을 편집해야합니다.
— Sridhar Sarnobat 19

2

다른 작업 트리에서 작업해도 괜찮다면

git worktree add ../repo2
cd ..
git status # now works fine

이것은 클론이 아닙니다.


이것은이 목록 최대 높지 확실하지 왜, 중대하다
— 있는 Nickolai

0

배포 후 배포

베어 원격을 표준 리포지토리로 변환하는 대신 hooks 디렉터리의 수신 후 스크립트를 사용하여 리포지토리를 배포 디렉터리로 확장 할 수 있습니다.

다음은 Push-to-Deploy를 설정하는 좋은 예입니다.

참조의 편의를 위해 위 링크의 스크립트 내용 예제입니다. "master"분기에서 저장소의 상위 디렉토리와 동일한 레벨에있는 "deploy"라는 디렉토리로 푸시 만 배포합니다.

#!/usr/bin/env ruby
# post-receive

# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "

# 2. Only deploy if master branch was pushed
if (branch =~ /master$/) == nil
    puts "Received branch #{branch}, not deploying."
    exit
end

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('../deploy')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.