git:你的分支领先X次提交

这到底是怎么发生的呢?

我在一个回购工作由自己的时刻,所以这是我的工作流程:

  1. 改变文件
  2. 提交
  3. 重复1-2次直到满意
  4. 推送至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)
520077 次浏览

它只是提醒你当前分支和运行当前轨迹的分支之间的区别。请提供更多信息,包括什么分支打印在消息中,你在哪里推/拉当前分支。

我认为你误读了消息-你的分支不是在master之前,它是 master。它在origin/master之前,后者是一个远程跟踪分支机构,它记录了上次pushpullfetch中的远程存储库的状态。它会告诉你你做了什么;你走到了遥控器前面,它在提醒你按。

如果在执行git pull remote branch之后得到此消息,请尝试使用git fetch来跟踪它。(可选地,运行git fetch -p从repo中删除分支)

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

有人说你可能误解了你的信息,你没有。这个问题实际上与你的<project>/.git/config文件有关。它将是一个类似于下面的部分:

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

如果你从你的项目的.git/配置文件中删除取行,你会停止“your branch is ahead of 'origin/master' by N commits.”的烦恼发生。

我希望如此。:)

虽然这个问题有点老了……我也遇到过类似的情况,我的回答帮助我解决了一个类似的问题

首先尝试push -f或force选项

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

上面的结果是你的推送同步你的本地/分支与你的远程/分支,然而,在你的本地回购缓存仍然显示以前的提交(本地/分支…如果只有一次提交被推)作为HEAD。

要确认上述操作,在不同的位置克隆回购,并尝试比较本地/分支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了!< / em >

现在执行git pull git pull github master < / p >

git status接收

# On branch master

nothing to commit (working directory clean)

我希望这对某些人有用,因为观看的数量是如此之高,以至于搜索这个错误几乎总是把这个线程列在顶部

详细信息请参考gitref

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

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

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

每当我切换到“web”分支时,它都会告诉我,我比开发提前了100多个提交。好吧,我不再致力于开发,这是真的。我可以简单地删除这个条目,它似乎像预期的那样运行。它正确地跟踪远程引用,而不是抱怨落后于开发分支。

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

我在一台Windows电脑上遇到了同样的问题。当我运行git pull origin master命令时,我会得到“在'origin/master' by X commits之前”的警告。我发现,如果我相反地运行git pull origin并且没有指定分支,那么我将不再收到警告。

提示git pullgit fetch的答案是正确的 当git status发现.git/FETCH_HEAD.git/refs/remotes/<repository>/<branch>之间存在差异(例如.git/refs/remotes/origin/master)时,该消息就会生成。< / p >

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

使用

git pull --rebase

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

我在我的舞台服务器上有这个问题,我只做拉。 硬复位帮助我将HEAD清理到与远程相同

git reset --hard origin/master

现在我又有了:

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

使用这3个简单的命令

__abc1: __abc0

__abc1: __abc0

__abc1: __abc0

更多详细信息:https://stackoverflow.com/a/39698570/2439715

享受。

我浏览了本页上的每个解决方案,幸运的是@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

祝你好运

就我而言,这是因为我改用了熟练使用

 git checkout -B master

把它的新版本拉出来,而不是

 git checkout master

第一个命令重置master的头部到我最近的提交

我使用

git reset --hard origin/master

为了解决这个问题

我想重申上文@Marian Zburlia所提到的。它对我很有效,也会对其他人提出同样的建议。

git pull origin develop

后面应该跟着$ git pull --rebase

这将删除$ git status在最近一次拉取之后出现的注释。

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

git fetch将为你解决这个问题

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

然后,当我执行git状态时,它告诉我我的分支领先X次提交(大概是我所做的承诺的相同数量)。

我的经验是在有许多分支的团队环境中工作。我们在自己的特性分支中工作(在本地克隆中),它是git status显示我提前11次提交的其中之一。我的工作假设,就像问题的作者,是+11来自我自己的承诺

原来,我已经在几个星期前从公共develop分支中引入了更改到我的功能分支中——但忘记了!当我今天重新访问我的本地功能分支并执行git pull origin develop时,数字跳转到+41提交。在develop中已经做了很多工作,所以我的本地特性分支甚至比origin存储库中的特性分支还要超前。

