繁体   English   中英

在仓库更新过程中如何解释git错误?

[英]How to interpret git error during repo update?

我正在尝试更新我的Github存储库。

操作系统/配置 :在MacBook Air上使用OS X 10.10.5(Yosemite)

完成以下命令后:

$ git init
$ git add
$ git commit -m "added new stuff"
$ git remote add origin https://github.com/user/repo.git
$ git push -u origin master

我收到此错误:

To https://github.com/user/repo.git>
! [rejected]        master -> master (fetch first)
error: failed to push some refs to
'https://github.com/user/repo.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first 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.

然后我尝试了...

$ git pull --commit https://github.com/user/repo.git

我知道了

Merge https://github.com/user/repo
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

这些错误在英语中是什么意思? 接下来我该怎么办?

有没有一种方法可以仅“转储”队列中的所有内容(而无需尝试“拉出”),这样我就可以继续进行新的提交了? 我对下一步该怎么办感到很困惑。

首先,让我建议您阅读Pro Git书 ,因为git随附的大多数文档都非常糟糕,尤其是对于新手。 (与5年前相比有所改进,但仍然有很多不足之处。)

就是说,让我在这里尝试快速介绍“您需要知道的内容”。

介绍性的东西

  1. 当与其他人一起工作时(包括在这里被称为“其他人”的github),您的git会通过互联网电话调出他们的git并进行工作。 这些其他人都是同龄人 ,也就是说,他们具有与您所做的新工作完全相同的能力,至少在一般情况下(github本身不会独自完成新工作)。 这意味着在交换期间,您可能拥有“他们”(无论他们是什么)所没有的东西,但是他们也可能拥有您所没有的东西。
  2. Git与单个提交交换工作。 1确切地说,哪个提交以及如何提交变得更加复杂,所以让我们暂缓一下。
  3. git push的反义不是git pull ,实际上是git fetch 我认为您收到的错误消息不应直接引用git pull ; 我们也会对此进行详细介绍。
  4. Git通过其“真实名称” SHA-1 ID来在内部跟踪提交,例如,这是您在git log输出中看到的长40个字符的十六进制内容。 每个提交都有一组由SHA-1 ID标识的“父”提交。 您可以自己使用SHA-1 ID,但是它们对人类非常不友好,您永远不会记住应该以f13c9ab还是0e1d227或其他任何f13c9ab 0e1d227 (这些都是缩写 ID!)。
  5. 因此,git因此为用户提供了分支名称,例如master 分支名称只是您告诉git用来跟踪在该分支上所做的最新提交的名称。
  6. 最新的提交具有作为其父级的“过去是最新的”提交,其父级具有甚至更老的“最新”的提交,依此类推。 (git实现此目的的方法非常简单:当您进行新的提交时,其父节点为“当前提交”,并且一旦将提交安全地存储在存储库中,git就会用的ID替换分支中存储的ID。新的提交。)

给定最后三项,让我们绘制一个提交图片段:

... <- 1f3a33c <- 98ab102   <-- branch

在这里,分支的尖端是commit 98ab102 ,其父节点是1f3a33c 我们可以说名称branch “指向” 98ab102 ,它指向其父级,依此类推。

当您创建一个新的存储库( git init ,假设实际上是2 )时,它完全没有提交,因此第一个提交没有父级。 它是第二个和第三个提交,以此类推,它指向以前的提交。

当您进行“合并”时,您告诉git接受两个(或三个,但现在仅说两个)现有的提交,并通过合并来自某些提交的所有更改来进行一个新的提交,将两者作为父提交共同点。 合并不是那么复杂,但是您通常应该在故意将工作划分为不同的开发线之后进行合并。

现在,返回以获取,推动和拉动

您已经创建了一个新的存储库( git init ),至少放入了一个提交( git commit ),并添加了一个“远程”( git remote add origin ... )。 最后一步说:“我有一个对等git,我想称其为origin ,所以请记住该名称下的URL。”

然后,您要求您的git调用“ origin”( git push ... origin ),并根据您的分支名称“ master”( git push ... master )找到您提交的提交。 这是有点棘手的地方。 当你的git的会谈,他混帐,应他的混帐使用什么名字? 简短的答案是, 他的 git也将使用master名称。 这是可变的,但是更改不是您想要的。

(您还通过-u标志要求让git在您的git配置中记录此交换。我们暂时将其保留。)

当您的git调用自己的git时,您的git会说“在这里,查看这些闪亮的新提交”(然后他做了),然后您的git说道:“为什么不将这些新提交完全按原样添加到您的存储库中, 4和使您的master指向这些承诺中最重要的一个?” 他的回答是:“嗯,我做到这一点,但我会失去一些提交没有。” 在这里您可以看到被rejected消息。

也许您希望他们到目前为止忘记他们的东西。 如果是这样,您可以要求“强制推送”,即使您的git“丢失”了某些提交,您也可以让他们的git告诉他们设置master 是否执行此操作仍由他们决定,但通常不是您想要的。

也许您想拿起他们拥有的东西并将其添加到您的收藏夹中,或者拿起他们拥有的东西并抛弃自己的工作。 这是您要git fetch

