推送到 git 时出现非快进错误

2024-02-13

我得到了一个non-fast-forward尝试推送到 WordPress git 存储库时出错,但像错误消息所说的那样拉动会给我一条消息,表明一切都是最新的。这是在拉取、合并和提交之后。这是我的日志:http://pastebin.com/6M4qLqjG http://pastebin.com/6M4qLqjG

简而言之,我尝试推动:

ajh$ git push staging master

我收到此错误,告诉我先拉:

To [email protected] /cdn-cgi/l/email-protection:staging/gordo.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to '[email protected] /cdn-cgi/l/email-protection:staging/gordo.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

但如果我尝试拉取,它会说它是最新的:

ajh$ git pull staging master
From git.wpengine.com:staging/gordo
 * branch            master     -> FETCH_HEAD
Already up-to-date.

而且会循环,不知道是怎么回事。有什么想法可以让我的仓库和本地保持一致吗?我从没见过这个non-fast-forward之前的错误,不知道该怎么做。它还告诉我检查 master,但我只是拉取并与 master 合并,所以我认为我不应该再尝试一次。

=========编辑修复============ 这是一个粘贴箱,其中包含我用来正确推送内容的终端命令。不过,我仍然可以对到底发生了什么进行解释。我可以重复这些步骤,但我不太明白为什么它们有效,而常规的推/拉却不起作用。

http://pastebin.com/u9DAiU5P http://pastebin.com/u9DAiU5P

基本上我创建了一个新分支,从 master 签出,它快进了我。发生了一些奇怪的事情,我必须推动去做git push staging staging,这个分支很混乱


我查看了你的第二个 Pastebin 链接,发现有很多混乱(这并不奇怪,因为 git 的术语似乎是故意混淆的ing).

我认为最好的办法是先退后一步,看看 git 术语,并使用 Pastebin 中的一些示例。

我们先从“远程”开始。

什么是遥控器?

A remote只是一个名字,比如origin or staging or upstream,它为 git (和您)提供了对应 git 存储库的完整 URL 的短名称。但是 git 利用这个短名称为您提供“远程跟踪分支”,我们还无法描述它。首先我们需要谈谈“分支”。

什么是分支机构?

这是来自pastebin的一些内容:

1.      The-Dorfchester:gordo.dev ajh$ git checkout -b trouble
2.      M       .idea/workspace.xml
3.      M       wp-content/themes/goTheme2015/blog-loadMore.php
4.      M       wp-content/themes/goTheme2015/home.php
5.      M       wp-content/themes/goTheme2015/stylesheets/layout.css
6.      M       wp-content/themes/goTheme2015/stylesheets/layout.scss
7.      Switched to a new branch 'trouble'
8.      The-Dorfchester:gordo.dev ajh$ git push trouble
9.      warning: push.default is unset; ...

在第 1 行,您创建了一个新的分支名称,trouble.

In git, the word "branch" has at least two distinct meanings.1 There are branch names, like trouble, and then there are sequences in the graph of commits stored in the repository, which form actual branches. To distinguish these from branch names, let's call them "commit graph fragments". Since these are unwieldy terms, let's note that the commit graph is, technically speaking, a Directed Acyclic Graph or "DAG". A piece of this graph is therefore a "DAGlet".2

DAGlet 很重要,因为来自 git 的抱怨:

 ! [rejected]        master -> master (non-fast-forward)

当您要求 git 进行推送时,会发生这种情况,该推送将“忘记”DAG 的一部分,即“丢失 DAGlet”。我们稍后再讨论这个问题。

分支和提交

我假设您对“提交”有一个合理的概念,在 git 中,它保存您工作的完整快照 - 更准确地说,是“索引”或“暂存区域”中的任何内容的副本 - 以及提交消息、您的姓名和电子邮件以及提交的时间。不过,他们还有一件非常重要的事情,我们将在下一节中介绍。

