ChatGPT解决这个技术问题 Extra ChatGPT

git:您的分支领先于 X 次提交

这实际上是如何发生的?

目前我自己在一个仓库中工作,所以这是我的工作流程:

更改文件 Commit 重复 1-2 直到满意 Push to master

然后,当我执行 git status 时,它告诉我我的分支领先 X 次提交(大概与我所做的提交次数相同)。是因为当您推送代码时,它实际上并没有更新您的本地缓存文件(在 .git 文件夹中)? git pull 似乎“修复”了这条奇怪的消息,但我仍然很好奇它为什么会发生,也许我使用 git 错误?

包括消息中打印的分支

我的本地分支领先于主人

你在哪里推/拉当前分支

我正在推送到 GitHub 并拉到我当时正在使用的任何一台计算机上,我的本地副本始终是最新的,因为我是唯一一个在使用它的人。

它实际上并没有检查远程仓库

我就是这么想的,我想我会确保我对它的理解是正确的。

您是否向它传递了一些额外的论点?

不是我能看到的,也许我这边有一些有趣的配置?

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
您的 push 做得如何?您的远程和分支配置设置是什么?
它实际上并没有检查远程仓库,您需要在执行推送后执行 git fetch 获取远程仓库上的最新信息,这将更新它用于跟踪的本地“远程”分支。
@Sekhat:虽然 git status 不检查远程存储库,但 git pull 会。如果您有要推送到的存储库的跟踪分支,如果您的推送成功,git push 将更新您的本地跟踪分支以反映远程分支的新状态。这就是为什么我询问询问者的配置的原因,因为如果它没有正确发生,则可能是配置错误。
git status?真的吗?我的 git status 从来没有告诉我我的分支有多远......你是否向它传递了一些额外的参数?
@hasen j:git status 不会去远程仓库检查远程分支是否已经更新。它告诉您本地分支与 本地存储 远程跟踪分支相比有多远。问题是正常的 git push(以及 fetch 和 pull)应该更新远程跟踪分支,而对于询问者,这似乎不起作用。要了解为什么我们需要查看正在使用的 git push 的确切形式和本地存储库的配置,但由于提问者已经接受了答案,我现在看不到这种情况发生。

e
elliotwhitehead

如果您在执行 git pull remote branch 后收到此消息,请尝试使用 git fetch 跟进。 (可选地,运行 git fetch -p 以从 repo 中删除已删除的分支)

Fetch 似乎更新了远程分支的本地表示,这在您执行 git pull remote branch 时不一定会发生。


太棒了。这确实是问题所在。我首先在 google 代码上创建了一个存储库。然后我在我的笔记本电脑上克隆了这个存储库,我在那里工作并推送更改,笔记本电脑 => code.google。我曾经在我创建了 code.google 代码存储库克隆的服务器上收到此消息,并且我曾经拉动更改。我认为 fetch 是更新本地数据库所必需的。
我们在这里遇到了同样的问题,因为另一个分支 (A) 指向 master 的相同 commitid。拉 A 再拉 master 导致了同样的情况。当 git 拉 A 时,commitid 更新为最后一个,所以拉 master 它实际上没有任何东西可以拉,所以 git 没有更新 master last commitid 并警告“领先于 master”。
谢谢,虽然我确实注意到一件奇怪的事情。 “git fetch origin master”没有帮助,但“git fetch origin”有帮助。我在主分支上,所以不确定“git fetch origin”在上下文中会如何做不同的事情。
@Parag 请参阅 stackoverflow.com/questions/26350876/… 以了解这两个命令之间的差异,以及如何修改配置文件以更改行为,因此 git fetch remote branch 也会更新 remote-tracking-branch ref,因此 git_status 不会报告“提前”经过'。
@Parag,stackoverflow.com/questions/7365415/… 答案也讨论了 ORIG_HEAD 和 FETCH_HEAD 不同步的详细信息,导致状态警告以及可能的配置文件更正。
M
Marian Zburlea

利用

git pull --rebase

--rebase 选项意味着 git 会将您的本地提交移到一边,与远程同步,然后尝试从新状态应用您的提交。


防止无用合并并拥有更清洁的树的真正好方法!
我试过这个命令,但我仍然遇到同样的问题...$ git pull --rebase Current branch xyz is up to date. $ git status On branch xyz Your branch is ahead of 'origin/xyz' by 6 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
这个答案是错误的:如果你在不了解情况的情况下使用它,你可能会在未来一段时间内产生麻烦(重写历史!)。如果您了解这种情况,这将不是解决它。使用 git 时请三思而后行,切勿盲目改写历史!
@Rich 的答案有什么不同?
这解决了我的问题!谢谢你 :)
C
Community

