如何将裸git存储库转换为普通存储库(就地)?

时间:2012-05-17 14:12:32

标签: git git-bare

我有一个简单的git存储库,但需要通过ssh访问和浏览其内容(在文件管理器中,如用户体验)。

我认为我可以克隆它:

git clone -l <path_to_bare_repo> <new_normal_repo>

但是,我的存储库大小约为20GB,我没有足够的空间来复制它。有没有办法将裸存储库就地转换为最终的工作副本?

8 个答案:

答案 0 :(得分:92)

注意:我在非常简单的 1-commit存储库上对此进行了测试。仔细检查一下,阅读man pages,并且在按照您在StackOverflow上找到的建议之前,总是很高兴您已经备份了。 (你做备份,对吗?)

--bare存储库转换为非裸存储:

  1. 在存储库的顶层创建一个.git文件夹。
  2. 将存储库管理事物(HEAD branches config description hooks info objects refs等)移动到刚刚创建的.git中。
  3. 运行git config --local --bool core.bare false将本地git-repository转换为非裸机。
  4. (通过Tamás Pap发表评论)在第3步之后,您会看到您在分支机构master(或您的主分支机构所在的分支机构),并且您的所有文件都是已删除,删除已暂停。这很正常。只需手动结帐master,或执行git reset --hard,即可完成。
  5. (解决Royi报告的问题).git/config部分的fetch = +refs/heads/*:refs/remotes/origin/*之后修改url = <...>文件添加行[remote "origin"]。否则git fetch将看不到origin/master和其他来源的分支。
  6. 这些步骤与this question相反,“git-convert normal to bare repository” - 特别是注意this answer,其中说明了上述步骤(我认为,在这两个方向中)与<{1}}进行不同。不过,不确定这是否与您相关,但您在问题中提到了git-clone

答案 1 :(得分:15)

我的情况略有不同:

解决方案:

  • .git目录中克隆该内容中的裸仓库:
    git clone --bare https://github.com/user/project .git
  • 将其标记为非裸露的回购:
    git config --local --bool core.bare false
  • 重置索引(否则,它认为所有内容都已删除,因为.git repo不包含文件“index”。)
    git reset HEAD -- .
    这将恢复.git/index

我已经有效地将一个裸露的回购变成了一个非裸露的回购,同时保留了我以前得到的内容 我多年来使用的full script涉及以下步骤:

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 -- .

但是我确实调查了accepted solutionhelpful git reset step added ADTC)更简单。

答案 2 :(得分:10)

简化和组合答案中的信息:

有三个区别使得裸仓库与普通的.git文件夹不同:

  • core.bare在配置文件
  • 中设置为true
  • 索引文件和工作树不存在
  • &#34; origin&#34;的默认refspec远程未生成

所以,你可以简单地将你的裸仓库移动到新文件夹的.git子文件夹,

mkdir clone
mv bare.git clone/.git

更改core.bare:

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

添加默认的原点refspec使git fetchgit push选择与往常相同的默认值:

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

生成索引文件和工作树:

git checkout master

我建议git checkout而不是git reset生成文件,以防万一意外输入错误的位置。

答案 3 :(得分:6)

如果磁盘空间不足,通过转换为普通存储库来扩展工作树将是一个问题,但您可以浏览裸存储库的内容而无需转换它。在任何提交上使用git cat-file -p <commit-sha>以查看它所引用的树。使用git cat-file -p <blob-sha>查看blob引用的文件的内容。使用git show <sha>:path,其中sha是提交或树,以查看路径中blob的内容。

答案 4 :(得分:6)

原始海报的问题是没有足够的空间以简单的方式做事。对于那些有足够空间的人来说,答案要简单得多:

git clone foo.git foo

答案 5 :(得分:1)

如果您不介意在不同的工作树上工作,那么

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

请注意,这不是克隆。

答案 6 :(得分:0)

进入裸仓库并执行

git config core.bare false

git reset --hard

git clone X.git X(将为您提供名为X的常规git仓库)

答案 7 :(得分:0)

即插即用

您可以使用hooks目录中的post-receive脚本,而不是将裸机远程转换为标准存储库,以将存储库扩展到部署目录。

Here is a good example of setting up 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}'"