如何将普通的Git仓库转换为裸仓库?


601

如何将“正常” Git存储库转换为裸存储库?

主要区别似乎是:

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

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


16
大概这是一个较短的方法:mv repo/.git repo.git; rm -rf repo
jameshfisher 2011年

是的,没错。当我写问题时,这只是我的历史片段,我在另一分钟执行了。
Boldewyn 2011年

54
@eegg使用&&而不是;万一mv失败!

Answers:


608

总之:更换的内容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与对新位置进行操作不同(请参见下文)。


9
感谢您的提示core.bare。现在,在搜索了该选项之后,我可以确认它:kernel.org/pub/software/scm/git-core/docs/git-config.html
Boldewyn

14
谢谢!这对我来说似乎更干净:mv repo / .git repo.git && rm -rf repo && cd repo.git && git config --bool core.bare true
JasonWoof 2012年

56
这比(git clone --bare /path/to/repo)下的答案要复杂和脆弱得多。
djd 2012年

7
rm命令可能* \.[!.]*不是*删除点文件和点目录所必需的。
minopret,2012年

6
@Ciantic:同样,正如我在上面的评论中已经解释的那样,我的答案是3年前给出的,但5个月前有人将问题编辑为完全不同的问题。此页面上的答案将会使任何意义了。该命令序列是直接从问题中复制的,我只添加了最后两行。
约尔格W¯¯米塔格

244

您的方法看起来可行。裸存储库的文件结构就是.git目录中的文件结构。但是我不知道是否真的更改了任何文件,所以如果失败,您可以做

git clone --bare /path/to/repo

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


50
错误,此方法不等效。进行克隆不会保留配置选项,这对于正确操作(例如,使用git-p4)至关重要。另外,克隆会破坏远程,再次使用git-p4之类的东西,您在克隆时会丢失p4 / master分支,因此上述方法是可取的。
nosatalian

26
但是您可以通过复制配置文件的各个部分轻松地传输配置选项。我仍然认为此方法比手动复制和重命名文件更干净。
菲利普

6
由于git-svn缺少对--bare的支持,因此在进行Subversion迁移之后,这是完美的。
Keyo

11
为了避免名称冲突---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
raksja

只要您git update-server-info在创建后在裸仓库上运行,就可以使用。
ACK_stoverflow

116

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

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

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo

2
是的,这正是我搜索的内容,谢谢!但是,他们的第二个建议(git clone)具有上述nosatalian的缺点。
Boldewyn

1
您建议的文档继续说:“更安全的方法是让Git通过执行以下操作来为您处理所有内部设置... git clone --bare -l <​​path_to_repos> <new_dir>”
dafunker

74

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

git clone --bare existing_repo_path bare_repo_path


6
令人惊讶的是,遥遥领先的最佳答案在> 4个月后获得0票。不是很好但很危险的“可接受的答案”有200个!
稳定狗2013年

36
一点也不令人惊奇-这个答案与原始问题所要求的不符。它不转换存储库,而是克隆一个存储库,从而在此过程中丢失信息(例如,远程分支)。
GreenAsJade

15

也请考虑使用

git clone --mirror path_to_source_repository

文档中

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


似乎这是执行OP想要的最简洁,完整和安全的方法(相对于just clone)。我想念什么吗?是--mirror最近才加入的吗?
Craig Silver

@CraigSilver:否,正如我在文档历史记录中所看到的那样,--mirror它可以从1.7版获得,因此已经相当长了。您可以在这里查看
Jacek Krawczyk

7

我只想推送到网络路径上的存储库,但是git不允许我这样做,除非该存储库被标记为裸机。我需要做的就是更改其配置:

git config --bool core.bare true

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


3
当您还想在远程存储库的工作树上工作时,这很危险。有时候,您迟早会还原更改是因为您的远程工作树和索引与存储库不同步。如果您不完全知道自己在做什么,则不建议使用此解决方案。
Boldewyn

没错,您不应该在远程裸仓库的树上工作。
斯莱恩

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


4

我认为这是最安全,最简单的方法。上面没有任何内容。我只想看到一个显示安全分步过程的答案。您从要裸露的存储库(仓库)中启动一个文件夹。我采用了上面隐含的约定,即裸仓库文件夹的扩展名为.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

1
由于您使用git clone进行备份,因此这实际上并不安全。通过克隆进行备份将导致您丢失一些配置,这在某些情况下对于存储库可能至关重要。
Lie Ryan

注意。我曾经关心过的唯一配置是我所有本地存储库的全局配置。
sdesciencelover 2012年

4

简单阅读

Pro 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的答案试图指出。也许有人可以彻底改造轮子;-)


我看不到,这个答案增加了什么,在其他任何答案中都没有任意讨论(包括投票否决)。你能澄清一下吗?(顺便说一句:Pro Git书中说:“这大致相当于……”,并且这里已经讨论了确切的等效性。)
Boldewyn 2015年

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消息,并且不会发生文件系统更改。


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命令完成。记住手册页是您的朋友。


1
您有没有想过阅读其他答案?尤其是@jonescb和@nosatalian对它的评论?“ git”方法是这样的:“对纯文本文件进行尽可能多的处理”。您应该开始调查.git文件夹的内部。了解各个部分如何组合在一起具有很高的教育意义。
Boldewyn 2014年

1

如果您的存储库中没有几个本地检出分支/ refs / heads / *和几个远程分支机构remotes / origin / *,并且如果您要将其转换为一个BARE存储库,则所有分支都位于/ refs / heads / *

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

  1. 创建一个裸仓库
  2. cd进入具有本地检出分支和远程分支的本地存储库
  3. git push / path / to / bare / repo + refs / remotes / origin / :refs / heads /

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推送更改


0

下面是一个定义纯仓库gitglossary

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

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

我会为一个专家的意见或某些特定的反例的爱,但它似乎只是要文件(通过一些Git的源代码里翻找,我发现后),.git/config并设置核心属性裸露真实,git会让你做什么您想远程处理存储库。即以下行应存在于.git/config

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

(这大致就是该命令git config --bool core.bare true将要执行的操作,建议您使用它来处理更复杂的情况)

我对此主张的理由是,在git源代码中,似乎有两种不同的测试回购是否裸露的方式。一种是通过检查全局变量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是未定义的(即既不是true也不是false)
  2. 没有工作树(即.git子目录是主目录)

稍后我将进行实验,但这似乎表明设置core.bare = true等效于从配置文件中删除core.bare并正确设置目录。

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


-1

首先,backup您现有的仓库:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

其次,运行以下命令:

git clone --bare -l non_bare_repo new_bare_repo

中间克隆是做什么用的?
稳定狗2013年

-4

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)


-9

哇,令人惊讶的是有这么多人参与其中,尤其是考虑到似乎并不是没有一个人停下来问这个人为什么在做他正在做的事情。

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

话虽如此,要转换为裸仓库,您要做的就是确保您没有未决的提交,然后执行以下操作:

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

没关系,裸仓库。


11
这将使其变得不够裸露。尝试将其推入。您也需要做git config core.bare true
安东尼·哈奇金斯

我没有downvote,但我只是想指出,这个答案的第1部分解释了为什么你想裸回购VS非裸一种是OK,但它不包含足够的技术细节,以及可能有点不准确。但是,对于答案的第二部分,尽管这些命令确实将您的存储库设置为裸机,但Anthony是正确的,您仍然需要进行设置git config core.bare true,就像在此答案中一样
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.