86

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

我想我可以克隆它:

git clone -l <path_to_bare_repo> <new_normal_repo>

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

4

8 回答 8

126

注意:我在一个非常简单的 1-commit 存储库上对此进行了测试。仔细检查这一点,阅读手册页,并且在遵循您在 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 fetchorigin/master

这些步骤与这个问题的方向相反,“git-convert normal to bare repository” - 特别注意这个答案,它指出上述步骤(我认为是任一方向)执行git-clone. 不过,不确定这是否与您有关,但您git clone在问题中提到了。

于 2012-05-17T14:39:39.837 回答
20

我有一个稍微不同的场景:

解决方案:

  • 在目录中克隆该内容中的裸仓库.git
    git clone --bare https://github.com/user/project .git
  • 将其标记为非裸回购:
    git config --local --bool core.bare false
  • 重置索引(否则,它认为所有内容都已删除,因为.git 仓库不包含文件“ 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 -- .

但我确实侦察了公认的解决方案(通过ADTC添加的有用git reset步骤)更简单。

于 2013-05-16T08:50:16.390 回答
12

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

裸仓库与普通的 .git 文件夹存在三个不同之处:

  • core.bare 在配置文件中设置为 true
  • 索引文件和工作树不存在
  • 未生成“origin”遥控器的默认 refspec

因此,您可以简单地将裸仓库移动到新文件夹的 .git 子文件夹中,

mkdir clone
mv bare.git clone/.git

更改 core.bare:

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

添加一个默认的 origin refspec 来制作git fetchgit push选择与往常一样的默认值:

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

并生成索引文件和工作树:

git checkout master

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

于 2016-04-25T15:06:51.343 回答
12

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

git clone foo.git foo
于 2017-01-26T20:45:38.773 回答
6

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

于 2012-05-17T14:49:56.157 回答
5

cd进入裸回购并做

  1. 任何一个:
git config core.bare false
git reset --hard
  1. 或者
git clone X.git X

(将为您提供名为 X 的常规 git 存储库)

于 2018-01-31T03:41:10.420 回答
2

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

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

请注意,这不是克隆。

于 2017-08-28T12:30:04.227 回答
0

推送部署

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

这是设置 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}'"
于 2019-01-31T18:06:02.200 回答