git 裸和非裸存储库之间的实际区别是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5540883/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 10:31:29  来源:igfitidea点击:

What's the -practical- difference between a Bare and non-Bare repository?

gitrepositorygit-bare

提问by AeroCross

I've been reading about the bare and non-bare / default repositores in Git. I haven't been able to understand quite well (theoretically) about the differences between them, and why I should "push" to a bare repository. Here's the deal:

我一直在阅读有关 Git 中的裸和非裸/默认存储库的信息。我一直无法很好地理解(理论上)它们之间的差异,以及为什么我应该“推送”到一个裸存储库。这是交易:

Currently, I'm the only one working on a project on 3 different computers, but there will be more people involved in it later, so I'm using Git for the version control. I clone the bare repo on all computers, and when I finish my modifications on one of them, I commit and push the changes to the bare repo. From what I've read, the bare repository does NOT have a "working tree", so if I clone the bare repo, I won't have a "working tree".

目前,我是唯一一个在 3 台不同计算机上进行项目的人,但是以后会有更多人参与其中,所以我使用 Git 进行版本控制。我在所有计算机上克隆裸存储库,当我完成对其中一台计算机的修改后,我提交并将更改推送到裸存储库。从我读过的内容来看,裸存储库没有“工作树”,所以如果我克隆裸存储库,我将没有“工作树”。

I'm guessing that the working tree stores the commit information, branches, etc. from the project. That wouldn't appear in the bare repo. So it seems better for me to "push" the commits to the repo with the working tree.

我猜测工作树存储来自项目的提交信息、分支等。那不会出现在裸回购中。所以对我来说,用工作树“推送”对 repo 的提交似乎更好。

Then, why should I use the bare repository and why not? What's the practical difference?That would not be beneficial to more people working on a project, I suppose.

那么,为什么我应该使用裸存储库,为什么不呢?有什么实际区别?我想,这对更多从事项目的人没有好处。

What are your methods for this kind of work? Suggestions?

你对这种工作有什么方法?建议?

采纳答案by Derek Mahar

Another difference between a bare and non-bare repository is that a bare repository does not have a default remote originrepository:

裸存储库和非裸存储库之间的另一个区别是裸存储库没有默认的远程存储库:

~/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

From the manual page for git clone --bare:

从手册页git clone --bare

Also the branch heads at the remote are copied directly to corresponding local branch heads, without mapping them to refs/remotes/origin/. When this option is used, neither remote-tracking branches nor the related configuration variables are created.

远程的分支头也直接复制到相应的本地分支头,而不将它们映射到 refs/remotes/origin/。使用此选项时,既不会创建远程跟踪分支,也不会创建相关的配置变量。

Presumably, when it creates a bare repository, Git assumes that the bare repository will serve as the origin repository for several remote users, so it does not create the default remote origin. What this means is that basic git pulland git pushoperations won't work since Git assumes that without a workspace, you don't intend to commit any changes to the bare repository:

想必,在创建裸仓库时,Git 假定裸仓库将作为多个远程用户的源仓库,因此它不会创建默认的远程源。这意味着基本git pullgit 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$ 

回答by Derek Mahar

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 .gitdirectory 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_DIRlinks a workspace to the repository from which it originates.

裸 Git 存储库和非裸 Git 存储库之间的区别是人为的和误导性的,因为工作区不是存储库的一部分,并且存储库不需要工作区。严格来说,Git 存储库包括那些描述存储库状态的对象。这些对象可能存在于任何目录中,但通常存在于.git工作区顶级目录中的目录中。工作区是一个目录树,代表存储库中的特定提交,但它可能存在于任何目录中,也可能根本不存在。环境变量$GIT_DIR将工作空间链接到它源自的存储库。

Git commands git cloneand git initboth have options --barethat create repositories without an initial workspace. It's unfortunate that Git conflates the two separate, but related concepts of workspace and repository and then uses the confusing term bareto separate the two ideas.

Git 命令git clonegit init两者都具有--bare在没有初始工作区的情况下创建存储库的选项。不幸的是,Git 将工作空间和存储库这两个独立但相关的概念混为一谈,然后使用令人困惑的术语“裸”来区分这两个概念。

回答by Deepak Sharma

A bare repository is nothing but the .gitfolder itself i.e. the contents of a bare repository is same as the contents of .gitfolder inside your local working repository.

裸存储库就是.git文件夹本身,即裸存储库的内容与本地工作存储库中.git文件夹的内容相同。

  • Use bare repository on a remote server to allow multiple contributors to push their work.
  • Non-bare - The one which has working tree makes sense on the local machine of each contributor of your project.
  • 在远程服务器上使用裸仓库,允许多个贡献者推送他们的工作。
  • 非裸 - 具有工作树的树在项目的每个贡献者的本地机器上都有意义。

回答by EML

5 years too late, I know, but no-one actually answered the question:

我知道已经晚了 5 年,但实际上没有人回答这个问题:

Then, why should I use the bare repository and why not? What's the practical difference? That would not be beneficial to more people working on a project, I suppose.

What are your methods for this kind of work? Suggestions?

那么,为什么我应该使用裸存储库,为什么不呢?有什么实际区别?我想,这对更多从事项目的人没有好处。

你对这种工作有什么方法?建议?

To quote directly from the Loeliger/MCullough book (978-1-449-31638-9, p196/7):

直接引用 Loeliger/MCullough 的书 (978-1-449-31638-9, p196/7):

A bare repository might seem to be of little use, but its role is crucial: to serve as an authoritative focal point for collaborative development. Other developers cloneand fetchfrom the bare repository and pushupdates to it... if you set up a repository into which developers pushchanges, it should be bare. In effect, this is a special case of the more general best practice that a published repository should be bare.

