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

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

主要的区别似乎是:

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

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

253241 次浏览

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

git clone --bare /path/to/repo

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

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

为此,执行以下命令:

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不同(见下文)。

用于执行上述所有操作的onlineer:

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)

我已经看了答案,我是这么做的:

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

以下是我认为最安全、最简单的方法。这里没有没有上面说过的。我只是想看到一个答案,显示一个安全的一步一步的程序。您从想要使其为空的存储库(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

首先,backup你现有的回购:

(a)  mkdir backup


(b)  cd backup


(c)  git clone non_bare_repo

其次,运行以下命令:

git clone --bare -l non_bare_repo new_bare_repo

哇,居然有这么多人插话,真是令人惊讶,尤其是考虑到似乎没有一个人停下来问这个人为什么要做他正在做的事情。

裸git和非裸git仓库之间的唯一区别是,非裸版本有一个工作副本。你需要裸回购的主要原因是,如果你想让第三方可以使用它,你实际上不能直接使用它,所以在某种程度上,你将不得不克隆它,此时你就会回到常规的工作副本版本。

也就是说,要转换为裸回购,你所要做的就是确保你没有提交挂起,然后:

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

这就对了,裸回购。

除非您特别想要或需要在文件系统上摆弄比特,否则创建一个非裸库的裸版本真的非常简单(在这里的其他几篇文章中提到过)。它是git核心功能的一部分:

# EYZ0

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

第一个克隆/path/to/normal/repo到一个名为repo.git的裸repo

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

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

cd repo.git
git remote rm origin

最后,您可以删除原来的回购。你可以重命名repo。在这一点上,Git的回购,但标准约定,以表示一个Git存储库是什么。git,所以我个人会这样做。

一旦你完成了所有这些,你可以克隆你的新裸回购(这实际上创建了一个正常的回购,也是你如何将它从裸转换为正常)

当然,如果你有其他的上行流,你会想要记录它们,并更新你的裸回购以包括它。但是同样,这一切都可以用git命令来完成。请记住手册页是您的朋友。

下面是一个小BASH函数,您可以将它添加到基于UNIX的系统上的.bashrc或.profile中。一旦添加,shell要么重新启动,要么通过调用source ~/.profilesource ~/.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消息,并且不会发生文件系统更改。

简单的读

Pro Git Book: 4.2 Git on the Server-Getting Git on a Server .

归结起来是什么

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

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

主要是,# 42试图指出的答案。当然,人们可以重新发明轮子;-)

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

git config --bool core.bare true

除非你想保持文件整洁,否则没必要乱动。

也请大家考虑使用

git clone --mirror path_to_source_repository path_to_bare_repository

文档:

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

我使用下面的脚本读取一个文本文件,其中包含我所有的SVN repo,并将它们转换为GIT,然后使用GIT clone——bare转换为一个裸露的GIT repo

#!/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有这个格式

# EYZ0

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

如果你有一个存储库,只有很少的本地签出分支/refs/heads/*和很少的远程分支分支/origin/* and,如果你想把它转换成一个BARE存储库,所有分支都在/refs/heads/*中

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

  1. 创建裸存储库
  2. CD到具有本地签出分支和远程分支的本地存储库中
  3. git push /path/to/bare/repo +refs/remotes/origin/参:/ /

下面是gitglossary裸存储库的定义:

裸存储库通常是一个适当命名的、后缀为.git的目录,该目录不包含任何受修订控制的文件的本地签出副本。也就是说,通常出现在隐藏的. Git子目录中的所有Git管理和控制文件都直接出现在存储库中。取而代之的是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属性设置为true.git/config,这应该总是返回1。函数的其余部分可能用于以下情况:

  1. 核心。Bare没有定义(即既非真也非假)
  2. 没有工作树(例如。git子目录是主目录)

稍后我将尝试使用它,但这似乎表明设置核心。裸=真相当于从配置文件中删除core.bare并正确设置目录。

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

增加2:
在写下答案后,意识到接受的答案可能会在我的PC上产生相同的结果,如果后面跟着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
< p > # EYZ0
在评论中提到,它不会删除“任何git忽略的文件”,这种情况下,它们需要额外手动删除(或存储库本身,即.git子文件夹被移动到其他地方) < p >指出:
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,我得到了文件,在git branch的输出中再次没有some_new_branch_name,所以我认为新的orphan分支不会被添加到存储库中,除非那里完成了一些工作(和/或提交执行)。