655

如何将“普通”Git 存储库转换为裸存储库?

主要区别似乎是:

  • 在普通的 Git 存储库中,存储库中有一个.git文件夹,其中包含所有相关数据和构成工作副本的所有其他文件

  • 在裸 Git 存储库中,没有工作副本,并且文件夹(我们称之为repo.git)包含实际的存储库数据

4

18 回答 18

682

简而言之:将 的内容替换为repo的内容repo/.git,然后告诉存储库它现在是一个裸存储库。

为此,请执行以下命令:

cd repo
mv .git ../repo.git # renaming just for clarity
cd ..
rm -fr repo
cd repo.git
git config --bool core.bare true

请注意,这与git clone --bare对新位置执行 a 不同(见下文)。

于 2010-02-04T15:06:17.983 回答
260

您的方法看起来可行;裸存储库的文件结构就是 .git 目录中的内容。但我不知道是否有任何文件实际上被更改了,所以如果失败了,你可以这样做

git clone --bare /path/to/repo

您可能需要在不同的目录中执行此操作以避免名称冲突,然后您可以将其移回您想要的位置。您可能需要更改配置文件以指向您的原始仓库所在的位置。

于 2010-02-04T13:26:10.767 回答
123

我认为以下链接会有所帮助

GitFaq:如何使现有的非裸存储库裸露?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
于 2010-08-03T01:46:09.247 回答
78

除非您特别想要或需要在文件系统上调整位,否则创建非裸存储库的裸版本确实非常简单(在此处的其他几篇文章中提到)。它是 git 核心功能的一部分:

git clone --bare existing_repo_path bare_repo_path

于 2013-03-08T17:36:41.977 回答
24

也请考虑使用

git clone --mirror path_to_source_repository path_to_bare_repository

文档中:

设置源存储库的镜像。这意味着 --bare。与 --bare 相比,--mirror 不仅将源的本地分支映射到目标的本地分支,它还映射所有 refs(包括远程跟踪分支、注释等)并设置 refspec 配置,以便所有这些 refs被目标存储库中的 git 远程更新覆盖。

于 2016-08-04T06:40:43.353 回答
10

我只想推送到网络路径上的存储库,但除非该存储库被标记为裸露,否则 git 不会让我这样做。我所需要的只是改变它的配置:

git config --bool core.bare true

除非您想保持文件清洁,否则无需摆弄文件。

于 2016-02-24T06:30:13.853 回答
6

我已经阅读了答案,我已经这样做了:

cd repos
mv .git repos.git
cd repos.git
git config --bool core.bare true # from another answer
cd ../
mv repos.git ../
cd ../
rm -rf repos/ # or delete using a file manager if you like

这将使内容repos/.git保持不变repos.git

于 2010-08-12T03:11:40.570 回答
4

这是我认为最安全和最简单的方法。这里没有什么不是上面提到的。我只想看到一个显示安全的分步程序的答案。您从要使其裸露的存储库 (repo) 启动一个文件夹。我采用了上面隐含的约定,即裸存储库文件夹具有 .git 扩展名。

(1) Backup, just in case.
    (a) > mkdir backup
    (b) > cd backup
    (c) > git clone ../repo
(2) Make it bare, then move it
    (a) > cd ../repo
    (b) > git config --bool core.bare true
    (c) > mv .git ../repo.git
(3) Confirm the bare repository works (optional, since we have a backup)
    (a) > cd ..
    (b) > mkdir test
    (c) > cd test
    (d) > git clone ../repo.git
(4) Clean up
    (a) > rm -Rf repo
    (b) (optional) > rm -Rf backup/repo
    (c) (optional) > rm -Rf test/repo
于 2011-10-14T16:03:31.900 回答
4

简单阅读

专业 Git 书籍:4.2 服务器上的 Git - 在服务器上获取 Git

归结为

$ git clone --bare my_project my_project.git
Cloning into bare repository 'my_project.git'...
done.