什么git fetch呢,去复杂尽可能,5是调用通过互联网,手机同行,并找出他们有什么, 不知道。 它带来了所有这些提交(记住,交换是通过提交进行的),并将它们(类似于Borg)添加到您的存储库中。 然后,这是至关重要的部分,它将更改分支名称,以便它们不会干扰您的分支名称。

git fetch用于与您的同级同步的名称称为“远程跟踪分支”,有时也称为“远程分支”。 关于“远程分支机构”的一件奇怪的事是它们实际上不在远程! 它们保存在您自己的存储库中。 原因很简单:它们是git上次与该远程通话时的远程快照。 在两个git挂断Internet电话后,可以更改遥控器。 (当然,远程实际更改的速度取决于远程git的繁忙程度。)

此处的重命名模式很简单:以遥控器的分支名称(如master )并在前面添加遥控器的名称( origin ):您的origin/master “跟踪” originmaster (有一种全名表格,如果您意外地命名了自己的纯本地,非远程跟踪分支或origin/oops分支的话,则可以使用,但最好的选择是一开始就不要这样做。 )

等一下, git pull从哪里来?

注意,到目前为止,都是git pushgit fetch 但是,假设您已经完成了git fetch并完成了他们的工作? 现在你有一个有点问题:你有你的工作,你有自己的工作,而这两个有分歧。

如果你们都是从一个共同的基础开始,我们可以这样绘制您的提交图:

... base <- yours   <-- HEAD -> master
         \
           theirs   <-- origin/master

这次我放入HEAD ->以显示您所在的分支(运行git status ,您应该在其输出中看到“ on branch master”)。

将这两个不同的工作联系在一起的一种简单方法是使用git merge 如果你想这样做,你只要运行git merge origin/master (注意斜线:你希望你的git找到你的 origin/master ,它在拿起git fetch和合并到这一点你的master ,使一个新的提交在您的master )。 结果看起来像这样:

... base <- yours <- merge  <-- HEAD -> master
         \         /
           theirs      <-- origin/master

处理此问题的另一种方法(实际上通常是更好的方法)是使用git rebase ,我在这里不做详细介绍。 关于使用rebase ,有很多StackOverflow答案。 但是,如果这样做,您将获得:

... base <- theirs <- yours   <-- HEAD -> master
                  \
                   .......... <-- origin/master

(请注意,在所有情况下, origin/master仍然指向最尖端的“其”提交。)

现在要牢记的主要一点是,无论您做什么,如果想让他们的git接受您的提交而不必强行按下,则需要使您的工作成为他们的附加内容,以便您新的提交“指向”他们的。 push过程并不重要,您的工作是将其作为合并提交的“第二父级”,还是直接在其提交上进行构建; 它只需要通过提交ID指向其提交即可。 (但同样,重新设置通常比合并好!)

所以, git pull (finally!)...

简化的git pull所做的只是运行git fetch然后git merge 简而言之,它是一个方便脚本:您总是先获取然后合并,因此我们将为您提供一个先获取然后合并的脚本。

当然, git merge通常是错误的。 默认情况下,它确实应该使用git rebase

您可以使 git pull使用git rebase 6,但是我认为至少(或者特别是对新手)使用两个单独的步骤是明智的,部分原因是如果出现问题,从中恢复的方式会有所不同两种不同的动作。 要摆脱失败的合并,请使用git merge --abort 要摆脱失败的rebase,可以使用git rebase --abort (这些曾经更加不同,现在只是“中止一切失败”,这是一个很大的改进。但是您需要知道该怎么做,如果您从git mergegit rebase开始,这将变得非常清楚。)

底线

最后,您需要在此处执行的操作取决于您要执行的操作以及遥控器允许您执行的操作。 如果您想放下它们的东西,请使用git push -f (强制),要知道您正在以这种方式使他们(无论他们为谁)感到痛苦,并且他们可能会完全禁止这样做。 如果要保留它们的内容,请先使用git fetch ,然后按自己的意愿保留它们的内容(合并,变基,重做等)。


1或带有补丁,您可以通过电子邮件与同行交换。 也可以“捆绑”提交并通过其他方法转移它们。 但是在这种情况下,我们正在通过Internet电话进行基于提交的交换。

2您可以在现有存储库中安全地运行git init 它的作用很小,但就我们的目的而言,它基本上什么也没做,因此需要说“假设它确实能做到”。

3 Git将此称为“章鱼”合并,即使只有3个或4个父级而不是8个。

4 Git通常只会添加“更多内容”。 我喜欢将其称为“ Git Borg” ,其中git在其现有系列中增加了您的技术独特性。

5 git的一个共同主题是“这是不太你想要什么?没关系,我们会保持现有的东西, 但要更复杂 ,所以你可以做想做什么呢!”

6见脚注5。

这样的答案表明:

git fetch --all
git reset --hard origin/master

但是我还没有尝试过,所以不能确定它是否可以解决问题。 但这至少是一个尝试的方向。

GIT告诉您先获取。 您可以在日志中看到

$ git fetch -all

可能其他人已经推动精通,而您的承诺落伍了。 因此,您必须获取,合并更改集,然后才能再次推送。

如果显示遥控器上有更改,请执行“ Pull”操作,这将更新您的工作目录。

$ git pull

然后您将更改推送到遥控器

$ git push -u origin master

我希望这会帮助您将更改推向大师

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM