推送不会更新非裸存储库中的工作副本和暂存区域
第一个存储库中的暂存区域似乎包含刚刚推送的更改的相反内容,因为它是一个非裸存储库,这意味着它包含一个工作副本,这也经常被引用作为 Git 文档中的工作(目录)树。另一方面,裸 存储库没有工作副本目录。
由于存储库是非裸存储库,当您推送到它时,推送只会更新分支引用和符号 HEAD 引用,因为 git push 不会在工作副本和暂存区域上操作存在于非裸仓库中。
因此,非裸 repo 的工作副本和暂存区域仍处于与更新 @987654324 的推送之前存在的存储库的相同状态之前 @。换句话说,工作副本和暂存区的实际状态与HEAD 指向的提交状态不匹配。这就是为什么在运行 git status 和 git diff 时会出现两种状态之间的差异的原因:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: plans.txt
$ git diff --staged
diff --git a/plans.txt b/plans.txt
index febb495..ce01362 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1 @@
MWA HA HA HA HA!
-Step 1: set up super secret spy base in Cleveland, Ohio
(次优)解决方案:硬重置
由于工作副本和暂存区域与HEAD 不同步,因此让它们再次匹配的解决方案是简单地使用
git reset --hard HEAD
git reset --hard
将工作区和暂存区重置为HEAD 指向的提交。
但是,这不是理想的解决方案...
理想的解决方案:改为推送到裸存储库
您实际上不应该推送到非裸存储库,因为它们的工作副本和暂存区域与存储库引用不同步的确切问题。相反,除非您有特殊原因推送到非裸存储库,否则您确实应该推送到没有工作副本的裸存储库。
要创建一个裸存储库,只需使用--bare 标志:
# Initialize a bare repo
mkdir bare
cd bare
git init --bare
# Push changes to the bare repo
cd ..
mkdir project
cd project
# Make some changes and commit
git remote add origin ../bare
git push origin master
# Or create a bare clone from another bare or non-bare repo
git clone --bare <repo-path-or-uri>
自 Git 1.6.2 起默认拒绝推送到非裸仓库
请注意since Git version 1.6.2,默认情况下拒绝推送到非裸存储库:
在下一个主要版本中,git push 进入一个分支
当前签出将默认被拒绝。你可以选择
通过设置配置进行这种推送会发生什么
接收存储库中的变量receive.denyCurrentBranch。
事实上,当您尝试使用当前版本的 Git 推送到非裸仓库时,您的推送应该被拒绝并显示以下错误消息(为简洁起见稍作修改):
$ git push origin master
Total 0 (delta 0), reused 0 (delta 0)
error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.
error:
error: You can set 'receive.denyCurrentBranch' configuration variable to
error: 'ignore' or 'warn' in the remote repository to allow pushing into
error: its current branch; however, this is not recommended unless you
error: arranged to update its work tree to match what you pushed in some
error: other way.
error:
error: To squelch this message and still keep the default behaviour, set
error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To non-bare
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'non-bare'
正如上面的错误消息所解释的,您可以通过禁用 remote 非裸存储库中的 receive.denyCurrentBranch 配置设置来禁用阻止您进入非裸存储库的安全检查:
git config receive.denyCurrentBranch warn # Warn when pushing to non-bare repo
git config receive.denyCurrentBranch ignore # Don't even bother warning