使用这 3 个简单的命令

第 1 步git checkout <branch_name>

第 2 步git pull -s recursive -X theirs

第 3 步git reset --hard origin/<branch_name>

更多详情:https://stackoverflow.com/a/39698570/2439715

享受。


这是真正为我解决问题的唯一答案。上面的命令奇怪地将其从 12 次提交到 7 次提交,这最终删除了那些
我同意这是唯一对我有用的东西。我确信 GIT 有时会出现多重人格障碍。
像 @leuan 一样,除了 git reset --hard origin/master 之外什么都没有为我清除。
同样在这里,这是唯一对我有用的步骤
这对我有用,特别是第 3 步进行了更改。谢谢!
J
Josh Lee

我认为您误读了消息 — 您的分支没有领先于 master,它 master。它在 origin/master 之前,它是一个远程跟踪分支,用于记录您上一个 pushpullfetch 的远程存储库的状态。它准确地告诉你你做了什么;你走在遥控器前面,它在提醒你推。


这实际上是我推后的。我不得不拉(或可能取?)让它没有那个消息。
А
Али Палитаев

这对我有用

git reset --hard origin/master

输出必须看起来像

On branch dev HEAD is now at ae1xc41z Last commit message


是的!谢谢,我正在使用 git reset --hard origin master,但我仍然准备好提交提交
git reset --hard origin/qa。这对我来说可以与遥控器同步
F
Fake Code Monkey Rashid

有人说你可能误读了你的信息,你不是。此问题实际上与您的 <project>/.git/config 文件有关。其中将有一个与此类似的部分:

