我一直在阅读Git中的裸库和非裸库/默认库。我还不能很好地(从理论上)理解它们之间的区别,以及为什么我应该“推送”到一个裸库。事情是这样的:
目前,我是唯一一个在3台不同计算机上从事项目的人,但以后会有更多人参与其中,所以我使用Git进行版本控制。我在所有计算机上克隆裸回购,当我完成对其中一台计算机的修改时,我提交并将更改推到裸回购。据我所知,裸库没有“工作树”,所以如果我克隆裸库,我就不会有“工作树”。
我猜工作树存储了来自项目的提交信息、分支等。这不会出现在裸回购中。因此,对我来说,用工作树将提交“推”到repo似乎更好。
那么,为什么我应该使用裸库,为什么不呢?实际的区别是什么?我想,这对更多人参与一个项目没有好处。
你做这种工作的方法是什么?建议吗?
裸库和非裸库的另一个区别是,裸库没有默认的远程源存储库:
~/Projects$ git clone --bare test bare
Initialized empty Git repository in /home/derek/Projects/bare/
~/Projects$ cd bare
~/Projects/bare$ git branch -a
* master
~/Projects/bare$ cd ..
~/Projects$ git clone test non-bare
Initialized empty Git repository in /home/derek/Projects/non-bare/.git/
~/Projects$ cd non-bare
~/Projects/non-bare$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
从手册页的git克隆——bare:
同时,分支的头在远程
是否直接复制到相应的
本地分支头,没有映射
它们指向refs/remotes/origin/。当
这两个选项都没有使用
远程跟踪分支机构也没有
相关配置变量为
创建。
假设,在创建裸存储库时,Git假定裸存储库将作为几个远程用户的原始存储库,因此它不会创建默认的远程源存储库。这意味着基本的git pull和git push操作将无法工作,因为git假设没有工作区,你不打算向裸库提交任何更改:
~/Projects/bare$ git push
fatal: No destination configured to push to.
~/Projects/bare$ git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.
~/Projects/bare$
The distinction between a bare and non-bare Git repository is artificial and misleading since a workspace is not part of the repository and a repository doesn't require a workspace. Strictly speaking, a Git repository includes those objects that describe the state of the repository. These objects may exist in any directory, but typically exist in the .git directory in the top-level directory of the workspace. The workspace is a directory tree that represents a particular commit in the repository, but it may exist in any directory or not at all. Environment variable $GIT_DIR links a workspace to the repository from which it originates.
Git命令Git clone和Git init都有选项——bare,可以在没有初始工作区的情况下创建存储库。不幸的是,Git将工作空间和存储库这两个独立但相关的概念合并在一起,然后使用令人困惑的术语bare来区分这两个概念。
我当然不是Git“专家”。我使用TortoiseGit有一段时间了,当我创建一个“裸”回购时,它问我是否想要创建一个“裸”回购,我想知道它在说什么。我正在阅读这个教程:https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init,它解决了这个问题,但我仍然不太理解这个概念。这个帮助很大:http://bitflop.com/tutorials/git-bare-vs-non-bare-repositories.html。第一个也说得通!
According to these sources, in a nutshell, a "bare" repo is used on a server where you want to set up a distribution point. It's not intended for use on your local machine. You generally push commits from your local machine to a bare repo on a remote server, and you and/or others pull from that bare repo to your local machine. So your GitHub, Assembla, etc. remote storage/distribution repo is an example where a "bare" repo is created. You would make one yourself if you were setting up your own analogous "sharing center".
这不是一个新的答案,但它帮助我理解上述答案的不同方面(这对于评论来说太多了)。
使用Git Bash试试:
me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:11 ../
me@pc MINGW64 /c/Test
$ git init
Initialized empty Git repository in C:/Test/.git/
me@pc MINGW64 /c/Test (master)
$ ls -al
total 20
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:11 ../
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 .git/
me@pc MINGW64 /c/Test (master)
$ cd .git
me@pc MINGW64 /c/Test/.git (GIT_DIR!)
$ ls -al
total 15
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 ../
-rw-r--r-- 1 myid 1049089 130 Apr 1 11:35 config
-rw-r--r-- 1 myid 1049089 73 Apr 1 11:35 description
-rw-r--r-- 1 myid 1049089 23 Apr 1 11:35 HEAD
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 hooks/
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 info/
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 objects/
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:35 refs/
git也是一样:
me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:36 ./
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:11 ../
me@pc MINGW64 /c/Test
$ git init --bare
Initialized empty Git repository in C:/Test/
me@pc MINGW64 /c/Test (BARE:master)
$ ls -al
total 23
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:36 ./
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:11 ../
-rw-r--r-- 1 myid 1049089 104 Apr 1 11:36 config
-rw-r--r-- 1 myid 1049089 73 Apr 1 11:36 description
-rw-r--r-- 1 myid 1049089 23 Apr 1 11:36 HEAD
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:36 hooks/
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:36 info/
drwxr-xr-x 1 myid 1049089 0 Apr 1 11:36 objects/
默认/非裸的Git repo包含两段状态:
存储库中所有文件的快照(这就是Git术语中“工作树”的含义)
对存储库中所有文件所做的所有更改的历史记录(似乎没有一个简洁的Git术语包含所有这些内容)
快照就是您可能认为的项目:您的代码文件、构建文件、助手脚本以及其他使用Git进行版本管理的东西。
历史记录是一种状态,它允许您检出不同的提交,并获得添加该提交时存储库中的文件的完整快照。它由一堆Git内部的数据结构组成,您可能从未直接与它们交互过。重要的是,历史记录不仅仅存储元数据(例如。“用户U在时间T向文件F添加了这么多行,作为提交C的一部分”),它还存储数据(例如。“用户U将这些确切的行添加到文件F”)。
裸存储库的关键思想是您实际上不需要快照。Git保留快照,因为它方便人类和其他想要与您的代码交互的非Git进程,但快照只是复制历史记录中已经存在的状态。
裸存储库是指没有快照的Git存储库。它只是存储历史。
Why would you want this? Well, if you're only going to interact with your files using Git (that is, you're not going to edit your files directly or use them to build an executable), you can save space by not keeping around the snapshot. In particular, if you're maintaining a centralized version of your repo on a server somewhere (i.e. you're basically hosting your own GitHub), that server should probably have a bare repo (you would still use a non-bare repo on your local machine though, since you'll presumably want to edit your snapshot).
如果您想要更深入地了解裸回购和另一个示例用例,我在这里写了一篇博客文章:https://stegosaurusdormant.com/bare-git-repo/