git:你的分支领先 X 次提交
这实际上是如何发生的?
我现在正在一个仓库中工作,所以这是我的工作流程:
- 更改文件
- 提交
- 重复 1-2 直到满意
- 推送到 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)
How does this actually come about?
I am working in one repo by myself at the moment, so this is my workflow:
- Change files
- Commit
- Repeat 1-2 until satisfied
- Push to master
Then when I do a git status
it tells me that my branch is ahead by X commits (presumably the same number of commits that I have made). Is it because when you push the code it doesn't actually update your locally cached files (in the .git folders)? git pull
seems to 'fix' this strange message, but I am still curious why it happens, maybe I am using git wrong?
including what branch is printed in the message
My local branch is ahead of master
where do you push/pull the current branch
I am pushing to GitHub and pulling to whichever computer I happen to be working on at that point in time, my local copy is always fully up to date as I am the only one working on it.
it doesn't actually check the remote repo
That is what I thought, I figured that I would make sure my understanding of it was correct.
are you passing some extra arguments to it?
Not ones that I can see, maybe there is some funny config going on on my end?
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
如果您在执行
git pull 远程分支
后收到此消息,请尝试使用git fetch
跟进。 (可选地,运行 git fetch -p 来从存储库中删除已删除的分支)Fetch 似乎更新了远程分支的本地表示,当您执行 git pull 时不一定会发生这种情况远程分支。
If you get this message after doing a
git pull remote branch
, try following it up with agit fetch
. (Optionally, rungit fetch -p
to prune deleted branches from the repo)Fetch seems to update the local representation of the remote branch, which doesn't necessarily happen when you do a
git pull remote branch
.使用
--rebase 选项意味着 git 会将您的本地提交移到一边,与远程同步,然后尝试从新状态应用您的提交。
Use
The --rebase option means that git will move your local commit aside, synchronise with the remote and then try to apply your commits from the new state.
使用这 3 个简单命令
第 1 步:
git checkout
第 2 步:
git pull -s recursive -X thoses< /code>
第 3 步:
git reset --hard origin/
更多详细信息:https://stackoverflow.com/a/39698570/2439715
尽情享受。
Use these 3 simple commands
Step 1 :
git checkout <branch_name>
Step 2 :
git pull -s recursive -X theirs
Step 3 :
git reset --hard origin/<branch_name>
More details : https://stackoverflow.com/a/39698570/2439715
Enjoy.
这对我有用
git reset --hard origin/master
输出必须类似于
On Branch dev
HEAD 现在位于 ae1xc41z 最后提交消息
This worked for me
git reset --hard origin/master
The output must look like
On branch dev
HEAD is now at ae1xc41z Last commit message
我认为您误读了该消息 - 您的分支不是在
master
之前,而是是master
。它位于origin/master
之前,后者是一个远程跟踪分支,用于记录上次推送
的远程存储库的状态,拉动
,或获取
。它准确地告诉你你做了什么;你领先于遥控器,它会提醒你按下。I think you’re misreading the message — your branch isn’t ahead of
master
, it ismaster
. It’s ahead oforigin/master
, which is a remote tracking branch that records the status of the remote repository from your lastpush
,pull
, orfetch
. It’s telling you exactly what you did; you got ahead of the remote and it’s reminding you to push.我在我的舞台服务器上遇到了这个问题,我只进行拉取。
硬重置帮助我将 HEAD 清理到与远程相同。
所以现在我又有了:
I had this issue on my stage server where I do only pulls.
And hard reset helped me to clean HEAD to the same as remote.
So now I have again:
有人说你可能误读了你的信息,但事实并非如此。这个问题实际上与您的
/.git/config
文件有关。其中将有一个与此类似的部分:如果您从项目的 .git/config 文件中删除 fetch 行,您将停止“您的分支领先于 'origin/master' by
N
次提交”。烦恼的发生。或者说我希望如此。 :)
Someone said you might be misreading your message, you aren't. This issue actually has to do with your
<project>/.git/config
file. In it will be a section similar to this:If you remove the fetch line from your project's .git/config file you'll stop the "Your branch is ahead of 'origin/master' by
N
commits." annoyance from occurring.Or so I hope. :)
注意:在我写这个答案时,这个特定的问题已经很老了。它是在修复了许多此类问题的 Git 版本首次发布三年前发布的。不过,似乎值得添加一个现代答案以及解释器。 现有接受的答案建议运行
git fetch -p
,1这是一个好主意,尽管现在很少需要。在 Git 1.8.2 版本发布之前,这是更加必要的; Git 在最初的问题提出三年后发布。1
-p
或--prune
选项不是必需的,仅在链接答案中以括号形式建议。请参阅下面较长的部分了解它的作用。这实际上是如何发生的?
原来的问题是:
所讨论的这个事实是,在 git push origin master 后,OP 运行 git status 并看到消息 Onbranch master 后跟
您的分支比“origin/master”领先 1 次提交。
为了正确回答这个问题,我们需要将其分解为多个部分。首先,每个(本地)分支都有一个上游设置
这个说法实际上有点太强了。在您自己的 Git 存储库中,您自己的每个本地分支都可以拥有 Git 称为上游的一个设置。或者,该分支可以没有上游。旧版本的 Git 并不太一致地将其称为上游设置,但在现代 Git 中,它更加一致。我们还有 gitbranch --set-upstream-to 和 gitbranch--unset-upstream 用于设置或清除上游。
这些
--set-upstream-to
和--unset-upstream
会影响当前分支。当git status
显示onbranch xyzzy
或其他任何内容时,当前分支就是您on
的分支。您选择使用git checkout
或从Git 2.23开始的git switch
这个分支。2无论您签出什么分支,这就是您所在的分支。3如果您使用
--unset-upstream
,这将删除当前分支的上游。如果没有上游,这就会阻止有关领先、落后或分歧的消息。但此消息是有用的,因此您可能不应该仅仅删除上游来阻止其发生。 (如果您发现它没有用,请随意忽略该消息 - 毕竟它不是错误。)如果您运行
git分支-- set-upstream-to=origin/xyzzy
,将当前分支的上游设置为origin/xyzzy
。对于名为xyzzy
的分支,这将是典型的正确设置。有些创建分支的行为自动会设置(通常是正确的)上游,而有些则不会,因此,如果您使用自动设置正确上游的分支创建操作,则无需执行任何操作。如果您想要不同的上游,或者如果您使用了设置no上游的分支创建操作,则可以使用它来更改上游。您可以将上游设置为:
gitbranch --set-upstream-to=experiment
使您自己的本地实验
成为当前分支的上游;或origin/main
或origin/master
或origin/xyzzy
。这些是 gitbranch -r 输出的名称。 Git 调用这些远程跟踪分支名称(我喜欢在这里删除“分支”这个词),我们稍后会详细讨论它们。git status
打印的领先、落后、最新或分歧消息源自运行看起来有些神奇的命令:其中
$branch< /code> 是当前的 branch 名称,
$upstream
是来自其上游设置的字符串(来自gitbranch --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可以在无分支上,即 Git 所谓的分离 HEAD 模式。如果你使用 git checkout ,它可能会让你突然进入这种模式(尽管它会打印一个很大的可怕警告,所以如果你没有看到可怕的警告,它就不会这样做),但是如果如果您使用
git switch
,则必须使用git switch --detach
允许分离HEAD模式。这种模式没有任何问题,您只需要在进入该模式后小心,不要丢失您所做的任何新提交。如果您不小心,很容易丢失它们。在正常模式下,Git 不会像这样丢失新的提交。如果您处于分离的 HEAD 模式,那么根据定义,您没有上游,因为您没有分支,并且这个问题中的所有内容都不适用。
可达性
这部分有点技术性,我将把其中大部分外包给一个网站,Think Like (a) git。我将在这里总结如下:分支名称(例如
main
或xyzzy
)和远程跟踪名称 (origin/main
,origin/xyzzy
) 是 Git 查找 提交的方式。 Git 的核心就是提交。您的分支名称仅对于查找您的提交很重要。当然,如果你找不到它们,你就有麻烦了,所以你的分支名称很重要。但关键是可达性,这是一个技术术语。Git 存储库中的每个提交都有编号,带有一个由字母和数字组成的丑陋的 十六进制 字符串。这是提交的哈希 ID,也是 Git 真正找到提交的方式。
每个提交都包含两件事:每个源文件的完整快照(以特殊的、压缩的、Git 化的和去重的形式),以及有关提交本身的一些信息:元数据告诉谁做了例如,它、何时以及为什么(他们的日志消息)。在元数据中,每个提交都保存一些早期提交的提交编号。这意味着一个提交可以找到另一个更早的提交。
正如 Think Like (a) Git 所指出的,这有点像火车。一旦您登上火车,这真是太棒了,在这种情况下,火车会自动带您倒退到所有较早的火车站。但首先您必须找到前往火车站的路。 Git 分支名称可以做到这一点:它保存分支上最新提交的哈希 ID。
我们可以这样画:
分支名称
branch
保存最新提交的哈希 ID。我们说名称指向提交。无论哈希 ID 到底是什么,我们都只是使用字母H
来代替它。H
是一个实际的提交,因此它有一个已保存的快照(您的文件)和一些元数据。在元数据中,Git 保存了早期提交的哈希 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 checkout 或 git switch 获取分支,然后进行新提交时,Git 自动更新分支名称的存储哈希 ID。也就是说,假设我们有一系列像这样的提交:
我们“在”分支
xyzzy
上,我喜欢通过附加特殊名称HEAD
来表示它。当图中有多个分支名称时,这一点很有用。请注意,H
目前是最新 提交。但现在我们将以通常的方式再做一个。这个新提交会获得一个新的、唯一的、又大又丑的十六进制哈希 ID,就像任何提交一样。 Git 确保新提交向后指向提交
H
,因为这是我们用来创建新提交的提交。我们将使用字母I
来表示这个新的提交。让我们画一下:这张图实际上是提交中的:Git 已经创建了
I
,但尚未完成git commit
操作。问自己这个问题:稍后我们将如何找到提交I
?我们需要它的哈希 ID。我们可以在哪里存储哈希 ID?如果您说:在分支名称中,那么您是对的。事实上,正确的分支名称(无论如何,就 Git 而言)就是您现在“所在”的分支名称。这就是我们在此绘图中附加
HEAD
的部分。现在,作为git commit
的最后一部分,Git 将I
的哈希 ID 写入名称xyzzy
中。这使得它指向提交I
,如下所示:现在绘图中没有任何扭结的原因,因此我们可以将其理顺:
这就是分支名称的工作原理。最后,这真的非常简单:只需要您同时思考几件事即可。该名称找到提交。它找到最新提交。从那里开始,Git 会向后工作,因为每次提交都会找到较早的提交。
远程跟踪名称怎么样?好吧,这里的技巧是你的 Git 与其他 Git 进行对话。 每个 Git 都有自己的分支名称。您有您的
master
或main
;他们有他们的。您拥有您的xyzzy
分支,他们也可以拥有自己的分支。您的 Git可以每次都调用他们的 Git,并询问他们的分支名称。但这不是很有效,而且如果您与 Internet 断开连接,则不起作用。4 无论如何,Git 都不会这样做。相反,当您的 Git 调用他们的 Git 并从他们那里获取所有分支名称及其哈希 ID 的列表时,您的 Git 会获取这些名称和哈希 ID 并将它们存储在中您的存储库。当您运行
git fetch
时会发生这种情况。5但有一个问题。他们的
main
或master
或他们的xyzzy
(如果有的话)并不一定意味着提交相同 您的main
或master
或xyzzy
。解决方案很简单:Git 只需获取他们的分支名称并将其转换为您的远程跟踪名称。如果
origin
的main
或master
或xyzzy
已移动,您只需运行git fetch 或
git fetch origin
,也许使用--prune
。你的 Git 调用他们的 Git。他们列出了分支名称并提交哈希 ID。如果有必要,你的 Git 会从他们那里获取任何新的提交:他们有的提交,而你没有。然后,您的 Git 将它们的分支名称转换为您的远程跟踪名称,并创建或更新您的远程跟踪名称以记住它们分支名称指向的位置,在您运行此git fetch
的那一刻。如果您使用
--prune
,这会处理他们删除某些分支名称的情况。假设他们有一个名为oldstuff
的分支。您较早获得了它,因此您的远程跟踪名称中有origin/oldstuff
。然后他们删除oldstuff
,所以这一次他们......只是不再拥有它了。如果没有--prune
,您的 Git 会忽略这一点。你可以保留你的旧origin/oldstuff
,即使它现在已经死了。 使用--prune
,你的 Git 会说:哦,呵呵,这看起来已经死了并将其修剪掉: 中的远程跟踪名称em>你的 Git 与他们的分支名称不对应,就会被删除。prune 选项可能应该一直是默认选项,但事实并非如此,因此现在不能如此。6 不过,您可以将
fetch.prune
配置为 < code>true 并将其设为默认值。4这种情况在 2021 年已经不像 2010 年那样常见了。在 2005 年 Git 首次发布时,这种情况要普遍得多。过去的情况是,比如说,在参加 Linux 会议的航班上,您无法以任何价格任何访问互联网。
5选择使用哪些名称以及何时使用它们实际上是此处答案的一部分。它随着时间的推移在 Git 中发生了变化,并且仍在发生一些变化,尽管仍然存在各种限制。但我们不会详细讨论所有细节。
6Git 通常非常重视向后兼容性。例如,从 1.x 到 2.0 的转换将
push.default
默认设置从matching
更改为simple
。git rev-list
如何获取这两个数字之前,我注意到
git status
打印的提前、落后、最新或分歧消息来自运行:git rev-list
在这里所做的是计算可到达的提交。 gitrevisions 文档中描述的三点语法产生了集合论中所谓的 < em>对称差异。不过,用非数学术语来说,我们可以将其视为进行两次提交可达性测试,我们可以这样画:
在这里,可以从您的分支名称
xyzzy
访问提交J
,因为该名称指向那里。提交I
可以从提交J
访问,因此它也很重要。这会返回到提交H
——正如您从图中看到的那样,它有点特殊。同时,可以从您的远程跟踪名称
origin/xyzzy
访问提交K
。可以从K
访问提交H
。从后面的提交H
开始,提交G
和F
等也都是可达的。但是两个“铁轨”在提交H
处连接:提交H
和所有早期提交都可以从两个名称访问嗯>。这使得提交
IJ
变得特殊,因为它们*只能从名称xyzzy
访问,而K
则特殊,因为它*只能从名称访问名称origin/xyzzy
。三点表示法找到这些提交:只能从一个名称访问的提交,或只能从另一个名称访问的提交。如果我们将分支名称放在左侧,将其上游放在右侧,并使用三点表示法,我们将找到这种情况下的所有三个提交。使用
--count
使git rev-list
打印这个数字: 3. 使用--left-right
告诉git rev-list不过,为了更聪明:它应该计算由于 left 名称(当前分支 名称)而计算的提交数量以及正在计算的提交数量计数是因为右一个,即上游。因此,通过这两个选项和三个点,我们得到:
作为输出,告诉我们在
xyzzy
上有两个提交不在origin/xyzzy
上,并且位于origin/xyzzy
上但不在xyzzy
上的提交。这些是提交J
-and-I
(在xyzzy
上)和K
(在origin/xyzzy
) 分别。如果没有
--count
选项,git rev-list
将列出哈希 ID,前缀为<
(左)或>
(右)符号。使用git log
而不是git rev-list
,如下所示:(再次注意三个点:请参阅 gitrevisions 并搜索对称差异)我们将得到显示的三个提交,同样以
<
或>
为前缀代码> 视情况而定。这是一种查看哪些提交位于您的分支上以及哪些提交位于上游的简单方法。它通常与
--decorate
、-- 一起使用更有用。 oneline
和--graph
(在某些情况下您可能还需要添加--boundary
)。领先、落后、发散或最新
所以,假设我们已经运行:(
或者 - 请参阅 gitrevisions< /a> 再次使用此处的
$branch@{upstream}
)并获得我们的两个计数。这些可以是:0
和0
:我们的分支名称和远程跟踪名称(或上游中的任何名称)指向相同< /em> 提交。没有人领先或落后。git status
命令会显示您的分支已更新为“”
。非零,零:当前分支上有不在上游的提交。上游没有不在当前分支上的提交。所以我们的分支领先上游。
零,非零:当前分支上没有不在上游的提交,但在上游有一些不在当前分支的提交。这意味着我们的分支落后上游。
非零,非零:这就像我上面画的图。当前分支及其上游同时相互领先和落后。
git status
命令将使用单词diverged
。我们现在要跳回原来的问题。我们假设当前分支的 upstrema 是远程跟踪名称。 请注意,
git rev-list
获得的计数基于我们的远程跟踪分支名称中的内容。这实际上是如何发生的?
在 OP 的场景中,只有一个人进行新的提交并使用 git push 发送它们。如果我是一个人,我可能会从 GitHub 上 git clone 一些东西,然后进行一两次新的提交,然后 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< /code> 已经起作用了。
当您运行 git push 时,您的 Git 会调用其他 Git。然后,您的 Git 向其他 Git 提供您拥有的、他们没有的、他们需要完成 git Push 的任何新提交。他们将这些提交放在某个地方。7然后你的 Git 询问他们的 Git(默认情况下是礼貌地询问)如果可以的话,请设置他们的 < strong>分支名称,通过其哈希 ID 引用最新提交,如您的分支名称中所示。这里没有进行远程跟踪的事情。您只需要求他们设置您正在使用的相同名称。
一般来说,如果您只是向其存储库添加新的提交,这种礼貌的请求就会成功。如果你要求他们“丢失”一些提交,它就会失败:你会收到关于这是“非快进”的抱怨。如果您是唯一向他们发送新提交的人,他们应该永远不会以这种方式丢失任何东西,因此这应该始终有效。8
如果推送失败,您的 Git 最好保持远程跟踪名称不变。您的 Git 从未从他们的 Git 中获取可以让您的 Git 更新的信息。但是,如果推送成功...那么,他们只需将其分支名称设置为您的 Git 要求他们使用的哈希 ID。现在你的 Git 知道他们的分支名称指向哪里了。您的 Git 应该更新您的远程跟踪名称。
在旧的 Git 版本中,您的 Git 只是懒得这样做。在 Git 版本 1.8.2 中,Git 作者最终解决了这个问题:成功的 git Push 会让您的 Git 更新您的远程跟踪名称,因为他们的 Git 同意您提供的更新。所以这样的事情已经很少发生了。
7在过去的糟糕日子里,他们直接将它们放入存储库中。在现代 Git 中,他们将它们放入隔离区,只有在它们确实接受新提交时才将它们迁移到存储库中。
8当然,像 GitHub 这样的地方也提供诸如受保护的分支之类的功能,例如,它只是对每一次推送说不。我们还可以发明更奇特的场景,例如当您拥有多台计算机并且忘记通过计算机 A 进行并推送新的提交,现在尝试从计算机 B 推送时。
如果您不是唯一一个执行 git 的人怎么办? Push
假设 Alice 和 Bob 都克隆了一些 GitHub 存储库。此存储库中的开发发生在分支 dev(用于开发)上。因此,Alice 从她的
origin/dev
中创建了自己的dev
:同样也创建了自己的
dev
:Bob GitHub 存储库
dev
也以H
结尾。 (它们没有origin/dev
:GitHub 存储库不关心远程跟踪名称。)Alice 进行了一次新提交,我们将其称为
I
,并绘制在 Alice 的计算机上就像这样:同时,Bob 进行了一次新的提交,我们将其称为
J
:现在 Alice 和 Bob 都尝试
git push origin dev
。他们中的一个首先到达那里 - 也许是 Alice:Bob 发送了提交
J
,该提交到 GitHub,看起来像这样:如果 GitHub 这样做,这将“丢失”Alice 的提交
I
>,因为 Git 是通过从名称开始并向后工作来查找提交的。因此,他们以“不是快进”为由拒绝了这一推动。Bob 现在需要将提交
I
从 GitHub 拉入 Bob 自己的存储库,以便 Bob 看到:Bob 应该使用
git fetch
或来执行此操作>git fetch origin
,也许使用--prune
(或将fetch.prune
设置为true
)。 现在当Bob运行git status
时,他将收到“分歧”消息。现在,鲍勃(作为推送竞赛的失败者)要弄清楚如何将他的工作(提交
J
)与Alice的工作(提交I
)结合起来。代码>)。结合工作的方式有多种。两个主要的是 git merge 和 git rebase。我们不会在这里讨论谁应该做什么、何时做什么以及为什么,只是事实上,当您认为自己严格领先于其他 Git 时,这是您可能会遇到“分歧”状态的另一种方式。Note: this particular question is, at the time I write this answer, quite old. It was posted three years before the first release of a version of Git that fixed many of these problems. It seems worth adding a modern answer along with explainers, though. The existing accepted answer suggests running
git fetch -p
,1 which is a good idea, although less-often required these days. It was much more necessary before Git version 1.8.2 came out; that Git was released three years after the original question.1The
-p
or--prune
option is not required and is suggested only parenthetically in the linked answer. See the longer sections below for what it does.How does this actually come about?
The original question asks:
The this in question is the fact that after
git push origin master
, the OP runsgit status
and sees the messageOn branch master
followed byYour branch is ahead of 'origin/master' by 1 commit.
To properly answer the question, we need to break it up into pieces.First, each (local) branch has an upstream setting
This claim is actually just a bit too strong. Each of your own local branches, in your own Git repository, can have one setting that Git calls an upstream. Or, that branch can have no upstream. Old versions of Git were not very consistent about calling this an upstream setting, but in modern Git, it's more consistent. We also have
git branch --set-upstream-to
andgit branch --unset-upstream
for setting, or clearing, an upstream.These
--set-upstream-to
and--unset-upstream
affect the current branch. The current branch is the one you areon
, whengit status
sayson branch xyzzy
or whatever it is it says. You choose this branch withgit checkout
or—since Git 2.23—git switch
.2 Whatever branch you checked out, that's the one you're on.3If you use
--unset-upstream
, this removes the current branch's upstream. With no upstream, this stops the message about being ahead or behind or diverged. But this message is meant to be useful, so you probably shouldn't just remove the upstream as a way to make it stop happening. (Do feel free to ignore the message—it's not a error after all—if you don't find it useful.)If you run
git branch --set-upstream-to=origin/xyzzy
, that sets the current branch's upstream toorigin/xyzzy
. For a branch namedxyzzy
, this would be the typical correct setting. Some acts of creating branches automatically set the (typically-correct) upstream, and some don't, so if you used a branch-creating operation that set the right upstream automatically, you need not do anything. If you want a different upstream, or if you used a branch-creating operation that set no upstream, you can use this to change the upstream.The things you can set an upstream to are:
git branch --set-upstream-to=experiment
makes your own localexperiment
the upstream of the current branch; ororigin/main
ororigin/master
ororigin/xyzzy
. These are the names output bygit branch -r
. Git calls these remote-tracking branch names (I like to drop the word "branch" here), and we'll talk about them more in a moment.The ahead, behind, up-to-date, or diverged message that
git status
prints is derived from running the somewhat magic-looking command:where
$branch
is the current branch name, and$upstream
is the string from its upstream setting (fromgit branch --set-upstream-to
above). There are three dots between the two names here, and the--count
,--left-right
, and three dots are all required to getgit rev-list
to spit out the two numbers.2If you have Git 2.23 or later, it's a good idea to move to
git switch
because it avoids some trickygit checkout
behaviors that have historically led beginners into trouble (and occasionally even tripped up Git experts). However, if you are used togit checkout
, you can keep using it as long as you like, as it's still supported. The real problem is basically thatgit checkout
was overly powerful and could destroy work unexpectedly. The newgit switch
is deliberately less-powerful and won't do that; the "destroy my work on purpose" operations were moved intogit restore
.3It's possible to be on no branch, in what Git calls detached HEAD mode. If you use
git checkout
it can put you in this mode suddenly (though it prints a big scary warning, so if you don't see the scary warning, it didn't do that), but if you usegit switch
, you must allow detached-HEAD mode withgit switch --detach
. There's nothing wrong with this mode, you just need to be careful once you're in it, not to lose any new commits you make. It's easy to lose them if you're not careful. In normal mode, Git won't lose new commits like this.If you're in detached HEAD mode, you have no upstream—by definition, because you have no branch—and none of the stuff in this question applies.
Reachability
This part is a bit technical and I will outsource much of it to a web site, Think Like (a) Git. I will summarize it here though like this: branch names (like
main
orxyzzy
) and remote-tracking names (origin/main
,origin/xyzzy
) are how Git finds commits. Git is all about the commits. Your branch names only matter for finding your commits. Of course, if you can't find them, you're in trouble, so your branch names do matter. But the key is reachability, which is the technical term.Each commit in a Git repository is numbered, with a big ugly hexadecimal string of letters and digits. This is the commit's hash ID and it's how Git really finds the commit.
Each commit contains two things: a full snapshot of every source file (in a special, compressed, Git-ified, and de-duplicated form), and some information about the commit itself: metadata telling who made it, when, and why (their log message), for instance. In the metadata, each commit holds the commit number(s) of some earlier commit(s). This means that one commit can find another—earlier—commit.
As Think Like (a) Git notes, this is a bit like a railway train. It's great once you're on the train, which in this case will take you backwards, automatically, to all the earlier train stops. But first you have to find your way to a train station. A Git branch name will do that: it holds the hash ID of the latest commit on your branch.
We can draw that like this:
The branch name
branch
holds the hash ID of the latest commit. We say that the name points to the commit. Whatever big ugly hash ID that really is, we've just used the letterH
to stand in for it here.H
is an actual commit, so it has a saved snapshot—your files—and some metadata. In the metadata, Git saved the hash ID of an earlier commit. We'll call that earlier commitG
. We say thatH
points toG
. Git can findH
by the branch name pointer, and that gives Git access to the commit, including the metadata, so now Git has the hash ID of earlier commitG
.G
is of course also an actual commit: it has a saved snapshot and some metadata. In the metadata forG
, Git saved the hash ID of an earlier commitF
. We say thatG
points toF
, and now Git can findF
using this saved hash ID.This repeats forever, or rather, until we get to the very first commit ever. That commit (presumably we'd call it
A
here) doesn't point backwards to an earlier commit, because there is no earlier commit.This concept of reachability is basically a summary of what happens if we start at commit
H
, as found by branch namebranch
, and work backwards. We reach commitH
, which reaches backwards to commitG
, which reaches back toF
, and so on.Branch names and remote-tracking names
As we just noted, a branch name holds the raw hash ID of some commit. That lets Git find that commit. There's one other special feature about a branch name though.
When you use
git checkout
orgit switch
to get on a branch, and then make a new commit, Git automatically updates the branch name's stored hash ID. That is, suppose we have a series of commits like this:We're "on" branch
xyzzy
, which I like to denote by attaching the special nameHEAD
to it. This is useful when there's more than one branch name in the diagram. Note thatH
is, at the moment, the newest commit. But now we'll make another one, in the usual way.This new commit gets a new, unique, big ugly hexadecimal hash ID, just like any commit. Git makes sure that the new commit points backwards to commit
H
, since that's the commit we used to make the new commit. We'll use the letterI
to represent this new commit. Let's draw it in:This picture is actually mid-commit: Git has made
I
, but isn't done with thegit commit
action yet. Ask yourself this question: how will we find commitI
later? We're going to need it's hash ID. Where can we store a hash ID?If you said: in a branch name, you're right. In fact, the right branch name—as far as Git is concerned, anyway—is the one you're "on" right now. That's the one we've attached
HEAD
to in this drawing. So now, as the last part ofgit commit
, Git writesI
's hash ID into the namexyzzy
. This makes it point to commitI
, like so:and now there's no reason for the kink in the drawing, so we can straighten it out:
That's how branch names work. It's really pretty simple, in the end: it just requires getting your head around several things at once. The name finds the commit. It finds the latest commit. From there, Git works backwards because each commit finds an earlier commit.
What about the remote-tracking names? Well, the trick here is that your Git talks to some other Git. Each Git has its own branch names. You have your
master
ormain
; they have theirs. You have yourxyzzy
branch and they can have theirs too.Your Git could call up their Git, all the time, every time, and ask them about their branch names. That's not very efficient, though, and does not work if you are cut off from the Internet.4 In any case, Git doesn't do that. Instead, when your Git calls up their Git and gets a list—from them—of all of their branch names and their hash IDs, your Git takes those names and hash IDs and stores them in your repository. This happens when you run
git fetch
.5There's a problem though. Their
main
ormaster
, or theirxyzzy
if they have one, doesn't necessarily mean the same commit as yourmain
ormaster
orxyzzy
. The solution is simple though: Git just takes their branch name and turns it into your remote-tracking name.If
origin
'smain
ormaster
orxyzzy
has moved, you simply rungit fetch
orgit fetch origin
, perhaps with--prune
. Your Git calls up their Git. They list out their branch names and commit hash IDs. Your Git gets any new commits from them, if necessary: commits they have, that you don't. Then your Git turns their branch names into your remote-tracking names and creates or updates your remote-tracking names to remember where their branch names pointed, at the moment you ran thisgit fetch
.If you use
--prune
, this handles the case where they deleted some branch name(s). Let's say they had a branch namedoldstuff
. You got it earlier so you haveorigin/oldstuff
in your remote-tracking names. Then they deletedoldstuff
, so this time they ... just don't have it any more. Without--prune
, your Git ignores this. You keep your oldorigin/oldstuff
even though it's dead now. With--prune
, your Git says: Oh, huh, this looks dead now and prunes it away: a remote-tracking name in your Git that doesn't correspond to one of their branch names, just gets deleted.The prune option probably should have always been the default, but it wasn't and hence now can't be.6 You can, however, configure
fetch.prune
totrue
and make it your default.4That's less common now in 2021 than it was back in 2010. It was substantially more common in 2005 when Git was first released. It used to be the case that, say, on an airline flight to a Linux conference, you couldn't get any access to the Internet, for any price.
5The choice of which names to take, and when to take them, is actually part of the answer here. It has changed over time in Git—and is still changing a little bit—although there are still various constraints. We won't go into all the details though.
6Git generally takes backwards-compatibility pretty seriously. It took the 1.x to 2.0 changeover to change the
push.default
default setting frommatching
tosimple
, for instance.How
git rev-list
gets the two numbersEarlier, I noted that the ahead, behind, up-to-date, or diverged message that
git status
prints is derived from running:What
git rev-list
does here is count reachable commits. The three-dot syntax, described in the gitrevisions documentation, produces what in set theory is called a symmetric difference. In non-math-jargon, though, we can just think about this as doing two commit reachability tests,which we can draw like this:
Here, commit
J
is reachable from your branch namexyzzy
, because the name points there. CommitI
is reachable from commitJ
, so it counts as well. This leads back to commitH
—which as you can see from the graph, is a little special.At the same time, commit
K
is reachable from your remote-tracking nameorigin/xyzzy
. CommitH
is reachable fromK
. From commitH
on back, commitsG
andF
and so on are all also reachable. But the two "railroad tracks" join up at commitH
: commitH
and all earlier commits are reachable from both names.This makes commits
I-J
special in that they're reachable *only from the namexyzzy
, andK
special in that it's reachable *only from the nameorigin/xyzzy
. The three-dot notation finds these commits: the ones reachable only from one name, or only from the other.If we put the branch name on the left, and its upstream on the right, and use the three-dot notation, we'll find all three of these commits for this case. Using
--count
makesgit rev-list
print this number: 3. Using--left-right
tellsgit rev-list
to be smarter, though: it should count how many commits are being counted because of the left name—the current branch name—and how many commits are being counted because of the right one, the upstream. So with both options—and the three dots—we get:as the output, telling us that there are two commits on
xyzzy
that aren't onorigin/xyzzy
, and one commit that's onorigin/xyzzy
that is not onxyzzy
. These are commitsJ
-and-I
(onxyzzy
) andK
(onorigin/xyzzy
) respectively.Without the
--count
option,git rev-list
would list out the hash IDs, prefixed with<
(left) or>
(right) symbols. Usinggit log
instead ofgit rev-list
, as in:(again note the three dots: see gitrevisions and search for Symmetric Difference) we'll get the three commits shown, again prefixed with
<
or>
as appropriate.This is an easy way to see which commits are on your branch, and which commits are on the upstream. It's usually more useful with
--decorate
,--oneline
, and--graph
(and you might want to add--boundary
as well in some cases).Ahead, behind, diverged, or up-to-date
So, suppose we have run:
(or—see gitrevisions again—using
$branch@{upstream}
on the right here) and gotten our two counts. These can be:0
and0
: Our branch name and our remote-tracking name (or whatever is in the upstream) point to the same commit. Nobody is ahead or behind. Thegit status
command will sayYour branch is up to date with '<upstream>'
.nonzero, zero: There are commits on the current branch that are not on the upstream. There are no commits on the upstream that are not on the current branch. So our branch is ahead of the upstream.
zero, nonzero: There are no commits on the current branch that are not on the upstream, but there are some on the upstream that are not on the current branch. This means our branch is behind the upstream.
nonzero, nonzero: This is like the diagram I drew above. Both the current branch and its upstream are simultaneously ahead-and-behind each other. The
git status
command will use the worddiverged
.We're about to jump back to the original question now. Let's assume the upstrema of the current branch is a remote-tracking name. Note that the counts that
git rev-list
got are based on what is in our remote-tracking branch names.How does this actually come about?
In the OP's scenario, only one person is making new commits and sending them off with
git push
. If I am the one person, I mightgit clone
something from GitHub, then make a new commit or two andgit push origin master
.In modern Git,
git status
would tell me that I am up to date. In very old Git versions,git status
would now tell me that mymaster
is ahead oforigin/master
. The reason why is simple: in the old days,git push
failed to updateorigin/master
. Runninggit fetch origin
, or justgit fetch
, made your own Git call up the Git over at GitHub, read their information, and realize that yourgit push
had worked.When you run
git push
, you have your Git call up some other Git. Your Git then offers the other Git any new commits you have, that they don't, that they'll need to complete thegit push
. They take those commits and put them somewhere.7 Then your Git asks their Git—politely asks, by default—if they would, please, if it's OK, set their branch name to refer to the latest commit, by its hash ID, as seen in your branch name. There's no remote-tracking stuff going on here. You are just asking them to set the same name you're using.As a general rule, this kind of polite request succeeds if you're just adding new commits to their repository. It fails if you're asking them to "lose" some commits: you'll get a complaint about this being a "non-fast-forward". If you're the only one sending them new commits, they should never have anything to lose this way, so this should always work.8
If the push fails, it's appropriate for your Git to leave your remote-tracking name unchanged. Your Git never got the information from their Git that would let your Git update it. But if the push succeeds ... well, they just set their branch name to the hash ID that your Git asked them to use. So now your Git knows where their branch name points. Your Git should update your remote-tracking name.
In old Git versions, your Git just didn't bother doing this. In Git version 1.8.2, the Git authors finally fixed this: a successful
git push
has your Git update your remote-tracking name, based on the fact that their Git agreed to the update your Git provided. So this sort of thing doesn't happen so much any more.7In the bad old days, they put them straight into their repository. In modern Git, they put them in a quarantine area, and only migrate them into their repository if they actually accept the new commits.
8Of course, places like GitHub also offer features like protected branches, which just say no to every push, for instance. We can also invent fancier scenarios, such as when you have multiple computers and forget that you made and pushed new commits via Computer A, and now try to push from Computer B.
What if you're not the only one doing
git push
Suppose that both Alice and Bob have cloned some GitHub repository. The development in this repository happens on branch
dev
(for develop). So Alice makes her owndev
from herorigin/dev
:Bob, likewise, makes his own
dev
:The GitHub repository
dev
ends atH
too. (They have noorigin/dev
: the GitHub repository does not bother with remote-tracking names.)Alice makes a new commit, which we'll call
I
, and draw like this on Alice's computer:Meanwhile, Bob makes a new commit, which we'll call
J
:Now both Alice and Bob try to
git push origin dev
. One of them gets there first—perhaps Alice:Bob sends commit
J
, which to GitHub, looks like this:If GitHub would do that, this would "lose" Alice's commit
I
, because Git finds commits by starting from the names and working backwards. So they reject the push with the "not a fast forward" complaint.Bob now needs to yank commit
I
from GitHub into Bob's own repository, so that Bob sees:Bob should do this with
git fetch
orgit fetch origin
, perhaps with--prune
(or withfetch.prune
set totrue
). Now when Bob runsgit status
, he will get the "diverged" message.It's now up to Bob, as the loser of the push race, to figure out how to combine his work (commit
J
) with Alice's (commitI
). There are different ways to combine work. The two primary ones aregit merge
andgit rebase
. We won't address who should do what, when, and why here, just the fact that this is another way you might run into "diverged" status when you thought you were strictly ahead of some other Git.就我而言,这是因为我使用
Just 来切换到 master 来提取它的新版本,而不是
第一个命令 将master的头重置为
我用来
解决这个问题的最新提交
In my case it was because I switched to master using
Just to pull the new version of it instead of
The first command resets the head of master to my latest commits
I used
To fix that
我浏览了此页面上的每个解决方案,幸运的是 @anatolii-pazhyn 发表了评论,因为他的解决方案是有效的。不幸的是,我没有足够的声誉来支持他,但我建议首先尝试他的解决方案:
这给了我:
我还建议:
您也可以使用:
祝你好运
I went through every solution on this page, and fortunately @anatolii-pazhyn commented because his solution was the one that worked. Unfortunately I don't have enough reputation to upvote him, but I recommend trying his solution first:
Which gave me:
I also recommend:
You can also use:
Best of luck
我在 Windows 机器上也遇到了同样的问题。当我运行 git pull origin master 命令时,我会收到“ahead of 'origin/master' by X commits”警告。我发现如果我运行 git pull origin 且没有指定分支,那么我将不再收到警告。
I had this same problem on a Windows machine. When I ran a
git pull origin master
command, I would get the "ahead of 'origin/master' by X commits" warning. I found that if I instead rangit pull origin
and did NOT specify the branch, then I would no longer receive the warning.我想重申上面 @Marian Zburlia 提到的内容。它对我有用,并且会向其他人提出同样的建议。
git pull origindevelop
后面应该跟着
$ git pull --rebase
。这将删除最新拉取后
$ git status
上出现的注释。I would like to reiterate the same as mentioned by @Marian Zburlia above. It worked for me and would suggest the same to others.
git pull origin develop
should be followed by
$ git pull --rebase
.This will remove the comments coming up on the
$ git status
after the latest pull.git fetch
将为您解决此问题如果我的理解是正确的,则您的本地(缓存)
origin/master
已过期。此命令将从服务器更新存储库状态。git fetch
will resolve this for youIf my understanding is correct, your local (cached)
origin/master
is out of date. This command will update the repository state from the server.实际上,当我使用 TortiseGIT 进行切换/结帐时,就发生了这种情况。
我的问题是我已经根据另一个本地分支创建了分支。它在
/.git/config
中创建了一个“合并”条目,看起来像这样:每当我切换到“web”分支时,它都会告诉我我在开发之前已经有 100 多个提交。好吧,我不再致力于开发,所以这是真的。我能够简单地删除此条目,它似乎按预期运行。它正确地跟踪远程引用,而不是抱怨落后于开发分支。
正如 Vikram 所说,这个 Stack Overflow 线程是 Google 搜索这个问题时的最高结果,所以我想我应该分享我的情况和解决方案。
I actually had this happening when I was doing a switch/checkout with TortiseGIT.
My problem was that I had created the branch based on another local branch. It created a "merge" entry in
/.git/config
that looked something like this:Where whenever I switched to the "web" branch, it was telling me I was 100+ commits ahead of develop. Well, I was no longer committing to develop so that was true. I was able to simply remove this entry and it seems to be functioning as expected. It is properly tracking with the remote ref instead of complaining about being behind the develop branch.
As Vikram said, this Stack Overflow thread is the top result in Google when searching for this problem so I thought I'd share my situation and solution.
我的经验是在一个有很多分支机构的团队环境中。我们在自己的功能分支(在本地克隆中)中工作,这是
git status
显示我领先 11 次提交的分支之一。我的工作假设,就像问题的作者一样,+11 来自我自己的提交。事实证明,我在几周前就已经将公共
develop
分支的更改拉入了我的功能分支 - 但忘记了!当我今天重新访问本地功能分支并进行git pull origindevelopment
时,提交数量跃升至 +41。在develop
中已经完成了很多工作,因此我的本地功能分支甚至比origin
存储库上的功能分支还要领先。因此,如果您收到此消息,请回想一下您可能从您有权访问的其他分支(您自己的或其他人的)进行的任何拉取/合并。该消息只是表明您需要将这些
pull
更改从本地存储库git Push
返回到origin
存储库(“跟踪分支”)让事情同步。My experience is in a team environment with many branches. We work in our own feature branches (in local clones) and it was one of those that
git status
showed I was 11 commits ahead. My working assumption, like the question's author, was that +11 was from commits of my own.It turned out that I had pulled in changes from the common
develop
branch into my feature branch many weeks earlier -- but forgot! When I revisited my local feature branch today and did agit pull origin develop
the number jumped to +41 commits ahead. Much work had been done indevelop
and so my local feature branch was even further ahead of the feature branch on theorigin
repository.So, if you get this message, think back to any pulls/merges you might have done from other branches (of your own, or others) you have access to. The message just signals you need to
git push
thosepull
ed changes back to theorigin
repo ('tracking branch') from your local repo to get things sync'd up.我收到以下与实际问题相关的信息
Yourbranch is advance of 'origin/testing/KB-200' by 17 commits
原因:我创建了 PR 供审核上周,然后我关闭了该项目。然后今天,我打开了项目,在同一个分支
(testing/KB-200)
中进行了轻微的更改,然后我首先运行了git pull
。这次拉取包含了从事该项目的其他开发人员的 18 个新提交,这使得我的本地分支在这些提交方面领先于我的远程分支,因此我收到了该消息。所以我只需要运行以下命令:然后一切都是同步的并且是最新的。
[在分支测试/KB-200上,您的分支已更新为“origin/testing/KB-200”]
I was getting the following which is related to the actual question
Your branch is ahead of 'origin/testing/KB-200' by 17 commits
Reason: I created PR for review the last week and then I closed the project. Then today, I opened up the project to make a slight change in the same branch
(testing/KB-200)
and I rangit pull
first. This pull contained 18 new commits by other developers working on the project this made my local branch ahead of my remote branch by those commits and therefore I was getting that message. So I just had to run the following command:and then it was all sync and up to date.
[On branch testing/KB-200 Your branch is up to date with 'origin/testing/KB-200']
它只是提醒您当前分支和执行当前轨道的分支之间的差异。请提供更多信息,包括消息中打印的分支以及您在哪里推/拉当前分支。
It just reminds you the differences between the current branch and the branch which does the current track. Please provide more info, including what branch is printed in the message and where do you push/pull the current branch.
建议/< 之间存在差异时,会生成该消息/code>(例如
git pull
或git fetch
的答案是正确的。当 git status 发现 .git/FETCH_HEAD 和 .git/refs/remotes/
.git/refs/remotes/origin/master
)。后一个文件记录了上次获取的 HEAD(对于存储库/分支)。执行
git fetch
会将两个文件更新到分支的当前 HEAD。当然,如果没有任何内容可获取(因为本地存储库已经是最新的),则
.git/FETCH_HEAD
不会更改。The answers that suggest
git pull
orgit fetch
are correct.The message is generated when
git status
sees a difference between.git/FETCH_HEAD
and.git/refs/remotes/<repository>/<branch>
(e.g..git/refs/remotes/origin/master
).The latter file records the HEAD from the last fetch (for the repository/branch). Doing
git fetch
updates both files to the branch's current HEAD.Of course if there is nothing to fetch (because the local repository is already up-to-date) then
.git/FETCH_HEAD
doesn't change.虽然这个问题有点老了......我遇到了类似的情况,我在这里的回答帮助我解决了类似的问题,我
首先尝试使用
push -f
或强制选项如果这不起作用可能(就像我的情况一样)远程存储库(或者更确切地说,对 git remote -v 上显示的远程存储库的引用)可能没有更新。
上述结果是您的推送将您的本地/分支与远程/分支同步,但是,本地存储库中的缓存仍然显示先前的提交(本地/分支...假设仅推送了单个提交)作为 HEAD。
要确认上述情况,请在不同位置克隆存储库,并尝试比较本地/分支 HEAD 和远程/分支 HEAD。如果它们相同,那么您可能面临我遇到的问题。
解决方案:
现在执行
push -f
如下git push -f github master
### 请注意,您的命令没有origin< /code> 不再了!
立即
执行
git pull
git pull github master
在
git status
上接收# On Branch master
无需提交(工作目录干净)
我希望这对某人很有用,因为视图数量如此之高,以至于搜索此错误几乎总是在顶部列出此线程
另请参阅 gitref 了解详情
Though this question is a bit old...I was in a similar situation and my answer here helped me fix a similar issue I had
First try with
push -f
or force optionIf that did not work it is possible that (as in my case) the remote repositories (or rather the references to remote repositories that show up on
git remote -v
) might not be getting updated.Outcome of above being your push synced your local/branch with your remote/branch however, the cache in your local repo still shows previous commit (of local/branch ...provided only single commit was pushed) as HEAD.
To confirm the above clone the repo at a different location and try to compare local/branch HEAD and remote/branch HEAD. If they both are same then you are probably facing the issue I did.
Solution:
Now do a
push -f
as followsgit push -f github master
### Note your command does not haveorigin
anymore!Do a
git pull
nowgit pull github master
on
git status
receive# On branch master
nothing to commit (working directory clean)
I hope this useful for someone as the number of views is so high that searching for this error almost always lists this thread on the top
Also refer gitref for details
如果您在提交后收到此消息,为了取消跟踪分支中的文件,请尝试在任何文件中进行一些更改并执行提交。显然,您无法进行单次提交,其中仅包括取消跟踪以前跟踪的文件。
最后这篇文章帮助我解决了整个问题 https:// /help.github.com/articles/removing-files-from-a-repository-s-history/。我只需从存储库历史记录中删除文件。
If you get this message after doing a commit, in order to untrack file in the branch, try making some change in any file and perform commit. Apparently you can't make single commit which includes only untracking previously tracked file.
Finally this post helped me solve whole problem https://help.github.com/articles/removing-files-from-a-repository-s-history/. I just had to remove file from repository history.
只是分享发生在我身上的事情。
我提交了一堆文件,并意识到有些文件我不想提交,所以我使用 VS code 来
撤消上次提交
,删除文件并添加到 gitignore,然后强制推送我的提交再次。这显然导致 git 认为我的提交仍然必须进行到远程,因为文件是在本地以某种方式提交的。
通过
撤消上次提交
并取消暂存现在位于 gitignore 中的文件来解决Just sharing what happened to me.
I committed a bunch of files and realized there are some files that I dont want to commit, so I used VS code to
undo last commit
, removed the file and added to gitignore, then force-pushed my commit again.This apparently caused git to think my commit still has to be made to remote, because locally the file was committed somehow.
Solved by
undo last commit
and unstaging the file which is in gitignore now