一个裸存储库似乎没什么用,但它的作用是至关重要的:作为协作开发的权威焦点。其他开发人员clone以及fetch来自裸存储库和对其的push更新……如果您设置了一个开发人员push更改的存储库,它应该是裸存储库。实际上,这是更通用的最佳实践的一个特例,即已发布的存储库应该是裸的。

回答by mipadi

A non-bare repository simply has a checked-out working tree. The working tree does not store any information about the state of the repository (branches, tags, etc.); rather, the working tree is just a representation of the actual files in the repo, which allows you to work on (edit, etc.) the files.

非裸存储库仅具有已检出的工作树。工作树不存储任何有关存储库状态(分支、标签等)的信息;相反,工作树只是存储库中实际文件的表示,它允许您处理(编辑等)文件。

回答by sehe

A bare repository has benefits in

裸仓库有以下好处

  • reduced disk usage
  • less problems related to remote push (since no working tree is there to get out of synch or have conflicting changes)
  • 减少磁盘使用
  • 与远程推送相关的问题更少(因为没有工作树会失去同步或发生冲突的更改)

回答by Nitin

Non bare repository allows you to (into your working tree) capture changes by creating new commits.

非裸存储库允许您(进入您的工作树)通过创建新提交来捕获更改。

Bare repositories are only changed by transporting changes from other repositories.

裸存储库只能通过传输来自其他存储库的更改来更改。

回答by BuvinJ

I'm certainly not a Git "expert". I have used TortoiseGit for a while, and wondered what it was talking about when it asked me if I wanted to make a "bare" repo whenever I created one. I was reading this tutorial: https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-initand it addresses the issue, but I still was not quite understanding the concept. This one helped a lot: http://bitflop.com/tutorials/git-bare-vs-non-bare-repositories.html. Now, the first one makes sense too!

我当然不是 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 setup a distribution point. It's not intented 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".

根据这些消息来源,简而言之,在要设置分发点的服务器上使用“裸”存储库。它不打算在您的本地机器上使用。您通常将提交从本地机器推送到远程服务器上的裸仓库,然后您和/或其他人从该裸仓库拉到您的本地机器。因此,您的 GitHub、Assembla 等远程存储/分发存储库是创建“裸”存储库的一个示例。如果您要建立自己的类似“共享中心”,您会自己制作一个。

回答by Greg Owen

A default/non-bare Git repo contains two pieces of state:

默认/非裸 Git 存储库包含两个状态:

  1. A snapshotof all of the files in the repository (this is what "working tree" means in Git jargon)
  2. A historyof all changes made to all the files that have ever been in the repository (there doesn't seem to be a concise piece of Git jargon that encompasses all of this)
  1. 一个快照的所有文件的存储库中的(这是Git的行话是什么“工作树”的意思)
  2. 对存储库中所有文件所做的所有更改的历史记录(似乎没有包含所有这些的简洁的 Git 术语)

The snapshotis what you probably think of as your project: your code files, build files, helper scripts, and anything else you version with Git.

快照是什么,你可能认为的项目:你的代码文件,生成文件,辅助脚本和其他任何你的版本使用Git。

The historyis the state that allows you to check out a different commit and get a complete snapshot of what the files in your repository looked like when that commit was added. It consists of a bunch of data structures that are internal to Git that you've probably never interacted with directly. Importantly, the history doesn't just store metadata (e.g. "User U added this many lines to File F at Time T as part of Commit C"), it also stores data (e.g. "User U added these exact linesto File F").

历史上是允许你检查出不同的提交,并得到一个什么在你的仓库中的文件看犯下加入时像一个完整的快照状态。它由一堆 Git 内部的数据结构组成,您可能从未直接与之交互过。重要的是,历史不仅存储元数据(例如“用户 U 在时间 T 将这么多行添加到文件 F 作为提交 C 的一部分”),它还存储数据(例如“用户 U 将这些确切的行添加到文件 F”) )。

The key idea of a bare repository is that you don't actually need to have the snapshot. Git keeps the snapshot around because it's convenient for humans and other non-Git processes that want to interact with your code, but the snapshot is just duplicating state that's already in the history.

裸存储库的关键思想是您实际上不需要拥有快照。Git 保留快照是因为它对于想要与代码交互的人类和其他非 Git 进程来说很方便,但快照只是复制历史中已经存在的状态。

A bare repositoryis a Git repository that does not have a snapshot. It just stores the history.

一个纯仓库是不具有快照的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).

你为什么要这个?好吧,如果您只打算使用 Git 与您的文件进行交互(也就是说,您不打算直接编辑您的文件或使用它们来构建可执行文件),那么您可以通过不保留快照来节省空间。特别是,如果您在某处的服务器上维护一个集中版本的仓库(即您基本上托管自己的 GitHub),那么该服务器可能应该有一个裸仓库(您仍然会在您的服务器上使用非裸仓库)本地机器,因为您可能想要编辑您的快照)。

If you want a more in-depth explanation of bare repos and another example use case, I wrote up a blog post here: https://stegosaurusdormant.com/bare-git-repo/

如果你想更深入地解释裸仓库和另一个示例用例,我在这里写了一篇博文:https: //stegosaurusdormant.com/bare-git-repo/

回答by Christoph

This is not a new answer, but it helped me to understand the different aspects of the answers above (and it is too much for a comment).

这不是一个新答案,但它帮助我理解了上述答案的不同方面(评论太多了)。

Using Git Bash just try:

使用 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/

Same with git --bare:

git --bare

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/