然后把my_project.git放到服务器上

主要是, #42试图指出什么答案。Shurely 可以重新发明轮子 ;-)

于 2015-11-04T15:42:22.000 回答
3

这是一个小 BASH 函数,您可以在基于 UNIX 的系统上将其添加到 .bashrc 或 .profile 中。添加后,shell 要么重新启动,要么通过调用source ~/.profile或重新加载文件source ~/.bashrc

function gitToBare() {
  if [ -d ".git" ]; then
    DIR="`pwd`"
    mv .git ..
    rm -fr *
    mv ../.git .
    mv .git/* .
    rmdir .git

    git config --bool core.bare true
    cd ..
    mv "${DIR}" "${DIR}.git"

    printf "[\x1b[32mSUCCESS\x1b[0m] Git repository converted to "
    printf "bare and renamed to\n  ${DIR}.git\n"
    cd "${DIR}.git"
  else
    printf "[\x1b[31mFAILURE\x1b[0m] Cannot find a .git directory\n"
  fi
}

一旦在包含 .git 目录的目录中调用,它将进行适当的更改以转换存储库。如果调用时不存在 .git 目录,则会出现 FAILURE 消息并且不会发生文件系统更改。

于 2015-04-19T01:20:48.783 回答
1

说删除文件和移动 .git 目录的方法并不干净,并且不使用“git”方法做一些应该很简单的事情。这是我发现将普通回购转换为裸回购的最干净的方法。

首先将 /path/to/normal/repo 克隆到一个名为 repo.git 的裸仓库中

git clone --bare /path/to/normal/repo

接下来删除指向 /path/to/normal/repo 的原点

cd repo.git
git remote rm origin

最后,您可以删除原始存储库。那时您可以将 repo.git 重命名为 repo,但表示 git 存储库的标准约定是 something.git,所以我个人会这样保留它。

一旦你完成了所有这些,你就可以克隆你的新的裸仓库(这实际上创建了一个普通的仓库,也是你将它从裸仓库转换为普通仓库的方式)

当然,如果您有其他上游,您需要记下它们,并更新您的裸仓库以包含它。但同样,这一切都可以用 git 命令完成。请记住,手册页是您的朋友。

于 2014-06-04T16:38:06.763 回答
1

这是来自gitglossary的裸存储库的定义:

裸存储库通常是一个具有 .git 后缀的适当命名的目录,它没有任何受修订控制的文件的本地签出副本。也就是说,通常存在于隐藏的 .git 子目录中的所有 Git 管理和控制文件都直接存在于 repository.git 目录中,并且没有其他文件存在和检出。公共存储库的发布者通常会提供裸存储库。

我来到这里是因为我正在玩一个“本地存储库”,并且希望能够做任何我想做的事情,就好像它是一个远程存储库一样。我只是在玩耍,试图了解 git。我假设这是任何想要阅读此答案的人的情况。

我希望获得专家意见或一些具体的反例,但是似乎(在翻阅了我发现的一些 git 源代码之后)只需转到文件.git/config并将core属性设置为true , git会让你做任何事情您想远程对存储库进行操作。即以下行应该存在于:.git/config

[core]
    ...
    bare = true
...

(大致就是这个命令git config --bool core.bare true会做的事情,大概是推荐处理比较复杂的情况)

我对这个说法的理由是,在 git 源代码中,似乎有两种不同的方法来测试一个 repo 是否是裸露的。一种是检查全局变量is_bare_repository_cfg。这是在执行的某些设置阶段设置的,并反映在.git/config文件中找到的值。另一个是函数is_bare_repository()。下面是这个函数的定义:

int is_bare_repository(void)
{
    /* if core.bare is not 'false', let's see if there is a work tree */
    return is_bare_repository_cfg && !get_git_work_tree();
} 

我没有时间也没有专业知识可以绝对自信地说出这一点,但据我所知,如果您将bare属性设置为truein .git/config,这应该总是返回1。该功能的其余部分可能是针对以下情况:

  1. core.bare 未定义(即既不是真也不是假)
  2. 没有工作树(即 .git 子目录是主目录)

