当上游存在更改时,为什么 git 状态显示分支是最新的?

Why does git status show branch is up-to-date when changes exist upstream?

更改存在于跟踪分支的上游,但是当我键入 git status 时,它表明我的本地分支是最新的。这是新行为,我是否更改了配置设置,还是出了什么问题?

感谢您的帮助。

ubuntu@host:/my/repo# git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean


ubuntu@host:/my/repo# git pull
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (11/11), done.
From bitbucket.org:my/repo
   1234567..abcdefg  master     -> origin/master
Updating 1234567..abcdefg
Fast-forward
 file1        |  1 -
 file2        | 43 +++++++++++++++++++++++++++++++++++++++++++
 file3        | 21 ++++++++++++---------
 file4        | 21 ++++++++++++---------
 4 files changed, 67 insertions(+), 19 deletions(-)
 create mode 100644 file5

这是因为您的本地存储库尚未与上游遥控器签入。要让这项工作如您所愿,请再次使用 git fetch 然后 运行 a git status

状态告诉您的是,您在名为 origin/master 的引用后面,它是您本地存储库中的本地引用 。在这种情况下,ref 恰好跟踪某个远程分支中的分支,称为 origin,但状态不会告诉您有关远程分支的任何信息。它告诉您有关 ref 的信息,它只是存储在本地文件系统上的提交 ID(在这种情况下,它通常位于本地存储库中名为 .git/refs/remotes/origin/master 的文件中)。

git pull 做了两个操作;首先它执行 git fetch 来更新远程仓库中的提交(更新本地仓库中的 origin/master ref),然后它执行 git merge 合并这些提交进入当前分支。

直到你执行 fetch 步骤(无论是自己还是通过 git pull)你的本地仓库无法知道上游还有额外的提交,并且只有 git status看看你当地的 origin/master ref.

git status 表示最新时,它表示 "up-to-date with the branch that the current branch tracks",在这种情况下表示 "up-to-date with the local ref called origin/master"。这仅等于 "up-to-date with the upstream status that was retrieved last time we did a fetch" 与 "up-to-date with the latest live status of the upstream".

不同

为什么会这样?那么 fetch 步骤可能是一个缓慢且昂贵的网络操作。 Git(和其他 distributed version control systems)的设计是为了避免在不必要时进行网络操作,并且与许多人习惯的典型客户端-服务器系统完全不同(尽管如在下面的评论中,Git 的 "remote tracking branch" 概念在这里引起混淆,并非所有 DVCS 都共享)。完全可以离线使用 Git,无需连接到中央服务器,git status 的输出反映了这一点。

在 Git 中创建和切换分支(并检查它们的状态)应该是轻量级的,而不是对集中式系统执行缓慢的网络操作。设计 Git 和 git status 输出时的假设是用户理解这一点(如果您已经知道 Git 是如何工作的,那么太多 Git 功能才有意义)。随着许多不熟悉 DVCS 的用户采用 Git,此假设并不总是有效。

"origin/master"指的是指向分支"origin/master"的HEAD提交的引用。 引用是 Git 对象的人性化别名,通常是提交对象。 "origin/master" 参考仅在您 git push 到您的遥控器 (http://git-scm.com/book/en/v2/Git-Internals-Git-References#Remotes) 时更新。

从项目的根目录中,运行:

cat .git/refs/remotes/origin/master

将显示的提交 ID 与:

进行比较
cat .git/refs/heads/master

它们应该是相同的,这就是为什么 Git 说 master 是最新的 origin/master

当你运行

git fetch origin master

这会在 .git/objects 文件夹下本地检索新的 Git 对象。 Git 更新 .git/FETCH_HEAD 现在,它指向获取分支的最新提交。

因此,要查看当前本地分支与从上游获取的分支之间的差异,您可以 运行

git diff HEAD FETCH_HEAD

让我们查看示例 git 存储库以验证 your branch (master) 是否为 up to dateorigin/master

验证本地主控正在跟踪origin/master:

$ git branch -vv
* master a357df1eb [origin/master] This is a commit message

关于本地 master 分支的更多信息:

$ git show --summary
commit a357df1eb941beb5cac3601153f063dae7faf5a8 (HEAD -> master, tag: 2.8.0, origin/master, origin/HEAD)
Author: ...
Date:   Tue Dec 11 14:25:52 2018 +0100

    Another commit message

验证 origin/master 是否在同一提交上:

$ cat .git/packed-refs | grep origin/master
a357df1eb941beb5cac3601153f063dae7faf5a8 refs/remotes/origin/master

我们可以看到相同的散列,可以肯定地说分支与远程分支是一致的,至少在当前 git 存储库中是这样。

虽然这些都是可行的答案,但我决定给出我的方法来检查本地存储库是否与远程存储库一致,而无需获取或拉取。为了查看我的分支在哪里,我简单地使用:

git remote show origin

它的作用是 return 所有当前跟踪的分支,最重要的是 - 它们是最新的、领先于或落后于远程原始分支的信息。在上面的命令之后,这是 returned:

的一个例子
  * remote origin
  Fetch URL: https://github.com/xxxx/xxxx.git
  Push  URL: https://github.com/xxxx/xxxx.git
  HEAD branch: master
  Remote branches:
    master      tracked
    no-payments tracked
  Local branches configured for 'git pull':
    master      merges with remote master
    no-payments merges with remote no-payments
  Local refs configured for 'git push':
    master      pushes to master      (local out of date)
    no-payments pushes to no-payments (local out of date)

希望这对某人有所帮助。

一些琐碎的答案在某些情况下却很准确,比如把我带到这里的那个。 我在一个对我来说是新的回购协议中工作,我添加了一个文件,该文件在状态上并不被视为新文件。

最终文件与 .gitignore 文件中的模式匹配。

在这种情况下使用 git 添加并整合所有未决文件然后使用 git commit 然后 git push

git 添加 - 整合所有 pedent 文件

git 提交 - 保存提交

git 推 - 保存到存储库

我遇到过类似的问题,我在网上到处搜索解决方案,并尝试遵循它们。 None 对我有用。这些是我解决问题的步骤。

创建新的 repo 并将现有代码再次推送到新的 repo

git 如果您的存储库中已有 .git/ 文件夹,则 init 不会初始化。所以,对于你的情况,做 -

(1) rm -rf .git/

(2) git 初始化

(3) git 远程添加源 https://repository.remote.url

(4) git commit -m “提交消息”

(5) git push -f origin master

请注意,此存储库的所有 git 配置(如远程存储库)已在步骤 1 中清除。因此,您必须重新设置所有远程存储库 URL。

另外,注意第 5 步中的 -f:远程已经有一些包含 n 次提交的代码库,而您正试图将所有这些更改合并到一次提交中。因此,force-pushing 需要对远程进行更改。