如果你有一个 Git 远程存储库,你可以通过 SSH git push 访问它,它通常应该1是一个--bare 存储库(请参阅description of setting up a bare repository on a server in the on-line Git book)。裸存储库没有任何地方可以对其进行任何工作。这意味着git status 没有什么要报告的——事实上,如果你有一个裸存储库和cd,你会收到一条错误消息:它需要一个工作目录才能报告任何内容。)
裸存储库的技术定义是git config --get --bool core.bare 打印true。我在/tmp/t 有一个非裸存储库,在这里:
$ cd /tmp/t; git config --get --bool core.bare
false
$ cd /tmp; git clone --bare t bare.t.git
Cloning into bare repository 'bare.t.git'...
done.
$ cd bare.t.git
$ git config --get --bool core.bare
true
但是通过检查通常很明显:如果您的克隆说来源是ssh://some.host/some/dir/repo,并且您可以ssh some.host 和cd /some/dir/repo 和ls,那么“裸”克隆看起来很像@ 的内容非裸克隆上的987654334@目录:
$ cd /tmp/t; ls .git
COMMIT_EDITMSG ORIG_HEAD description index objects
FETCH_HEAD branches gitk.cache info packed-refs
HEAD config hooks logs refs
对比:
$ cd /tmp/bare.t.git; ls
HEAD config hooks objects refs
branches description info packed-refs
(裸克隆缺少一些在非裸克隆中进行普通 Git 工作的文件,但它们显然是相关的。)
1可以推送到非裸存储库——这只是个坏主意。如果你查看自己非裸克隆的.git/config(或者使用更官方的接口git config --get receive.denyCurrentBranch),一般会看到这样的内容:
[receive]
denyCurrentBranch = warn
此处的值可以是refuse、true、warn、false 或ignore 中的任何一个。大多数值都设置为push 只有在推送到“当前”分支之外的某个分支other 时才被接受。
这里的问题是......好吧,假设您登录到其他人推送的服务器上。你瞧,你cd /some/dir/repo 还有所有这些工作文件。
git checkout zorg,编辑出租车司机的数量,git commit 结果非常诱人。但是当其他人在其他地方编辑同一个分支并提交然后git push-es 在你中间做类似的事情时会发生什么?
如果他/她在您开始 commit 之前完成了他/她的推送,那么您就会陷入混乱。通常,你们俩都在服务器以外的系统上执行此操作,并且首先推送的人“获胜”,而另一个人获得失败的“非快进”推送并且知道获取和(合并或重新设置)(@ 987654351@ 或 git pull --rebase 或其他)。
但是你已经在服务器上,所以你不能使用正常的工作流程。事实上,首先要让工作树保持最新是很困难的:你可以用钩子来做到这一点,但是如果你有钩子 git reset --hard 来更新工作树,它会丢弃任何人所做的任何工作2
完全避免这个问题更容易:下令没有工作树,这是一个--bare 克隆。所有的诱惑和问题都消失了。
2在一项工作中,我继承了一个可以做到这一点的设置(git reset --hard 在接收后挂钩中,并且每隔六小时通过cron)。它至少每隔几个月就会引起很多混乱。不幸的是,服务器和目录路径在很多地方都是硬连接的,因此也很难修复(而且这个特殊问题的优先级很低)。我们只是忍受它。
(根据 cmets 的要求,这是“答案”形式的两个 cmets。由于这里有更多空间,我将它们扩展了一点。)