为什么当上游存在变化时,git status show branch是最新的?


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

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

谢谢你的帮助。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

状态告诉您的是,您在名为origin/master的引用后面,该引用是您的本地回购中的本地引用。在这种情况下,REF正好跟踪某个远程分支,称为origin,但状态并没有告诉您有关远程分支的任何信息。它向您介绍了REF,它只是存储在本地文件系统上的一个提交ID(在本例中,它通常位于本地repo中名为.git/refs/remotes/origin/master的文件中)。

git pull执行两个操作;首先它执行git fetch以更新远程回购中的承诺(更新本地回购中的origin/masterRef),然后执行git merge将这些承诺合并到当前分支。

在执行fetch步骤(单独或通过git pull)之前,您的本地回购没有办法知道上游有额外的承诺,而git status只查看您的本地origin/master参考。

git status表示最新时,表示"与当前分行跟踪的分行保持最新",在本例中表示"与本地参考文件origin/master保持最新"。这只等同于"最新的上游状态,即我们上次执行fetch时检索到的上游状态",与"最新的上游实时状态"不同。

为什么会这样?那么,fetch步骤可能是一个缓慢而昂贵的网络操作。Git(和其他分布式版本控制系统)的设计是为了避免不必要的网络操作,它与许多人习惯的典型客户机-服务器系统完全不同(尽管正如下面的评论所指出的那样,Git的"远程跟踪分支"的概念在这里引起了混乱,但Al不共享。l dvcss)。完全可以离线使用git,不需要连接到集中服务器,git status的输出反映了这一点。

在Git中创建和交换分支(并检查它们的状态)应该是轻量级的,而不是对集中系统执行缓慢的网络操作。在设计git和git status输出时,假设用户理解这一点(太多的git特性只有在您已经知道git是如何工作的情况下才有意义)。随着越来越多的不熟悉DVC的用户采用Git,这种假设并不总是有效的。


这是因为您的本地回购还没有与上游的遥控器签入。要按预期进行此工作,请使用git fetch,然后再次运行git status


让我们研究一个git repo样本来验证your branch (master)是否是up to dateorigin/master

确认本地主机正在跟踪源站/主机:

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

有关本地主分支的详细信息:

1
2
3
4
5
6
$ 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

验证源站/主服务器是否处于同一提交状态:

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

我们可以看到相同的散列,可以安全地说分支与远程分支一致,至少在当前的git repo中是一致的。


"原点/主节点"是指指向分支"原点/主节点"的头提交的引用。引用是git对象的友好别名,通常是commit对象。"源站/主站"引用只有当您的git push到您的远程(http://git scm.com/book/en/v2/git internals git references_remotes)时才会更新。

从项目的根目录中运行:

1
cat .git/refs/remotes/origin/master

将显示的提交ID与以下内容进行比较:

1
cat .git/refs/heads/master

他们应该是一样的,这就是为什么Git说master是最新的origin/master

当你跑步时

1
git fetch origin master

它在本地的.git/objects文件夹下检索新的git对象。并且git会更新.git/fetch-head,这样现在,它就指向了获取的分支的最新提交。

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

1
git diff HEAD FETCH_HEAD