因此,如果您收到这条消息,请回想一下您可能从您可以访问的其他分支(您自己的或其他分支)执行的任何拉/合并。该消息只是表明你需要将那些pulled的更改git push从本地回购回origin回购('跟踪分支'),以使事情同步。

这对我很有效

git reset --hard origin/master

输出必须是这样的

在分支dev上 HEAD现在在ae1xc41z最后提交消息

注意:在我写这个答案的时候,这个问题是非常古老的。这篇文章是在Git的第一个版本发布三年前发布的,该版本修复了许多这些问题。尽管如此,添加一个现代的答案和解释似乎是值得的。现有的公认答案建议运行git fetch -p1,这是一个好主意,尽管现在很少使用要求。在Git 1.8.2版本发布之前,这是非常必要的;Git是在最初的问题发布三年后发布的。


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


这到底是怎么发生的呢?

原来的问题是这样的:

这到底是怎么发生的呢?

问题中的是这样的事实:在git push origin master之后,OP运行git status并看到消息On branch masterYour branch is ahead of 'origin/master' by 1 commit.。为了正确地回答这个问题,我们需要将其分解成几个部分。

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

这种说法实际上有点太强烈了。你自己的本地分支,在你自己的Git存储库中,可以一个设置,Git称之为上游。或者,该分支可以上游有没有。旧版本的Git在调用上游设置方面不是很一致,但在现代Git中,它更一致。我们还有git branch --set-upstream-togit branch --unset-upstream用于设置或清除上游对象。

这些--set-upstream-to--unset-upstream影响当前分支。当前分支是你所在的on,当git statuson branch xyzzy或其他它说的时候。你可以用git checkout或since Git 2.23 -git switch选择这个分支。无论你签出的是哪个分支,那就是你正在运行的那个分支

如果你使用--unset-upstream,这个删除是当前分支的上游。没有了上游,这就停止了关于领先、落后或偏离的信息。但是这条消息是有用的,所以您可能不应该仅仅删除上游来阻止它发生。(如果你觉得没有用的话,可以随意忽略消息——毕竟不是错误。)

如果运行git branch --set-upstream-to=origin/xyzzy,将当前分支的上游设置为origin/xyzzy。对于名为xyzzy的分支,这将是典型的正确设置。一些创建分支自动的行为设置了(通常正确的)上游,而另一些则没有,所以如果你使用了自动设置正确上游的分支创建操作,你不需要做任何事情。如果你想要一个不同的上游,或者如果你使用了一个分支创建操作来设置没有上游,你可以使用这个来改变上游。

你可以设置upstream为:

  • 另一个你自己的(本地)分支:git branch --set-upstream-to=experiment使你自己的本地experiment成为当前分支的上游;或
  • 任何你的remote-tracking名字,如origin/mainorigin/masterorigin/xyzzy。这些是git branch -r输出的名称。Git将它们称为远程跟踪分支名称(我喜欢去掉单词"branch"这里),我们将在稍后详细讨论它们。

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

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

其中$branch是当前的分支名称,而$upstream是其上游设置的字符串(来自上面的git branch --set-upstream-to)。在这两个名字之间有三个点,并且--count--left-right和三个点都需要让git rev-list吐出这两个数字。


__abc6如果你使用的是2.23或更高版本的Git,最好迁移到git switch,因为它避免了一些棘手的git checkout行为,这些行为在历史上曾让初学者陷入麻烦(有时甚至会绊倒Git专家)。然而,如果你习惯了git checkout,你可以继续使用它,只要你喜欢,因为它仍然被支持。真正的问题基本上是git checkout过于强大,可能会意外地破坏工作。新的git switch故意降低功能,不会这样做;“故意破坏我的作品”;操作被移动到git restore

__abc3可能位于没有分支,Git称之为分离的头模式。如果你使用git checkout,它可以让你突然进入这种模式(尽管它会打印一个很大的可怕警告,所以如果你没有看到可怕的警告,它不会那样做),但如果你使用git switch,你必须使用git switch --detach 允许分离- head模式。在这个模式中没有任何错误的,你只需要小心,不要丢失你所做的任何新提交。如果不小心就很容易弄丢。在正常模式下,Git不会像这样丢失新提交。

