为什么我的远程Git存储库在推送后会有未提交的更改?

时间:2014-07-31 04:19:07

标签: git git-push git-non-bare-repository

我使用以下命令设置了一个新的Git存储库:

mkdir plans-for-world-domination
cd plans-for-world-domination
git init
echo "MWA HA HA HA HA!" > plans.txt
git add .
git commit -m "Beginning my plans..."

然后我复制了这个存储库,进行了一些更改,提交了它们,然后尝试推送:

cd ..
git clone plans-for-world-domination clone
cd clone
echo "Step 1: set up super secret spy base in Cleveland, Ohio" >> plans.txt
git commit -am "Update plans"
git push origin master

当我cd回到plans-for-world-domination存储库时,staging-area / index中有一些更改,这些更改是我刚刚推送的更改的 reverse

$ cd ../plans-for-world-domination
$ 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

为什么我的第一个回购包含这些与我刚刚推送的相反的非暂停更改,以及如何解决此问题?

1 个答案:

答案 0 :(得分:7)

请求不要更新非裸存储库中的工作副本和临时区域

第一个存储库中的暂存区域似乎包含刚刚推送的更改的反向,因为它是非裸存储库,这意味着它包含一个工作副本,这是在Git文档中也经常被称为工作(目录)树。另一方面, Bare 存储库没有工作副本目录。

由于存储库是非裸的,当您按下它时,推送仅更新分支引用和符号HEAD引用,因为git push不会对工作进行操作 - 非裸仓库中存在的复制和暂存区域。

因此,非裸仓库的工作副本和临时区域仍然保留在之前存在的存储库的相同状态更新的推送{{ 1}}。换句话说,工作副本和临时区域的实际状态与 HEAD指向的提交状态不匹配。这就是为什么在HEADgit 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

将work-coy和staging-area重置为git reset --hard HEAD git reset --hard 指向的提交。

然而,这不是理想的解决方案......

理想的解决方案:推送到裸存储库

您并不是真的应该推送到非裸存储库,因为它们的工作副本和暂存区域与存储库引用解除同步的确切问题。相反,除非你有一个不寻常的理由推送到非裸存储库,否则你真的应该推送到裸存储库,而不是没有工作副本。

要创建裸存储库,只需使用HEAD标志:

--bare

默认情况下,从Git 1.6.2

开始,拒绝推送到非裸存储库

请注意,since Git version 1.6.2默认拒绝推送到非裸存储库:

  

在下一个主要版本中,# 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 push

事实上,当您尝试使用当前版本的Git推送到非裸机时,应该拒绝您的推送,并显示以下错误消息(为了简洁起见略有修改):

receive.denyCurrentBranch

如上面的错误消息所示,您可以通过禁用远程非裸机中的$ 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' 配置设置来禁用安全检查,以防止您进入非裸机状态回购:

receive.denyCurrentBranch