无法拉取或推送我的github回购



以下是我所做的。

  1. 在github repo中直接对我的README进行了3次提交更改
  2. 在本地又进行了4次提交,而没有将这3次提交拉入

现在,当我尝试推送时,它说先拉那些远程提交,但当我进行git拉时,它显示错误。

warning: Pulling without specifying how to reconcile divergent branches is discouraged. You can squelch this message by running one of the following commands sometime before your next pull:
git config pull.rebase false  # merge (the default strategy)
git config pull.rebase true   # rebase
git config pull.ff only       # fast-forward only

所以我只是运行命令git config pull.ff only

现在,当我拉动它时,它说的是fatal: Not possible to fast-forward, aborting.

好的。。。。当前设置(使用pull.ff only)的问题是,它是一个非常限制的设置。

假设这个启动图

A <- B <- C <- D <- (main)

您从main启动一个功能分支:

A <- B <- C <- D <- (main)
^
- (feature)

过了一段时间,图表是这样的:

A <- B <- C <- D <- F <- G <- (main)
^
- (feature)

请注意feature没有移动。此时,feature指向main的祖先,因此快进将起作用,它将执行以下操作:

A <- B <- C <- D <- F <- G <- (main)
^
- (feature)

因为,顾名思义,快进只移动指针,所以在这个过程中不会进行任何重新定基/合并。

然而,在一个正常的功能分支上,您会引入提交,所以您会有这样的东西:

A <- B <- C <- D <- F <- G <- (main)
^
- I <- J <- K <- (feature)

在这种情况下,假设feaure没有指向main的祖先,不可能执行FF……但您的设置要求仅在它是FF的情况下运行pull……因此,它失败了。您需要能够重新建立基础或合并才能工作,因此pull.ff only是一个禁止

注意:我并不反对eftshift0的答案,因为我同意将pull.ff设置为only是有限制的。但我要指出,这一限制可能是个好主意。这是我想要的,事实上,我自己也用这种方式配置了Git。

git pullgit pull originbranchfatal: Not possible to fast-forward, aborting错误而失败时,是时候使用git log检查传入的提交了,例如:

git log --graph --decorate --left-right --boundary ...@{u}

(或与添加--oneline相同),或:

git log --oneline ..@{u}

以显示";传入";提交(已提取,只是尚未合并或重新基于)和:

git log --oneline @{u}..

以显示";仅本地";commits(存在于我的存储库中,但不存在于我提取的其他Git中)。这些git log命令都使用了@{u}结构,它是branch@{upstream}的缩写。

分支名称的上游是您可以设置的,但通常在执行此操作时已正确设置。例如,如果您在develop分支上;上游";develop的可能是origin/develop,这可能是正确的。上游的这个特殊概念——Git在这里很糟糕,它使用单词upstream来表示多个不同的概念1——就是我们在这里谈论的一个:无论你是什么分支;关于";现在;上游";这个名称的origin/版本,您可能想与git rebasegit merge或您想做的任何操作一起使用。

写出develop@{upstream}就可以了,但如果你不是在develop上,而是在feature/long上呢?现在您必须编写feature/long@{upstream}。Git有一个简单的解决方案:如果去掉分支名称,只写@{upstream},这意味着当前分支的上游。这就是我们在这里所做的。我们也可以将HEAD@{upstream}写得更明确,但当HEAD部分很明显时,我们可以省略它。

同时,两个点符号HEAD..HEAD@{upstream}A..Bmain..origin/main或其他任何符号也有非常具体的含义。对于CCD_ 36——类似于大多数Git命令2——它意味着";使用我在右边指定的提交,可以找到很多提交;当您找到那些使用我在左边指定的提交的提交时,请停止查找这些提交"这意味着CCD_ 37或CCD_。

如果你不习惯Git,最后一段可能只是看起来像是很多随机的单词。但使用eftshift0绘制的相同类型的图表,我们可以理解这一点。以下是发生的事情:

I--J   <-- feature/long (HEAD)
/
...--G--H   <-- main

K--L   <-- origin/feature/long

在这里,我是"关于";我的分支机构CCD_ 39。其上游为origin/feature/long。I、 他们都是从共同的起点提交H开始的:我提交了两个I-J,他们——无论他们是谁——都提交了两次K-L

当我在原点上运行git fetch时——请记住,git pull运行的第一个命令始终是git fetch——我得到了他们的K-L提交,我的Git软件更新了我的origin/feature/long以记住提交L,我现在已经有了。这就是为什么这个图看起来是这样的:这就是我的Git存储库中的内容。(到目前为止,他们的Git存储库完全没有提交I-J。)

现在,请注意,HEAD的字面意思是feature/long,而HEAD@{upstream}的意思是origin/feature/long。进一步注意,CCD_;从B开始并向后工作所发现的提交,不包括从A开始并向后操作所发现的"提交";。如果我们将这些与HEADHEAD@{upstream}放在一起作为AB部分,我们要求Git找到:

  • L这样的提交,我们可以在origin/feature/long中找到
  • 包括像K这样的提交,我们可以从那里开始并向后工作,就像Git喜欢做的那样
  • ,包括JIH等提交

结果是git log HEAD..HEAD@{upstream}显示提交LK,然后停止!这正是";传入";提交。

同时,用git log HEAD@{upstream}..HEAD反转这两个参数,显示提交J,然后是I,然后停止:这些正是我的提交,而它们没有。

添加--graph和/或--oneline有助于更好地显示这类内容。由于我们可以在Git清楚我们的意思是HEAD时删除单词HEAD,并且由于@{u}@{upstream}的缩写,所以我们可以写..@{u}@{u}..

事实上,我经常使用git log ..@{u},所以我为它创建了一个Git别名:

[alias]
lin = log ..@{u}

这使我可以运行git linlog(或查看)即将提交的in。(我有一个包括--onelineincoming别名,以及一个具有--oneline并交换@{u}侧的git outgoing。)

git log ...@{u}一样,三个点的形式更为奇特:它意味着左侧或右侧都有提交,但不是两者都有。这会发现提交J-IL-K,换句话说,对于上面绘制的图。这里的缺点是,您无法判断哪个提交在哪个"提交"上;侧面";。添加--left-right修复了这一问题;添加CCD_ 95绘制图形;并且添加CCD_ 96告诉Git也包括提交CCD_。不过,我并没有真正使用这种形式,也没有为它使用别名:";传入";以及";传出";这里是我的常用别名3

在任何情况下,在检查传入的提交之后,我选择是合并、重新建立基础,还是完全做其他事情。然后我就这么做。我只想做快进,如果我可以做快进;在这种情况下,让Git使用git pull自动执行可能是可以的。因此,将pull.ff设置为only是我想要的。


1我把Git比作一个聚会,每个人都叫Bruce。有人走到你面前说:";嘿,Bruce,Bruce让我告诉Bruce Bruce正在找他。如果你看到布鲁斯,让他知道,好吗"在Git中,一次又一次地将同一个词疯狂地重复用于多种不同的事物,这非常令人困惑——就像在这次Bruce聚会上一样。

2同样,Git在这里并不总是很好:一些Git命令使用双点符号来表示其他含义。git diff命令是最明显的罪魁祸首。它同时使用两点和三点表示法来表示不同的意思。我们不会在这里报道。

3它们也是hg log的两种Mercurial形式,并非完全巧合。

最新更新