[remote "origin"]
    url = <url>
    fetch = +refs/heads/*:refs/remotes/origin/*

如果您从项目的 .git/config 文件中删除 fetch 行,您将停止“您的分支在 N 次提交之前领先于 'origin/master'”。烦恼的发生。

或者我希望如此。 :)


下次我看到 ahead by x commits 消息时,我会检查一下。好久没看到消息了
好久没看到消息了我认为这是因为我已经开始在本地创建 git 存储库,然后将其推送到远程存储库,而不是相反......
我试过这个,但是当我尝试提交时,它使 Eclipse 中的 eGit 开始弹出“内部错误”。不过,Git 本身似乎运行良好。
那条线有什么作用?删除它我错过了什么? (除了烦恼)
这行得通,但它更像是抑制错误。重新添加该行,您将再次开始收到警告。
A
Anatolii Pazhyn

我在我的舞台服务器上遇到了这个问题,我只做拉。硬重置帮助我将 HEAD 清理到与遥控器相同的位置。

git reset --hard origin/master

所以现在我又有了:

On branch master
Your branch is up-to-date with 'origin/master'.

我第一次尝试不带 --hard 标志,它成功了!
e
erwin

我浏览了这个页面上的每一个解决方案,幸运的是@anatolii-pazhyn 评论了,因为他的解决方案是有效的。不幸的是,我没有足够的声誉来支持他,但我建议先尝试他的解决方案:

git reset --hard origin/master

这给了我:

HEAD is now at 900000b Comment from my last git commit here

我还推荐:

git rev-list origin..HEAD
# to see if the local repository is ahead, push needed

git rev-list HEAD..origin
# to see if the local repository is behind, pull needed

您还可以使用:

git rev-list --count --left-right origin/master...HEAD
# if you have numbers for both, then the two repositories have diverged

祝你好运


意识到! reset --hard origin/master 将销毁您的本地提交(您尚未推送的提交)!
A
AxCoder

就我而言,这是因为我切换到 master 使用

 git checkout -B master

只是为了拉取它的新版本而不是

 git checkout master

我最新提交的第一个命令 resets the head of master

我用了

git reset --hard origin/master

解决这个问题


t
torek

注意:这个特殊的问题在我写这个答案的时候已经很老了。它是在第一个版本的 Git 版本发布前三年发布的,该版本修复了许多这些问题。 不过,似乎值得添加一个现代答案和解释器。 The existing accepted answer 建议运行 git fetch -p,1,这是一个好主意,尽管这些天不太经常需要。在 Git 版本 1.8.2 出来之前,它是非常必要的; Git 是在最初的问题发布三年后发布的。

1-p--prune 选项不是必需的,仅建议在链接答案的括号中。请参阅下面较长的部分了解它的作用。

这实际上是如何发生的?

最初的问题是:

这实际上是如何发生的?

有问题的 this 是在 git push origin master 之后,OP 运行 git status 并看到消息 On branch master 后跟 Your branch is ahead of 'origin/master' by 1 commit. 为了正确回答问题,我们需要将其分解成为碎片。

首先,每个(本地)分支都有一个上游设置

这种说法实际上有点太强了。您自己的每个本地分支,在您自己的 Git 存储库中,可以一个设置,Git 将其称为 上游。或者,该分支可以有 no 上游。旧版本的 Git 并不太一致地将其称为 upstream 设置,但在现代 Git 中,它更加一致。我们还有 git branch --set-upstream-togit branch --unset-upstream 用于设置或清除上游。

这些 --set-upstream-to--unset-upstream 影响 当前分支。当前分支是您是 on 的分支,当 git statuson branch xyzzy 或它说的任何内容时。您选择这个带有 git checkout 的分支,或者——从 Git 2.23 开始——git switch2无论你签出哪个分支,这就是你所在的那个。 3

如果您使用 --unset-upstream,这删除当前分支的上游。没有上游,这会阻止关于领先或落后或分歧的信息。但是此消息是有用的,因此您可能不应该仅仅删除上游作为使其停止发生的一种方式。 (请随意忽略这条消息——毕竟它不是一个错误——如果你觉得它没有用处。)

如果您运行 git branch --set-upstream-to=origin/xyzzy,则会将当前分支的上游设置为 origin/xyzzy。对于名为 xyzzy 的分支,这将是典型的正确设置。某些创建分支的行为自动设置(通常是正确的)上游,而有些则没有,因此如果您使用自动设置正确上游的分支创建操作,则无需执行任何操作。如果您想要不同的上游,或者如果您使用了设置 no 上游的分支创建操作,则可以使用它来更改上游。

您可以将上游设置为:

您自己的另一个(本地)分支: git branch --set-upstream-to=experiment 使您自己的本地实验成为当前分支的上游;或者

您的任何远程跟踪名称,例如 origin/main 或 origin/master 或 origin/xyzzy。这些是 git branch -r 输出的名称。 Git 调用这些远程跟踪分支名称(我喜欢在这里去掉“分支”这个词),稍后我们将详细讨论它们。

git status 打印的前面、后面、最新或不同的消息来自运行看起来有点神奇的命令:

git rev-list --count --left-right $branch...$upstream

其中 $branch 是当前 branch 名称,$upstream 是来自其上游设置的字符串(来自上面的 git branch --set-upstream-to)。这里两个名字之间有三个点,而--count--left-right、三个点都需要得到git rev-list才能吐出两个数字。

2如果您有 Git 2.23 或更高版本,最好改用 git switch,因为它避免了一些棘手的 git checkout 行为,这些行为在历史上会导致初学者陷入困境(有时甚至会绊倒 Git 专家)。但是,如果您习惯了 git checkout,您可以继续使用它,只要您愿意,因为它仍然受支持。真正的问题基本上是 git checkout 过于强大,可能会意外破坏工作。新的 git switch 故意不那么强大,不会那样做; “故意破坏我的工作”操作已移至 git restore

3可能在 no 分支上,Git 称之为 detached HEAD 模式。如果您使用 git checkout,它可能会让您突然进入这种模式(虽然它会打印一个很大的可怕警告,所以如果您没有看到可怕的警告,它没有这样做),但是如果您使用 git switch,您必须使用 git switch --detach允许 detached-HEAD 模式。这种模式没有任何错误,您只需要在进入该模式后小心,不要丢失您所做的任何新提交。如果您不小心,很容易丢失它们。在正常模式下,Git 不会像这样丢失新的提交。

如果您处于分离 HEAD 模式,则根据定义,您没有上游,因为您没有分支,并且此问题中的任何内容都不适用。

可达性

这部分有点技术性,我会将大部分内容外包给一个网站,Think Like (a) Git。我将在这里总结如下:分支名称(如 mainxyzzy)和 远程跟踪名称origin/mainorigin/xyzzy)是Git 如何发现 提交。 Git 是关于 commits 的。您的分支名称仅对查找您的提交很重要。当然,如果你找不到它们,你就有麻烦了,所以你的分支名称很重要。但关键是可达性,这是技术术语。

Git 存储库中的每个提交都有编号,带有一个大而难看的 hexadecimal 字母和数字字符串。这是提交的 hash ID,它是 Git 真正 找到提交的方式。

每个提交包含两件事:每个源文件的完整快照(以特殊的、压缩的、Git 化的和去重的形式),以及关于提交本身的一些信息:元数据告诉谁做了它,时间和原因(他们的日志消息),例如。在元数据中,每个提交都包含一些较早提交的提交编号。这意味着一个提交可以找到另一个更早的提交。

正如 Think Like (a) Git 所指出的,这有点像火车。一旦您火车上,感觉很棒,在这种情况下,火车会自动带您倒退到所有较早的火车站点。但首先您必须找到火车站的路。 Git 分支名称可以做到这一点:它保存您分支上 latest 提交的哈希 ID。

我们可以这样画:

... <-F <-G <-H   <--branch

分支名称 branch 包含 最新 提交的哈希 ID。我们说名称指向提交。无论真正的丑陋哈希 ID 是什么,我们都只是在这里使用了字母 H 来代替它。

H 是一个实际提交,因此它有一个保存的快照(您的文件)和一些元数据。在元数据中,Git 保存了 earlier 提交的哈希 ID。我们将其称为较早的提交 G。我们说H 指向 G。 Git 可以通过分支名称指针找到 H,这使 Git 可以访问提交,包括元数据,因此现在 Git 具有早期提交 G 的哈希 ID。

G 当然也是一个实际的提交:它有一个保存的快照和一些元数据。在 G 的元数据中,Git 保存了较早提交 F 的哈希 ID。我们说 G 指向 F,现在 Git 可以使用这个保存的哈希 ID 找到 F

这将永远重复,或者更确切地说,直到我们进行第一次提交。该提交(大概我们在这里称之为 A指向更早的提交,因为没有更早的提交。

可达性 的概念基本上是对如果我们从提交 H 开始(通过分支名称 branch 找到)并向后工作会发生什么的总结。我们到达提交 H,它向后到达提交 G,又回到 F,依此类推。

分支名称和远程跟踪名称

正如我们刚刚提到的,分支名称包含某个提交的原始哈希 ID。这让 Git 可以找到那个提交。不过,还有一个关于分支名称的特殊功能。

当您使用 git checkoutgit switch on 一个分支,然后进行 new 提交时,Git 会自动更新分支名称的存储哈希 ID< /em>。也就是说,假设我们有一系列这样的提交:

...--F--G--H   <-- xyzzy (HEAD)

我们在“打开”分支 xyzzy,我想通过附加特殊名称 HEAD 来表示它。当图中有多个分支名称时,这很有用。请注意,H 目前是 最新 提交。但是现在我们将按照通常的方式制作另一个。

这个新的提交获得了一个新的、唯一的、又大又丑的十六进制哈希 ID,就像任何提交一样。 Git 确保新提交向后指向提交 H,因为这是我们用来制作新提交的提交。我们将使用字母 I 来表示这个新提交。让我们把它画进去:

...--F--G--H   <-- xyzzy (HEAD)
            \
             I

这张图片实际上是提交中期:Git 已经完成了 I,但还没有完成 git commit 动作。问自己这个问题:稍后我们将如何找到提交 I?我们将需要它的哈希 ID。我们可以在哪里存储哈希 ID?

如果你说:在一个分支名称中,你是对的。事实上,正确的分支名称——无论如何,就 Git 而言——是你现在“启用”的那个。这就是我们在此图中附加 HEAD 的那个。所以现在,作为 git commit 的最后一部分,Git 将 I 的哈希 ID 写入名称 xyzzy。这使得它指向提交 I,如下所示:

...--F--G--H
            \
             I   <-- xyzzy (HEAD)

现在图纸中没有任何扭结的原因,所以我们可以把它理顺:

...--F--G--H--I   <-- xyzzy (HEAD)

这就是分支名称的工作方式。最后,这真的很简单:它只需要你同时考虑几件事。该名称找到提交。它找到最新的提交。从那里开始,Git 向后工作,因为每个提交都会找到更早的提交。

远程跟踪名称呢?好吧,这里的诀窍是您的 Git 与其他 Git 对话。 每个 Git 都有自己的分支名称。你有你的mastermain;他们有他们的。你有你的 xyzzy 分支,他们也可以有他们的。

您的 Git 可以随时、每次都调用他们的 Git,并询问他们的分支名称。但是,这不是很有效,而且如果您与 Internet 断开连接,也不会起作用。4 无论如何,Git 不会这样做。相反,当您的 Git 调用他们的 Git 并从他们那里获取所有分支名称和哈希 ID 的列表时,您的 Git 会获取这些名称和哈希 ID 并将它们存储在 您的 存储库。当您运行 git fetch 时会发生这种情况。5

不过有问题。他们的 mainmaster,或者他们的 xyzzy(如果有的话)并不一定意味着 same 提交与 your mainmasterxyzzy。不过解决方案很简单:Git 只需将它们的 branch 名称转换为您的 remote-tracking 名称

如果 originmainmasterxyzzy 已移动,您只需运行 git fetchgit fetch origin,也许与 --prune。你的 Git 调用他们的 Git。他们列出了他们的分支名称和提交哈希 ID。如有必要,您的 Git 会从他们那里获得任何新的提交:他们有的提交,而您没有。然后您的 Git 将它们的 branch 名称转换为您的 remote-tracking 名称并创建或更新您的远程跟踪名称以记住 their 分支名称指向的位置,此时您运行此 git fetch

如果您使用 --prune,这将处理他们删除某些分支名称的情况。假设他们有一个名为 oldstuff 的分支。您之前得到它,所以您的远程跟踪名称中有 origin/oldstuff。然后他们删除了 oldstuff,所以这次他们......只是不再拥有它了。如果没有 --prune,您的 Git 会忽略这一点。你保留旧的 origin/oldstuff,即使它现在已经死了。 使用 --prune,您的 Git 会说:哦,呵呵,现在看起来已经死了并将其删掉:您的中的远程跟踪名称与他们的 branch 名称之一不对应的 Git 会被删除。

prune 选项可能应该一直是默认选项,但它不是,因此现在不能。6 但是,您可以将 fetch.prune 配置为 truemake 你的默认值。

4现在 2021 年的情况比 2010 年要少。在 2005 年 Git 首次发布时,这种情况要普遍得多。过去的情况是,例如,在飞往 Linux 会议的航班上,您无法以任何价格访问 Internet。

5选择取哪些名字,什么时候取名字,实际上是这里答案的一部分。它在 Git 中随着时间的推移发生了变化——并且仍在发生一点点变化——尽管仍然存在各种限制。不过,我们不会详细介绍所有细节。

6Git 通常非常重视向后兼容性。例如,从 1.x 到 2.0 的转换将 push.default 默认设置从 matching 更改为 simple

git rev-list 如何获取这两个数字

早些时候,我注意到 git status 打印的提前、落后、最新或分歧消息来自运行:

git rev-list --count --left-right $branch...$upstream

git rev-list 在这里所做的是count 可访问的提交the gitrevisions documentation 中描述的三点语法产生集合论中称为对称差分的东西。但是,在非数学术语中,我们可以将其视为进行两次提交可达性测试,我们可以这样绘制:

          I--J   <-- xyzzy (HEAD)
         /
...--G--H
         \
          K   <-- origin/xyzzy

在这里,可以从您的分支名称 xyzzy 访问提交 J,因为名称指向那里。提交 I 可从提交 J 访问,因此它也很重要。这会返回到提交 H——从图中可以看出,它有点特别。

同时,可以从您的远程跟踪名称 origin/xyzzy 访问提交 K。提交 H 可从 K 访问。从后面的提交 H 开始,提交 GF 等也都可以访问。但是两个“铁轨”在提交 H 处加入:提交 H 和所有更早的提交都可以从 两个名称 访问。

这使得提交 I-J 的特殊之处在于它们*仅可从名称 xyzzy 访问,而 K 的特殊之处在于它*仅可从名称 origin/xyzzy 访问。三点符号查找这些提交:只能从一个名称访问的提交,或者只能从另一个名称访问的提交。

如果我们把分支名称放在左边,把它的上游放在右边,并使用三点符号,我们将找到所有这三个提交。使用 --count 使 git rev-list 打印这个数字: 3. 使用 --left-right 告诉 git rev-list 更聪明,但是:它应该计算由于 left 名称而被计算的提交数—— 当前分支 名称——以及由于 正确 之一(上游)而计算了多少次提交。因此,通过这两个选项和三个点,我们得到:

2       1

作为输出,告诉我们 xyzzy 上的两个提交不在 origin/xyzzy 上,一个在 origin/xyzzy 上的提交不在 xyzzy 上。它们分别是提交 J-and-I(在 xyzzy 上)和 K(在 origin/xyzzy 上)。

如果没有 --count 选项,git rev-list 将列出哈希 ID,前缀为 <(左)或 >(右)符号。使用 git log 而不是 git rev-list,如:

git log --left-right xyzzy...origin/xyzzy

(再次注意三个点:参见 gitrevisions 并搜索 Symmetric Difference)我们将看到三个提交,再次根据需要以 <> 为前缀。

这是查看哪些提交在您的分支上以及哪些提交在上游的一种简单方法。它通常对 --decorate--oneline--graph 更有用(您可能在某些情况下也想添加 --boundary)。

领先、落后、分歧或最新

所以,假设我们已经运行:

git rev-list --count --left-right $branch...$upstream

(或者 - 再次参见 gitrevisions - 使用此处右侧的 $branch@{upstream})并得到我们的两个计数。这些可以是:

0 和 0:我们的分支名称和远程跟踪名称(或上游中的任何名称)指向同一个提交。没有人领先或落后。 git status 命令会说 Your branch is up to date with ''。

非零,零:当前分支上有不在上游的提交。上游没有不在当前分支上的提交。所以我们的分支领先于上游。

零,非零:当前分支上没有不在上游的提交,但上游有一些不在当前分支上的提交。这意味着我们的分支在上游之后。

非零,非零:这就像我上面画的图。当前分支和它的上游都同时相互领先和落后。 git status 命令将使用发散这个词。

我们现在要跳回到最初的问题。假设当前分支的上游是一个远程跟踪名称。 请注意,git rev-list 获得的计数基于我们的远程跟踪分支名称中的内容。

这实际上是如何发生的?

在 OP 的场景中,只有一个人在进行新的提交并使用 git push 将它们发送出去。如果我是一个人,我可能会git clone GitHub 上的一些东西,然后进行一两次新的提交,然后 git push origin master

在现代 Git 中,git status 会告诉我我是最新的。在非常旧的 Git 版本中,git status 现在会告诉我我的 master 领先于 origin/master原因很简单:在过去,git push 未能更新 origin/master。运行 git fetch origin 或仅运行 git fetch,让您自己的 Git 在 GitHub 上调用 Git,阅读他们的信息,并意识到您的 git push 已经工作。

当您运行 git push 时,您的 Git 会调用其他 Git。然后,您的 Git 会向其他 Git 提供您拥有的任何新提交,而他们没有提交,他们需要完成 git push。他们接受这些提交并将它们放在某个地方。7 然后你的 Git 会询问他们的 Git——默认情况下礼貌地询问——如果他们愿意,请设置 他们的 < strong>branch 名称,通过其哈希 ID 引用最新提交,如 您的 分支名称中所示。这里没有远程跟踪的东西。您只是要求他们设置您正在使用的同名

作为一般规则,如果您只是向他们的存储库添加新提交,这种礼貌的请求会成功。如果你要求他们“丢失”一些提交,它会失败:你会抱怨这是一个“非快进”。如果你是唯一一个向他们发送新提交的人,他们不应该以这种方式失去任何东西,所以这应该总是有效的。8

如果推送失败,您的 Git 可以保持远程跟踪名称不变。你的 Git 从来没有从他们的 Git 那里得到信息,让你的 Git 更新它。但是如果推送成功......好吧,他们只是将他们的分支名称设置为您的 Git 要求他们使用的哈希 ID。所以现在你的 Git 知道他们的分支名称指向哪里。您的 Git 应该更新您的远程跟踪名称。

在旧的 Git 版本中,您的 Git 只是不打扰这样做。在 Git 版本 1.8.2 中,Git 作者最终解决了这个问题:成功的 git push 让您的 Git 更新您的远程跟踪名称,基于他们的 Git 同意您的 Git 提供的更新这一事实。所以这种事情不会再发生了。

7在过去糟糕的日子里,他们将它们直接放入自己的仓库中。在现代 Git 中,他们将它们放在隔离区,并且只有在他们真正接受新提交时才将它们迁移到他们的存储库中。

8当然,像 GitHub 这样的地方也提供了受保护的分支等功能,例如,它只是对每次推送说不。我们还可以创造更奇特的场景,例如当您拥有多台计算机并忘记您通过计算机 A 进行和推送新提交时,现在尝试从计算机 B 推送。

如果你不是唯一一个做 git push 的人怎么办

假设 Alice 和 Bob 都克隆了一些 GitHub 存储库。此存储库中的开发发生在分支 dev(用于开发)上。所以 Alice 从她的 origin/dev 中创建了自己的 dev

...--G--H   <-- dev (HEAD), origin/dev  [Alice's computer]

同样,Bob 使 他的 成为自己的 dev

...--G--H   <-- dev (HEAD), origin/dev  [Bob's computer]

GitHub 存储库 dev 也以 H 结束。 (他们没有 origin/dev:GitHub 存储库不关心远程跟踪名称。)

Alice 进行了一个新的提交,我们称之为 I,并在 Alice 的计算机上绘制如下:

          I   <-- dev (HEAD)
         /
...--G--H   <-- origin/dev

同时,Bob 做了一个新的提交,我们称之为 J

...--G--H   <-- origin/dev
         \
          J   <-- dev (HEAD)

现在 Alice 和 Bob 都尝试 git push origin dev。其中一个最先到达那里——也许是爱丽丝:

...--G--H--I   <-- dev  [GitHub's systems]

Bob 将提交 J 发送到 GitHub,如下所示:

          I   <-- dev
         /
...--G--H
         \
          J   ... polite request to set dev to J

如果 GitHub 会这样做,这将“丢失” Alice 的提交 I,因为 Git finds 提交是从名称开始并向后工作。因此,他们以“不是快进”的抱怨拒绝了推动。

Bob 现在需要将提交 I 从 GitHub 拉到 Bob 自己的存储库中,以便 Bob 看到:

          I   <-- origin/dev
         /
...--G--H
         \
          J   <-- dev (HEAD)  [Bob's computer]

Bob 应该使用 git fetchgit fetch origin,也许使用 --prune(或将 fetch.prune 设置为 true)来执行此操作。 现在当 Bob 运行 git status 时,他将收到“发散”消息。

现在由 Bob 作为推动竞赛的失败者来决定如何将 他的 工作(提交 J)与 Alice 的(提交 I)结合起来。有不同的方法可以组合工作。两个主要的是 git mergegit rebase。我们不会在这里讨论谁应该做什么、何时以及为什么要做,只是当你认为自己完全领先于其他 Git 时,这是另一种可能会陷入“分歧”状态的事实。


T
The Code Father

我在 Windows 机器上遇到了同样的问题。当我运行 git pull origin master 命令时,我会收到“X 提交领先于 'origin/master'”的警告。我发现如果我改为运行 git pull origin 并且没有指定分支,那么我将不再收到警告。


我相信这在幕后有效地git fetch
“git fetch”没有解决我的问题,这解决了。我得到了新添加的分支列表和这条消息“你要求从远程'上游'拉,但没有指定一个分支。因为这不是你当前分支的默认配置远程,你必须在命令上指定一个分支线。”并且下一个“git status”命令没有显示警告。
r
rodgdor

我想重申上面@Marian Zburlia 提到的相同内容。它对我有用,并且会向其他人提出相同的建议。

git pull origin develop

后跟 $ git pull --rebase

这将删除最近一次拉取后出现在 $ git status 上的评论。


G
Guillaume Racicot

git fetch 将为您解决此问题

如果我的理解是正确的,那么您的本地(缓存)origin/master 已过时。此命令将从服务器更新存储库状态。


请添加一些描述
s
seh

它只是提醒您当前分支与执行当前轨道的分支之间的差异。请提供更多信息,包括消息中打印的分支以及您在哪里推/拉当前分支。


D
Dustin Graham

当我使用 TortiseGIT 进行切换/结帐时,实际上发生了这种情况。

我的问题是我创建了基于另一个本地分支的分支。它在 /.git/config 中创建了一个“合并”条目,如下所示:

[branch "web"]
    merge = refs/heads/develop
    remote = gitserver

每当我切换到“web”分支时,它告诉我我在开发之前有 100 多个提交。好吧,我不再致力于开发,所以这是真的。我能够简单地删除此条目,它似乎按预期运行。它与远程参考正确跟踪,而不是抱怨在开发分支后面。

正如维克拉姆所说,这个 Stack Overflow 线程是谷歌搜索这个问题时的最高结果,所以我想我会分享我的情况和解决方案。


F
FPGA-guy

然后,当我执行 git status 时,它告诉我我的分支领先于 X 次提交(大概与我所做的提交次数相同)。

我的经验是在一个有许多分支机构的团队环境中。我们在自己的功能分支中工作(在本地克隆中),它是 git status 显示我领先 11 次提交的分支之一。与问题的作者一样,我的工作假设是 +11 来自 我自己的提交

事实证明,我已经在几周前将更改从 common develop 分支引入了我的特性分支——但是忘记了!当我今天重新访问我的本地功能分支并执行 git pull origin develop 时,数字跃升至 +41 提交。在 develop 中已经完成了很多工作,因此我的本地功能分支甚至比 origin 存储库上的功能分支更早。

因此,如果您收到此消息,请回想一下您可能从您有权访问的其他分支(您自己的或其他分支)所做的任何拉取/合并。该消息只是表明您需要将这些pull更改从您的本地存储库返回到 origin 存储库(“跟踪分支”)以使事情同步。


V
Vikram

虽然这个问题有点老了......我遇到了类似的情况,我在这里的回答帮助我解决了我遇到的类似问题

首先尝试使用 push -f 或强制选项

如果这不起作用,那么(在我的情况下)远程存储库(或者更确切地说是对显示在 git remote -v 上的远程存储库的引用)可能没有得到更新。

上述结果是您的推送将您的本地/分支与远程/分支同步,但是,本地存储库中的缓存仍将先前的提交(本地/分支的......如果仅推送单个提交)显示为 HEAD。

要确认上述在不同位置克隆 repo 并尝试比较本地/分支 HEAD 和远程/分支 HEAD。如果它们都相同,那么您可能面临我所做的问题。

解决方案:

$ git remote -v
github  git@github.com:schacon/hw.git (fetch)
github  git@github.com:schacon/hw.git (push)
$ git remote add origin git://github.com/pjhyett/hw.git
$ git remote -v
github  git@github.com:schacon/hw.git (fetch)
github  git@github.com:schacon/hw.git (push)
origin  git://github.com/pjhyett/hw.git (fetch)
origin  git://github.com/pjhyett/hw.git (push)
$ git remote rm origin
$ git remote -v
github  git@github.com:schacon/hw.git (fetch)
github  git@github.com:schacon/hw.git (push)

现在按如下方式执行 push -f

git push -f github master ### 请注意,您的命令不再有 origin

立即执行git pull git pull github master

git status 接收

# On branch master

nothing to commit (working directory clean)

我希望这对某人有用,因为视图数量如此之多以至于搜索此错误几乎总是将此线程列在顶部

另请参阅 gitref 了解详细信息


除非您知道自己在做什么,否则切勿执行 push -f!至少做一个 push --force-with-lease 这样您就不会覆盖其他人的提交!
N
NoBrassRing

建议 git pullgit fetch 的答案是正确的。
git status 发现 .git/FETCH_HEAD.git/refs/remotes/<repository>/<branch> 之间的差异(例如 .git/refs/remotes/origin/master)时,将生成该消息。

后一个文件记录了上次获取的 HEAD(用于存储库/分支)。执行 git fetch 会将两个文件更新到分支的当前 HEAD。
当然,如果没有要获取的内容(因为本地存储库已经是最新的),那么 .git/FETCH_HEAD 不会更改。


这对我来说似乎不是这样:.git/FETCH_HEAD 包含 9f7336c873ccffc772168bf49807e23ff74014d3 branch 'master' of URL.git/refs/remotes/origin/master 包含 9f7336c873ccffc772168bf49807e23ff74014d3,但我仍然收到消息,git pullgit fetch 都没有解决它
I
Iqra.

我得到以下与实际问题 Your branch is ahead of 'origin/testing/KB-200' by 17 commits 相关的内容

原因:我上周创建了 PR 以供审核,然后我关闭了该项目。然后今天,我打开项目在同一个分支 (testing/KB-200) 中稍作更改,我先运行 git pull。这个拉取包含 18 个由其他开发人员在该项目上工作的新提交,这使得我的本地分支通过这些提交领先于我的远程分支,因此我收到了这条消息。所以我只需要运行以下命令:

git push origin testing/KB-200

然后它全部同步并且是最新的。 [On branch testing/KB-200 Your branch is up to date with 'origin/testing/KB-200']


n
nurb

如果您在提交后收到此消息,为了取消跟踪分支中的文件,请尝试在任何文件中进行一些更改并执行提交。显然,您不能进行仅包括取消跟踪以前跟踪的文件的单个提交。最后这篇文章帮助我解决了整个问题https://help.github.com/articles/removing-files-from-a-repository-s-history/。我只需要从存储库历史记录中删除文件。


b
boy

只是分享发生在我身上的事情。

我提交了一堆文件,并意识到有些文件我不想提交,所以我使用 VS 代码 undo last commit,删除文件并添加到 gitignore,然后再次强制推送我的提交。

这显然导致 git 认为我的提交仍然必须远程提交,因为本地文件以某种方式提交。

undo last commit 解决并取消暂存 gitignore 中的文件