如果处于分离HEAD模式,则没有上游——根据定义,因为没有分支——这个问题中的任何东西都不适用。


可达性

这部分有点技术性,我将把大部分内容外包给一个网站像(a) Git那样思考。我将在这里总结它:分支机构名称(像mainxyzzy)和remote-tracking名字 (origin/mainorigin/xyzzy)是Git 发现的提交方式。Git是关于提交的。你的分支名称只对发现你的提交有影响。当然,如果你找不到它们,你就有麻烦了,所以你的分支名称很重要。但关键是xyzzy0,这是一个专业术语。

Git存储库中的每个提交都有编号,用一个由字母和数字组成的又大又丑的十六进制字符串。这是提交的散列ID, Git 真的就是这样找到提交的。

每次提交都包含两件事:每个源文件的完整快照(以一种特殊的、压缩的、git化的和重复数据删除的形式),以及关于提交本身的一些信息:例如,元数据告诉谁做的,什么时候做的,为什么做(他们的日志消息)。在元数据中,每个提交都保存了一些先前提交的提交号。这意味着一个提交可以找到另一个更早提交。

正如像(a) Git那样思考所指出的,这有点像火车。一旦你的火车,这是伟大的,在这种情况下,它会带你向后,自动,到所有较早的火车站。但是首先你必须找到你的路,一个火车站。Git分支名可以做到这一点:它保存了分支上提交的最新的的哈希ID。

我们可以这样画:

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

分支名称branch保存了最新的提交的哈希ID。我们说名字指出提交。不管哈希ID到底是什么,我们只是用字母H来代替它。

H是一个实际的提交,所以它有一个保存的快照——你的文件——和一些元数据。在元数据中,Git保存了早些时候提交的哈希ID。我们将其称为前面的commit 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来获取分支,然后进行提交时,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而言——就是你正在“on”的那个;现在。这就是我们在这个图中附加的HEAD。所以现在,作为git commit的最后一部分,Git将I的哈希ID写到名字xyzzy中。这使得它指向提交I,如下所示:

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

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

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

这就是分支名称的工作原理。说到底,这真的很简单:它只需要你同时思考几件事。名称查找提交。它找到最新的提交。从那里,Git工作在向后,因为每次提交都会找到一个早些时候提交。

那远程跟踪的名字呢?这里的技巧是你的Git与其他Git对话。你有你的 mastermain;他们有他们的。你有你的 xyzzy分支,他们也可以有他们的分支。

你的Git 可以每次都会调用他们的Git,并询问他们的分支名称。然而,这并不是很有效,如果你与互联网切断了联系,就无法工作。4在任何情况下,Git都不会这样做。相反,当你的Git调用他们的Git并从他们那里获得所有分支名称和哈希id的列表时,你的 Git将这些名称和哈希id存储在你的存储库中。这发生在你运行git fetch.5

但是有一个问题。他们的mainmaster,或者他们的xyzzy(如果他们有的话),并不一定意味着相同提交为你的 mainmasterxyzzy。解决方案很简单:Git只是获取他们的分支名称,并将其转换为你的remote-tracking名字

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

如果你使用--prune,这将处理他们删除一些分支名称的情况。假设它们有一个名为oldstuff的分支。你之前得到了它,所以你的远程跟踪名称中有origin/oldstuff。然后他们删除 oldstuff,所以这次他们…只是再也没有了。如果没有--prune, Git会忽略这一点。你保留你的旧origin/oldstuff,即使它现在已经死了。 --prune,你的Git说:oldstuff0并删除它:在oldstuff1 Git中的远程跟踪名称不对应于他们的oldstuff2名称之一,就会被删除。

修剪选项可能一直都应该是默认选项,但它不是,因此现在也不能。然而,你可以将fetch.prune配置为true,并将使配置为你的 default。


与2010年相比,这种情况在2021年不那么常见了。它在2005年Git首次发布时更为普遍。它曾经是这样的情况,比如说,在飞往Linux会议的航班上,你无法获得任何访问互联网,无论价格如何。

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