稍后我会尝试它,但这似乎表明设置core.bare = true相当于从配置文件中删除 core.bare并正确设置目录。

无论如何,设置core.bare = true肯定会让你推动它,但我不确定项目文件的存在是否会导致其他一些操作出错。这很有趣,我认为推送到存储库并查看本地发生的情况(即运行git status并理解结果)具有指导意义。

于 2020-01-03T13:59:13.347 回答
1

如果您的存储库具有很少的本地签出分支 /refs/heads/* 和很少的远程分支分支 remotes/origin/* 并且如果您想将其转换为所有分支都在 /refs/heads/* 中的 BARE 存储库

您可以执行以下操作来保存历史记录。

  1. 创建一个裸仓库
  2. cd 进入具有本地签出分支和远程分支的本地存储库
  3. git push /path/to/bare/repo +refs/remotes/origin/ :refs/heads/
于 2017-02-03T07:08:50.637 回答
0

我使用以下脚本读取包含我所有 SVN 存储库列表的文本文件并将它们转换为 GIT,然后使用 git clone --bare 转换为裸 git 存储库

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name 
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt 的格式为

repo1_name
repo2_name

users.txt 的格式为

(no author) = Prince Rogers <prince.rogers.nelson@payesley.park.org>

www-data 是 Apache Web 服务器用户,需要权限才能通过 HTTP 推送更改

于 2017-01-03T17:39:15.670 回答
-1

首先,backup您现有的回购:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

其次,运行以下命令:

git clone --bare -l non_bare_repo new_bare_repo
于 2012-02-23T12:54:38.640 回答
-1

补充 2:
写完答案后,如果后面跟着git add *.

我的文件从我的工作文件夹中消失了(只剩.git下了),它再次变得又好又紧凑:

git switch --orphan some_new_branch_name 

如果想要的话,然后转换为裸露的:

git config --bool core.bare true

这样配置包括远程链接被保留:

$ git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=true
remote.origin.url=https://github.com/vmatare/thinkfan.git
remote.origin.fetch=+refs/*:refs/*
remote.origin.mirror=true

补充:
在评论中提到它不会删除“任何被 git 忽略的文件”,在这种情况下,它们需要额外手动删除(或者作为.git子文件夹的存储库本身被移动到其他地方)。

注意:
core.bare true某些操作导致错误之前:

$ git fetch --all
Fetching origin
fatal: Refusing to fetch into current branch refs/heads/devel of non-bare repository
error: Could not fetch origin

some_new_branch_name之后的输出中没有列出git branch。为了进一步测试,我确实得到了文件,并且在输出中git checkout master再次没有,所以我认为除非在那里完成一些工作(和/或执行提交),否则不会将新分支添加到存储库中。some_new_branch_namegit branchorphan

于 2021-12-07T04:23:24.663 回答
-5

Oneliner 用于执行上述所有操作:

for i in `ls -A .`; do if [ $i != ".git" ]; then rm -rf $i; fi; done; mv .git/* .; rm -rf .git; git config --bool core.bare true

(如果发生故障并且您没有备份,请不要怪我:P)

于 2010-06-29T09:45:17.140 回答
-9

哇,令人惊讶的是有多少人对此表示赞同,尤其是考虑到似乎没有一个人停下来问这个人为什么要做他正在做的事情。

裸和非裸 git 存储库之间的唯一区别是非裸版本具有工作副本。您需要一个裸仓库的主要原因是,如果您想将其提供给第三方,您实际上不能直接对其进行处理,因此在某些时候您将不得不克隆它,此时您是回到常规的工作副本版本。

话虽如此,要转换为裸仓库,您所要做的就是确保您没有待处理的提交,然后只需:

rm -R * && mv .git/* . && rm -R .git

好了,裸回购。

于 2012-04-01T13:05:20.057 回答