【问题标题】:git: Your branch is ahead by X commitsgit:您的分支领先于 X 次提交
【发布时间】:2011-01-26 19:36:01
【问题描述】:

这实际上是如何发生的?

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

  1. 更改文件
  2. 提交
  3. 重复 1-2 直到满意
  4. 推送到大师

然后,当我执行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(以及获取和拉取)应该更新远程跟踪分支,而对于提问者来说,这似乎不起作用。要了解为什么我们需要查看正在使用的 git push 的确切形式和本地存储库的配置,但由于提问者已经接受了答案,我现在看不到这种情况发生。

标签: git git-commit


【解决方案1】:

如果您在发送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 不同步的细节,导致状态警告,以及可能的配置文件更正。
【解决方案2】:

使用

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 的答案有何不同?
【解决方案3】:

使用这 3 个简单的命令

第一步git checkout <branch_name>

第 2 步git pull -s recursive -X theirs

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

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

享受吧。

【讨论】:

  • 这是唯一真正为我解决问题的答案。上面的命令奇怪地将它从 12 次提交到 7 次提交,这最终删除了那些
  • 我同意这是唯一对我有用的东西。我确信 GIT 有时会出现多重人格障碍。
  • 就像@leuan,不过git reset --hard origin/master 为我清理了它。
  • 这里也一样,这是唯一对我有用的步骤
【解决方案4】:

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

【讨论】:

  • 这其实是我推送之后的。我不得不拉(或可能取?)让它没有那个消息。
【解决方案5】:

这对我有用

git reset --hard origin/master

输出必须看起来像

On branch dev HEAD is now at ae1xc41z Last commit message

【讨论】:

  • 是的!谢谢,我使用的是git reset --hard origin master,但我仍然准备好提交提交
【解决方案6】:

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

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

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

我希望如此。 :)

【讨论】:

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

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

git reset --hard origin/master

所以现在我又来了:

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

【讨论】:

  • 我第一次尝试不带 --hard 标志,它成功了!
【解决方案8】:

我浏览了此页面上的所有解决方案,幸运的是 @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 会破坏你的本地提交(那些你还没有推送的)!
【解决方案9】:

就我而言,这是因为我使用

切换到 master
 git checkout -B master

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

 git checkout master

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

我用过

git reset --hard origin/master

解决这个问题

【讨论】:

    【解决方案10】:

    注意:在我写这个答案的时候,这个特殊的问题已经很老了。它是在第一个版本的 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 使您自己的本地 experiment 成为当前分支的上游;或
    • 您的任何远程跟踪名称,例如origin/mainorigin/masterorigin/xyzzy。这些是git branch -r 输出的名称。 Git 将这些远程跟踪分支名称称为(我喜欢在这里去掉“分支”这个词),我们稍后会详细讨论它们。

    git status 打印的领先、落后、最新或分歧消息源自运行看起来有点神奇的命令:

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

    其中$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 的分离 HEAD 模式。这种模式没有任何错误,您只需要在进入该模式后小心,不要丢失您所做的任何新提交。如果您不小心,很容易丢失它们。在普通模式下,Git 不会像这样丢失新的提交。

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


    可达性

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

    Git 存储库中的每个提交都有编号,带有一个大而难看的 hexadecimal 字母和数字字符串。这是提交的哈希 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 找到)开始并向后工作会发生什么的总结。我们到达commit H,它向后到达commit G,它又回到F,以此类推。

    分支名称和远程跟踪名称

    正如我们刚刚提到的,分支名称保存了某个提交的原始哈希 ID。这让 Git 找到那个提交。不过,branch 名称还有另一个特殊功能。

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

    ...--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)
    

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

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

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

    虽然有问题。他们的mainmaster,或者他们的xyzzy(如果有的话)并不一定意味着相同 提交与你的 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 会说:哦,呵呵,这现在看起来已经死了并把它删掉了:你的中的远程跟踪名称与其 分支 名称之一不对应的 Git,将被删除。

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


    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
    

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

    同时,提交K 可以从您的远程跟踪名称origin/xyzzy 访问。提交H 可从K 访问。从后面的 commit H 开始,commit 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-和-Ixyzzy)和Korigin/xyzzy)。

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

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

    (再次注意三个点:请参阅gitrevisions 并搜索对称差异)我们将获得三个提交,再次以&lt;&gt; 为前缀(视情况而定)。

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

    领先、落后、分歧或最新

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

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

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

    • 00:我们的分支名称和远程跟踪名称(或上游中的任何名称)指向 same 提交。没有人领先或落后。 git status 命令将显示Your branch is up to date with '&lt;upstream&gt;'

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

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

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

    我们现在要跳回到最初的问题。假设当前分支的上游是一个远程跟踪名称。 请注意,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——默认情况下礼貌地询问——如果他们愿意,请设置 他们的 branch 名称,通过其哈希 ID 引用最新提交,如 您的 分支名称中所示。这里没有远程跟踪的东西。您只是要求他们设置您正在使用的同名

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

    如果推送失败,您的 Git 可以保持远程跟踪名称不变。你的 Git 从来没有从他们的 Git 那里得到信息,让你的 Git 更新它。但是如果推送 成功 ...好吧,他们只需将他们的 branch 名称设置为您的 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(用于开发)上。所以爱丽丝从她的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 时,这是另一种可能会陷入“分歧”状态的事实。

    【讨论】:

      【解决方案11】:

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

      【讨论】:

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

      git fetch 将为您解决此问题

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

      【讨论】:

      • 请添加一些描述
      【解决方案13】:

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

      【讨论】:

        【解决方案14】:

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

        我的问题是我创建了基于另一个本地分支的分支。它在/.git/config 中创建了一个“合并”条目,看起来像这样:

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

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

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

        【讨论】:

          【解决方案15】:

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

          git pull origin develop

          后面应该跟$ git pull --rebase

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

          【讨论】:

            【解决方案16】:

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

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

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

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

            【讨论】:

              【解决方案17】:

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

              首先尝试使用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,这样你就不会覆盖其他人的提交!
              【解决方案18】:

              建议git pullgit fetch 的答案是正确的。
              git status 发现.git/FETCH_HEAD.git/refs/remotes/&lt;repository&gt;/&lt;branch&gt; 之间存在差异时会生成该消息(例如.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 都没有解决它
              【解决方案19】:

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

              【讨论】:

                【解决方案20】:

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

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

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

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

                【讨论】:

                  【解决方案21】:

                  我得到以下与实际问题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']

                  【讨论】:

                    猜你喜欢
                    • 2012-04-27
                    • 2021-07-02
                    • 2013-04-23
                    • 2011-01-21
                    • 2020-05-19
                    相关资源
                    最近更新 更多