现在让我们看一下第 2-7 行。当你这样做时git checkout -b trouble,git 指出它保留了一堆已修改但未提交的文件作为已修改但未提交的文件。

我知道你正在尝试做一个git push, and git push pushes commits,而不是文件。因此,如果您修改了但未提交的文件,这些未提交的更改cannot被推。

(你没有显示git status在那里,但是git status确实是查看已修改和未提交文件的情况的最佳命令。它告诉你你现在在哪个分支(这将是trouble在这里,如果您的分支正在“跟踪”另一个分支,则您的分支领先和/或落后多远。你的git checkout -b有效地运行git status但对我们来说。)

这意味着在某些时候,您可能应该运行git commit进行新的提交。当你do进行新的提交,它会去哪里?

提交添加到分支

每当你进行新的提交时,你的新提交都会有上面的“一件事”:它有一个家长 ID。对于大多数新提交,父 ID 是“当前提交”。这会将新的提交链接回之前的提交,我们可以将其绘制为一个小箭头:

A <- B <- C <- D

在这里,我们从最近(和当前)的提交开始,我称之为D. D存储其父提交的 IDC; C存储其父级的 IDB; and B存储其父级的 IDA.

我们刚刚绘制了一个 DAGlet:我们选择一个起始提交(在本例中,D),并且该提交为我们提供了一系列较旧的提交。如果我们进行新的提交——我们称其为E——它将指向D:

A <- B <- C <- D <- E

我们有一个更长的 DAGlet。

分支名称从何而来?

分店name让我们找到一个特定的提交。这几乎就是分支名称的全部内容:它是指向提交的指针。如果您在分行master当你做出一个新的提交时,git 首先找到当前的提交——它有一个又大又丑的 40 个字符的 SHA-1“真实姓名”,有时你会看到这个的缩写版本,比如b66c9f0— 并从暂存区域、您的姓名和电子邮件、您的提交消息以及此父 ID 进行新提交。然后——这是棘手的部分——git 写了new将 SHA-1 提交到分支名称中。

这样,枝条本身就长大了,枝条也生长了。name指向分支末尾的新“提示提交”。如果它过去结束于D,你现在有D <- E与名字master指向E代替D。犯罪E现在是“tip-most”,并且您的分支(名称)指向E,整个链条开始于E形成分支(DAGlet)。这是之前和之后:

[before]
A <- B <- C <- D   <-- master

[after]
A <- B <- C <- D <- E   <-- master

为什么这一切都很重要?

当你去git push一些提交,你让你的 git 将提交交给另一个 git(监听远程存储的 URL 的 git),然后要求该 git 设置its分支到您正在推送的最尖端的提交。

不过,假设您要求 git 推送您的master(犯罪E)到他们身边并让他们master指向E也。但是——无论出于什么原因——他们的master现在存在,但指向不同的提交:

A <- B <- C <- D <- F   <-- master (in their repo)
                 \
                   E   <-- (your proposed replacement)

如果有礼物套装master在他们的仓库中指向提交E,您将让他们使用您拥有的相同 DAGlet:E指向D, 指向C, 等等。犯罪F——他们拥有而你没有的承诺——将会丢失。

这是什么non-fast-forward means.这意味着他们的分支名称指向您的提交don't包含在您要推送的任何 DAGlet 中。该承诺指向一些父母,又指向更多父母,依此类推。最终(甚至是立即)这些历史提交会合并在一起,但至少有一个提交是他们拥有而您没有的,如果他们将分支名称指向您的 DAGlet(其副本),那么这些提交就会丢失。

迄今为止的回顾:

  • git push:这需要一个遥控器,即一个短名称,例如origin or staging提供用于推送的 URL。这是后面的第一个词push. Any 额外的单词是“refspecs”,我们还没有定义,但现在我们只说它们是由分支名称组成的(这基本上是正确的)。你给 git 一个分支名称,例如master or trouble它尝试使用远程上的另一个分支名称将您在该名称下的提交推送到远程。 (Which远程分支名称?好吧,我们稍后会看到其他内容。)

  • 您推送的 DAGlet 应该简单地extend他们的分支,向其添加新的提交。从技术上讲,您要求他们将分支设置为的提交应该是他们已经拥有的提示提交(这是“无实际推送”的情况),或者最终应该指向该提交。您可以添加一个或多个提交,但在序列中的某个位置,您的新提交之一必须指向其现有的提示提交。

  • 或者,您可以推送他们根本没有的分支名称。如果您在远程创建该名称,则不会丢失任何提交。

侧边栏:push.default

让我们考虑第 9 行,warning: push.default is unset。该警告一直运行到第 28 行。每次运行时都会出现该警告git push使用遥控器,但没有额外的 refspec 参数。为了让 git 关闭,我建议设置push.default, 到任一simple or upstream.

您可以对每个存储库执行一次此操作,或者在您的个人全局配置中进行设置(通常在其中设置用户名和电子邮件):

$ git config --global push.default simple

例如。

如果你使用simple,git 将推送您当前的分支(例如,trouble) 到远程,要求远程更新its trouble。也就是说,这些推送按分支工作names and simple要求这里的两个不同的 git(你的,在你的系统上,他们的,在远程系统上)使用相同的分支名称。

这回答了“你的 git 要求他们的 git 更新哪个分支名称”的问题:如果你正在推送分支trouble,你的 git 会要求他们的 git 更新他们名为trouble。如果你的 git 正在推动你master,它会要求他们的 git 更新他们的master。如果您没有命名分支,您将推送的分支就是您当前的分支,并且没有诸如在其中创建分支之类的棘手问题your拼写的存储库Raymond-Luxury-Yacht,但在遥控器上拼写为 Throatwobbler-Mangrove http://www.imdb.com/character/ch0027524/.

这非常简单,这就是为什么它被称为simple。还有其他四个选项,但我将在本文中将其保留。

这里出了什么问题?

考虑第 35-37 行:

35.     The-Dorfchester:gordo.dev ajh$ git push trouble trouble
36.     fatal: 'trouble' does not appear to be a git repository
37.     fatal: Could not read from remote repository.

The git push命令将远程作为其后的第一个单词push。这个单词trouble,被视为遥控器,不起作用(您没有名为trouble). The push代码充满了历史包袱,因此它尝试使用trouble之后作为 URL,但这也不起作用。

(我要跳过git show-branch输出因为某些东西损坏了它,删除了前导空白,使其难以阅读。)

git checkout,以及这里出了什么问题

Git's checkout命令(在我看来)不必要地复杂,因为它有太多的操作模式。如果 git 使用单独的命令来“切换到不同的分支”与“从某个分支中检查特定文件,而不更改当前分支”,那就不会那么混乱了。但这些都归结为一git checkout命令,让我们看一下第 75-79 行:

75.     The-Dorfchester:gordo.dev ajh$ git checkout staging master
76.     error: pathspec 'staging' did not match any file(s) known to git.
77.     error: pathspec 'master' did not match any file(s) known to git.
78.     The-Dorfchester:gordo.dev ajh$ git checkout staging
79.     error: pathspec 'staging' did not match any file(s) known to git.

更常见的结账形式是git checkout branch-name,但在这种情况下,您调用的是不同的git checkout,即git checkout [ branch-name ] [ -- ] path1 path2 ... pathN,但你可以省略--。自从staging不是有效的分支名称,它被解释为path反而。 (这并不重要master is有效的分支名称,因为staging处于唯一的论证位置git checkout允许使用分支名称。)

在第 80 行,你得到了一个不同的错误:

80.     The-Dorfchester:gordo.dev ajh$ git checkout master
81.     error: Your local changes to the following files would be overwritten by checkout:
82.             .idea/workspace.xml
83.             wp-content/themes/goTheme2015/blog-loadMore.php
84.             wp-content/themes/goTheme2015/home.php
85.             wp-content/themes/goTheme2015/stylesheets/layout.css
86.             wp-content/themes/goTheme2015/stylesheets/layout.scss
87.     Please, commit your changes or stash them before you can switch branches.

您目前(仍在)在分支上trouble并且你要求 git 移动到分支master。要从一个分支移动到另一个分支,git 必须替换工作树中某些文件的内容。哪些文件?

答案有点复杂,但在这种情况下,(至少)某些文件会出现错误,例如.idea/workspace.xml(1) 存储在最近的提交中current分支; (2) 位于new分支的提示也提交; (3) 该文件的内容new分支是不同的来自当前提交中该文件的内容。

如果工作树中的文件与当前提交中的文件匹配,git 会放心地擦除工作树版本并将其替换为切换到分支(master,在本例中)提示提交版本。但是你的工作树中的这些文件don't匹配当前提交。我们在原著中看到了git checkout -b当它运行时git status.

因此,git 拒绝更改分支,要求您提交更改的文件,或者使用git stash提交它们(区别在于git stash承诺他们no分支,而不是当前分支)。

好的,所以你终于提交了它们

现在我们进入第 89-91 行:

89.     The-Dorfchester:gordo.dev ajh$ git commit -am "idk"
90.     [trouble 820decb] idk
91.      5 files changed, 39 insertions(+), 93 deletions(-)

这在当前分支上进行了新的提交trouble。然后,它移动分支以指向新提交,其 40 个字符的 SHA-1 开头为820decb.

现在我们到达第 92 行:

92.     The-Dorfchester:gordo.dev ajh$ git push master

这要求你的 git 推送到名为master。没有,并且您会得到与之前相同的错误。所有这些也吐出了巨大的烦人的“设置你的push.default" 消息,这让我们到达第 119 行,以及第 125 行:

119.    The-Dorfchester:gordo.dev ajh$ git pull master
...
125.    The-Dorfchester:gordo.dev ajh$ git push --set-upstream master trouble

这两个都有和以前一样的问题:这个词master位于远程名称的插槽中,但不是有效的远程。

这将我们带到第 131 行:

131.    The-Dorfchester:gordo.dev ajh$ git push --set-upstream staging trouble

终于有一个 git 喜欢的命令了! :-) 这次staging位于遥控器插槽中,并且trouble位于“refspec”的位置,并且这两者都有效。 (这--set-upstream tells git push一旦推送成功,它应该记录staging's trouble作为您当地的“上游分支”staging。有关这一切含义的更多信息,请参阅这个答案 https://stackoverflow.com/a/33509159/1256452.)

让我们跳过一个错误的检查并继续执行第 154 行(及其随之而来的成功消息):

154.    The-Dorfchester:gordo.dev ajh$ git checkout master
155.    Switched to branch 'master'
156.    Your branch is behind 'staging/master' by 16 commits, and can be fast-forwarded.
157.      (use "git pull" to update your local branch)

这个有效。并不是因为成功git push不过:这次成功了,因为你终于承诺了trouble分支。这使得修改后的文件安全地存储在存储库中,因为新提交的 40 个字符的“真实名称”SHA-1 ID 开头为820decb.

一旦它们被提交,那么你的工作树是干净的,git 就可以了git checkout master。你也推了你的trouble到名为“staging”的遥控器,为其命名trouble也有,但这对于git checkout master step.

第 155 行确认成功。第 156 行是以下输出git status,告诉你你的master位于其上游(你的 git 称之为staging/master)比其上游提交了 16 次(他们有 16 次提交是您没有的),并且并不“领先”其上游。再次,请参阅我的其他答案(上面已链接)以了解更多信息。

然后你跑了git pull,这实际上只是git fetch其次是git merge(它的目的是作为这两个步骤的方便包装,但事实证明第二个是wrong对于大多数人来说,这是一个步骤,所以它是可配置的)。这git merge进行了“快进”合并,这意味着您没有新的提交,而他们有新的提交,因此您的 git 能够“将分支向前滑动”到新的分支提示,将他们的新 DAGlet 添加到您现有的 DAG没有任何大惊小怪。

这让我们一直到第 388 行(及其响应行):

388.    The-Dorfchester:gordo.dev ajh$ git commit -am "pull from staging/master to master, idk"
389.    On branch master
390.    Your branch is up-to-date with 'staging/master'.
391.    nothing to commit, working directory clean

This git commit命令发现没有任何可提交的内容,并且没有进行任何新的提交。你的分行master没有添加新的提交,并且分支提示与以前相同。

392.    The-Dorfchester:gordo.dev ajh$ git push master

这与之前的错误相同:git push首先想要一个遥控器的名称。喷出的大水大约push.default让我们一路:

419.    The-Dorfchester:gordo.dev ajh$ git push staging master

这是正确的,但我们刚刚看到您的git commit早些时候没有添加新的提交。所以你的 git 会调用 gitstaging并发现没有什么可做的:

420.    Everything up-to-date

它什么也没做(并且成功了)。

(顺便说一下,关于push.default此处省略,因为您给出了git push both一个遥控器and参考规格。这push.default设置是推送应该做的,如果你don't给出一个参考规范,即,如果你只给它一个遥控器,或者什么都不给它。如果你给git push什么都没有,它会根据当前分支的上游设置确定要使用的遥控器。)


1How many meanings depends on how you count some finer divisions. See this question https://stackoverflow.com/q/25068543/1256452 for more.

2Be aware that DAGlet is my own invention, so if you start using it, you may have to define it for your audience.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

推送到 git 时出现非快进错误 的相关文章

随机推荐

  • 配置 AspNetCore TestServer 返回 500 而不是抛出异常

    我正在开发一个 Web API 在某些情况下会响应 500 我知道设计很丑 但对此无能为力 在测试中 有一个包含 AspNetCore TestHost 的 ApiFixture public class ApiFixture public
  • 如何在我的机器上获取特定的拉取请求? [复制]

    这个问题在这里已经有答案了 有人向我发送了拉取请求 在合并之前 我想看看我的机器上的变化 我怎么做 From http community elgg org pages view 1123557 how to check out a pul
  • java.security.NoSuchAlgorithmException:RSA 签名不可用

    这是例外 Exception in thread main java security NoSuchAlgorithmException RSA Signature not available at java security Signat
  • 奇怪的回声输出

    谁能解释一下 bash shell 的这种行为 它让我发疯 root ns1 bin export test whois h whois lacnic net 187 14 6 108 grep i inetnum awk print 2
  • 共享环境中 IIS7 中应用程序池回收的最佳设置是什么?

    共享环境中 IIS7 中应用程序池回收的最佳设置是什么 作为托管者 您肯定希望回收内存和时间 潜在的请求限制和 CPU 您希望对这些限制采取非常积极的态度 但请确保将它们发布给您的客户 Memory https technet micros
  • UWP WinUI TreeView 以编程方式滚动到项目

    我正在尝试使用新的WinUI工具包TreeView控制 我需要以编程方式滚动到特定项目 我找不到办法做到这一点 目前 没有这样的APITreeView用于滚动到视图中的类 但你可以获得TreeViewList在树视图中ControlTemp
  • 从 Spring 控制器中删除重复项

    我一直在寻找一种方法来减少 Spring MVC 控制器中因细微差异而重复的代码量 但到目前为止搜索 SO 问题只产生了一些问题 没有任何令人满意的答案 我想要删除的重复示例是这样的 其中用户创建页面和角色创建页面有相似之处 Request
  • 如何将自定义类型调用函数泛化为抽象类型?

    我有以下模拟设置 其中包含抽象类型 具体类型作为子类型和函数f它需要两个参数 第一个是Letter abstract type Letter end struct A lt Letter end struct B lt Letter end
  • 使用子记录数据更新父记录的字段(同一表)

    我有一张表 其中存在父 子关系 其中每个孩子的ExternalCategoryCode列数据需要连接到父级中ExternalCategoryCode 以下是一些已损坏的示例数据 其中父记录 Id 96 ExternalCategoryCod
  • 将completionSelector 和completionTarget 与UIImageWriteToSavedPhotosAlbum 结合使用

    我正在尝试找出一种方法让我的 iOS 应用程序将屏幕截图保存到相机胶卷 然后弹出警报告诉用户屏幕截图已成功保存 我能想到的唯一方法是使用某种形式的 if else 循环 正如您将在下面的伪代码注释中看到的那样 但我想不出任何语法来使用UII
  • Android 需要深厚的 Java 知识吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 以对数刻度间距绘制 x 轴,但不以指数形式标记它

    我想绘制两个值x 0 10 20 50 100 and y 1 2 3 10 100 使用pylab 我想将 x 轴的间距保持为对数形式 但我想在 x i e 的值 10 20 50 100 处勾选并打印它们 因为它不是 10e1 或 10
  • 我如何知道哪一行代码导致我的 iOS 应用程序在 Xcode 9 中崩溃

    I am building an app in Xcode 9 Swift 4 and it crashes before it even loads completely I get an error Thread 1 Signal SI
  • NUnit 测试项目无法加载 System.Windows.Forms 的程序集

    我有一个专门用于单元测试的 NUnit 测试项目 其目标框架为 Net Core 2 1 该测试项目引用了另外两个项目 其中一个是窗口窗体基于应用程序 另一个是类库基于数据库交互的应用程序 这两个项目的目标框架都是 Net Framewor
  • 获取包含的库的版本信息?

    我创建了 2 个项目 其中 1 个是 Lib 第 2 个是 Test 我从测试应用程序将上下文传递给 Lib 项目 由于我在 Lib 中有上下文 因此我在 Lib 中使用了以下代码 字符串版本 this mContext getPackag
  • 随机数生成器:它应该用作单例吗?

    我在几个地方使用随机数 并且通常在需要时构建一个随机数生成器 目前 我使用 Marsaglia Xorshift 算法将当前系统时间作为种子 现在我对这个策略有一些疑问 如果我使用多个生成器 生成器之间的数字的独立性 随机性 取决于种子 相
  • 如何使用 Google Translator Api 将转换后的英文文本设置到另一个文本框?

    我有两个文本框 一个用于英语 另一个用于印地语 当我在第一个框中输入英语时 文本应在第二个框中显示为印地语版本 在按键事件上 我已经提到了一个例子如何在您的网站中通过 Google API 将英语翻译成印地语 http arunsonare
  • 单选按钮检查事件处理

    在我的应用程序中 我需要一个单选组 每当选中单选按钮时 就会出现警报 以便我可以使用 jQuery 将其值发布到 ajax post 你能帮我看看我如何在 jQuery 中做到这一点吗 尝试这样的事情 function input type
  • 使用自签名证书是否可以防止中间人攻击?

    我不确定以前是否有人问过类似的问题 我找不到任何问题 但是是否可以保护客户端 服务器免受中间人攻击 我正在编写一个客户端应用程序来与服务器进行通信 通信将基于 SSLv3 我对服务器的自签名证书没问题 但担心其他人以相同的服务器名称生成相同
  • 推送到 git 时出现非快进错误

    我得到了一个non fast forward尝试推送到 WordPress git 存储库时出错 但像错误消息所说的那样拉动会给我一条消息 表明一切都是最新的 这是在拉取 合并和提交之后 这是我的日志 http pastebin com 6