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在获取之前无法了解变更。但它不应该说"最新",这完全是不正确的。最好说"不知道远程发生了什么"。
- @但是如果真是这样的话,就必须这么说。即使您进行了一次提取,也可能在一微秒后发生上游提交,所以当您读取状态时,它又过时了。这是像Git这样的分布式版本控制系统的一个特性,需要改变思维习惯,但这是合乎逻辑的。
- 也许这是完全合乎逻辑的,但这根本不是人类的理性。你为什么不设计它来做一个获取,然后声明它是否是最新的?或者更改消息以说明它真正做了什么,例如,"上次检查时间戳时,您的分支使用‘源站/主服务器’是最新的"?或者说,"去拿东西看看你的分行是否是最新的"?
- 因为取数是一个昂贵的网络操作,交换分支是快速和轻量级的。因为Git的设计是离线工作,独立于一个集中的上游服务器。这是dvcs的分布式部分(维基百科页面反复强调"无网络操作"点)。当然可以添加额外的文本(在配置选项后面,这样就不会显示多余的噪音,如果Git是如何工作的),但是在这里要求它不会改变它,请尝试发邮件至[email protected]。
- 正如我在之前的评论中所说,这是一个需要习惯的数字视频控制器的特性,"为什么它不能像我习惯的集中式VCS那样工作?"错过了这一点。我更新了答案,强调它所指的"EDOCX1"(0)实际上是本地文件系统上的一个本地实体,它恰好(有时)跟踪远程repo中的某个远程实体。
- 为什么还要显示消息"你的分支机构是最新的"?我不知道原点/主节点的状态,如果它应该表示原点远程上的实际主节点分支,那么它显然不知道任何方式。
- @Whiterook6我不认为知道源站/主站的状态有什么意义[…]它不告诉你该分支的状态,它告诉你当前分支相对于它跟踪的分支的状态,在OP的情况下正好是origin/master。对于跟踪其他分支的分支,当您通过运行git status请求状态时,这些分支显然是有用的信息。如果它应该表示原始远程上的实际主分支,[…]则不是。
- 如果只需要获取一个引用/提交ID,那么为什么获取一个昂贵的操作?
- @开发,可能有成千上万的提交要获取,这可能是大量的数据。任何网络操作都是昂贵的,而且比检查本地磁盘要慢很多个数量级,而这正是Git设计的目的。数字视频控制系统的关键是独立于网络,独立于中央服务器上的中央存储库。
- 好的,那么在运行git status命令之前,有没有一种方法可以自动强制获取?我们中有相当多的"不懂DVC的用户",他们会发现这比一条无用的"最新"假消息更有用!
- @所以创建一个别名。
- 为了深入了解所涉及的概念,我衷心推荐在本次调查中首次出现的答案"这是长答案"。网址:stackoverflow.com/questions/16408300/…。例如,对于所有想知道远程分支和远程跟踪分支(存储在本地)之间的区别的人来说。
- 这是Git可怕的可用性的完美例子。我喜欢它的功能和灵活性,但是简单地将消息更改为"您的分支是最新的,本地版本的‘源站/主服务器’",这将是一个巨大的改进。这里的混淆在于跟踪远程分支的本地分支源/主(模式与您使用的任何远程/分支匹配)。
- 这种行为不是分布式版本控制系统的一个常见特性,而是git的一个特定特性。例如,第二大最流行的DVC Mercurial没有远程跟踪分支的概念。因此,即使在其他dvcss中有经验的用户看到术语"源站/主服务器",他们也可能会有理由认为它可能是远程分支本身。至于我自己,当我在使用mercurial多年后开始学习git时,我发现"origin/master"完全令人困惑,直到我真正了解git的工作原理。
- @DodgycodeException感谢您的更正。
- 情况总是这样吗?我发誓,在某些系统上,我可以在不提前获取和提前获取或延迟提交的情况下只获取git状态。但也许我的记忆错了…
- @客家信一直都是这样
这是因为您的本地回购还没有与上游的遥控器签入。要按预期进行此工作,请使用git fetch,然后再次运行git status。
让我们研究一个git repo样本来验证your branch (master)是否是up to date和origin/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。
当你跑步时
它在本地的.git/objects文件夹下检索新的git对象。并且git会更新.git/fetch-head,这样现在,它就指向了获取的分支的最新提交。
因此,要查看当前本地分支和从上游提取的分支之间的差异,可以运行
1
| git diff HEAD FETCH_HEAD |
。
- 你不应该在.git目录中分类项目,它不能与压缩的refs一起工作。另外,您描述的获取行为适用于旧版本的Git。
- origin/masterref是否也通过fetch和push得到更新?
- 对的。到目前为止,我使用的是Git 1.8.3。我可以注意到,在2.2.1版中,fetch-head也会在fetch期间得到更新。当出现"您的分支是最新的…"或"您的分支落后于…通过x提交",只有当本地分支跟踪给定的远程分支时才会显示。要让master跟踪origin/master,必须从branch master运行git branch-u origin/master。如果没有跟踪,您仍然需要运行git diff。
- 好吧,那么我建议你纠正"原始/主"引用只有在你推到你的遥控器时才会更新的说法。