6Git通常非常重视向后兼容性。它拿走了1。例如,将push.default的默认设置从matching更改为simple


git rev-list如何得到这两个数字

前面,我注意到git status打印的前方、后方、最新或发散的消息是通过运行:

git rev-list --count --left-right $branch...$upstream
这里git rev-list所做的是计数可达提交。在gitrevisions文档中描述的三点语法,产生了集合论中所谓的对称差分。然而,在非数学术语中,我们可以将其视为进行两次提交可达性测试, 我们可以这样画:

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

在这里,提交J可以从你的分支名称xyzzy到达,因为名称指向那里。Commit I可以从Commit J到达,所以它也算数。这将导致返回提交__abc4 -正如你可以从图表中看到的,这有点特殊。

同时,提交K可以从你的远程跟踪名称origin/xyzzy到达。从K可以到达Commit H。从后面的提交H开始,提交GF等等都是可达的。但两条“铁轨”;加入在提交H时:提交H和所有以前的提交都可以从origin/xyzzy0到达。

这使得提交I-J很特别,因为它们只能从名字xyzzy到达,而K也很特别,因为它只能从名字origin/xyzzy到达。三点表示法找到这些提交:只能从一个名称到达的提交,或者只能从另一个名称到达的提交。

如果我们把分支名称放在左边,把它的上游放在右边,并使用三点表示法,我们将找到这种情况下的所有这三个提交。使用--count使git rev-list打印这个数字:3。使用--left-right告诉git rev-list更聪明:它应该计算由于名称——当前分支名称——而被计数的提交数量,以及由于上游的正确的名称而被计数的提交数量。所以有了这两个选项和三个点,我们得到:

2       1

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

如果没有--count选项,git rev-list将列出哈希id,前缀为<(左)或>(右)符号。使用git log代替git rev-list,如下所示:

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

(再次注意这三个点:参见gitrevisions并搜索对称差异)我们将得到如图所示的三次提交,同样以<>作为前缀。

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

领先的,落后的,发散的或最新的

那么,假设我们运行:

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

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

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

  • nonzero, 0:在当前分支上有不在上游的提交。上游上没有不在当前分支上的提交。所以我们的分支是上游的之前,

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

  • 非零,非零:这就像我上面画的图。当前分支和上游分支同时处于彼此的前后位置。git status命令将使用单词diverged

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

这到底是怎么发生的呢?

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

原因很简单:在过去,git push git status0。运行git fetch origingit fetch,让你自己的Git调用GitHub上的Git,读取他们的信息,并意识到你的git push已经工作了。

当你运行git push时,你让你的Git调用一些其他的Git。然后,你的Git向其他Git提供你所拥有的任何新提交,它们将需要完成git push。他们把这些提交放到某个地方。7然后你的Git问他们的Git——默认情况下礼貌地问——他们是否愿意,如果可以的话,请设置他们的 分支 name来引用最近的提交,通过它的哈希ID,如你的分支名称所示。这里没有远程追踪的东西。你只是要求他们设置你正在使用的相同的名称

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

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

在旧的Git版本中,你的Git只是没费心做这个。在Git版本1.8.2中,Git作者最终修复了这个问题:一个成功的git push会让Git更新你的远程跟踪名称,基于他们的Git同意你的Git提供的更新。所以这类事情不再经常发生了。


在过去糟糕的日子里,他们把他们直接放入他们的仓库。在现代Git中,它们将它们放在隔离区域中,只有在实际接受新提交时才将它们迁移到存储库中。

__abc0当然,像GitHub这样的地方也提供了像受保护的分支这样的功能,例如,它只是对每一个 push说不。我们还可以发明一些更奇特的场景,比如当你有多台计算机,你忘记了你通过计算机A进行了新的提交,现在尝试从计算机B进行提交。


如果你不是唯一一个在做git push

假设Alice和Bob都克隆了一些GitHub存储库。这个存储库中的开发发生在分支dev (for develop)上。所以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 发现通过从名称开始并向后工作来提交。所以他们用“not a fast forward”来拒绝推进。投诉。

Bob现在需要将commit I从GitHub拖拽到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时。

只是说说我的遭遇。

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

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

通过undo last commit解决并取消当前gitignore中的文件

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