当我执行git pull,add,commit,push时,会发生这种情况
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'http://foo:8080/tfsdev/foo/_git/Development.Services'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Run Code Online (Sandbox Code Playgroud)
当我添加-ff到git pull时,它会通过.我认为fastforward是默认的,为什么会发生这种情况?
tor*_*rek 12
当我添加-ff到git pull时,它会通过.我认为fastforward是默认的,为什么会发生这种情况?
你是混合了一堆在这里不同的概念......这也难怪,因为git pull 还混合了一堆不同的概念,企图要方便是主要结果是混乱.(好吧,偶尔也方便.:-))
使用git pull通常会运行git merge,这通常会执行快进而不是合并.这使您的分支更新git pull了从远程(via git fetch)带来的任何内容,以便您添加的提交,也将仅添加(不替换或删除)其提交.但是,git push是不是相反git pull,它是相反的git fetch:它不会做任何合并.
当你做一些pull+做东西(提交或其他)+ push序列时,你正在与其他也在做pull-commit-push序列的人竞争.谁赢了,就得推.这部分真的很简单.当你没有赢的时候会出现问题!
当你是唯一一个跑步的人时,很容易赢得这场比赛. 如果没有其他人推进那个分支,你将永远赢得比赛.这里发生的事情是你不是唯一一个跑步的人,你输了.
遗憾的是,完整的答案很复杂,而且你没有充分展示能够回答这个具体案例的情况.那么让我们来看看究竟发生了什么.
如果git status说on branch master,或git branch打印* master,你当前的分支是master.大多数Git命令都适用于您当前的分支,git pull这里也不例外.
该git pull命令只运行另外两个Git命令.第一个是永远 git fetch.第二个,你可以改变.
git pull运行git fetch第一个命令git pull运行是git fetch.它运行有点有限 git fetch,告诉git fetch你只需要当前分支所需的提交和其他项目.如果你只是跑步git fetch,Git会带来所有东西,这可能需要更长的时间,但意味着你可以与所有东西保持同步.
该git fetch命令是关于使用当前分支的常用Git规则的例外.在某些情况下,它仍会查看您当前的分支,但git fetch通常更新远程跟踪分支是什么.在大多数情况下,你将有只有一个所谓的遥控器,命名origin,并运行git fetch从拥有超过一切origin,并更新你的origin/master,origin/develop和其他origin/分支.这些是远程命名的远程跟踪分支origin.
因此,如果您git fetch自己运行,它将更新所有origin/*远程跟踪分支.如果您运行git pull,它将以基于您当前分支仅git fetch更新其中一个的方式运行.这些更新始终是安全的:它们将新的提交带入您的存储库,这对您的存储库中的所有现有提交都没有影响.
只要是混乱的,git fetch并将它的所有更新到指定的文件FETCH_HEAD,你会看到中提到的git fetch文档.但它也会更新你的远程跟踪分支,除非你有一个非常旧版本的Git(早于Git版本1.8.4).对于那些有古代Gits(1.7.x)的人来说,手册里git fetch的所有内容都是从origin更新它们开始的,但是那个运行的手册git pull没有.
git pull运行别的东西事情变得有些混乱.所述第二部分git pull是任一 git merge或git rebase.默认情况是git merge,即使git rebase通常是一个更好的主意. 您必须提前选择git pull应使用的命令. 但是你应该使用哪一个?要确定的唯一方法是查看即将发生的事情.如果你拿起新的提交,你可以用它们git log和其他Git命令来查看它们.
然而,要看到即将发生的事情,你必须把它带进来.那就是git fetch它.该git fetch步骤安全地引入了新的提交,将它们安全地放在那些远程跟踪分支之后. 现在您可以决定是合并还是改造.
该git pull命令会让您在看之前做出决定.因此,选择你想要它做哪一个 - 合并,或者rebase-and pull,然后它将获取然后执行.要使其执行rebase,运行git pull --rebase或设置当前分支以git pull默认执行此操作.
(这个设置是每个分支,所以你必须为每个分支设置它.还有一个配置条目告诉Git为Git创建的每个分支自动设置"rebase模式" - 但是在我看来,运行git fetch自己要容易得多,然后自己运行第二个命令.这使您有机会查看您所获取的内容,以及在出现问题时更少混淆.)
git merge让我们假设第二件事git pull就是git merge.这确实对你当前分支工作.但git merge它本身有点复杂.
当您合并时,您通常通过分支名称选择一些提交,并且通常通过远程跟踪分支名称(例如origin/master-)并要求Git找出几个东西.这种合并的目标很容易说明:合并将您完成的工作与其他人的工作结合起来,用两组工作进行新的提交.
为了弄清楚你做了什么,以及他们(无论他们是谁)做了什么,Git必须找到合并基础.这个合并基础或多或少是您和他们共享的第一个提交.这意味着是时候绘制提交图的一部分了.这是一些可能性.
...--o--* <-- master
\
o <-- origin/master
Run Code Online (Sandbox Code Playgroud)
该os为提交,与新向右提交.我已经标记了合并基础提交*.在这里,您master指向合并基础提交,origin/master指向更新的提交.
在这种情况下,git merge能够做到这个"快进"的事情.也就是说,因为合并基础已经是提示master,所以不需要实际的合并.Git只需向下滑动名称大师,使其指向同一个提交origin/master:
...--o--o
\
o <-- master, origin/master
Run Code Online (Sandbox Code Playgroud)
现在我们也可以理顺这条线,并且只有:
...--o--o--o <-- master, origin/master
Run Code Online (Sandbox Code Playgroud)
如果你现在跑步git push origin master,基本上没有任何事情发生,因为你的结果并没有什么新东西.最后一次提交是你已经得到的origin.
但是,如果我们有这个呢?
...--o--*--o <-- master
\
`-o <-- origin/master
Run Code Online (Sandbox Code Playgroud)
在这里,Git必须进行真正的合并.Git将提交*与您的master提交(最右边的最右边o)和origin/master提交(o底线)进行比较.也就是说,Git运行了git diff两次.然后它尝试组合两组更改,如果成功,它会进行"合并提交"风格的新提交:
...--o--*--o--o <-- master
\ /
`-o <-- origin/master
Run Code Online (Sandbox Code Playgroud)
这个承诺是准备git push到origin,在比赛反对任何人也试图git push给origin.
你甚至可以从这开始:
...--o--o--* <-- master, origin/master
Run Code Online (Sandbox Code Playgroud)
现在没有任何东西可以合并:名称master和名称origin/master都指向同一个提交,因此合并基础提交已经是master(以及origin/master同样)的提示.现在没有什么可以合并,并且在无所事事之后,也没有什么可以推动的.你甚至不必尝试比赛,更不用说赢了.
现在,您master和origin/master排队,就可以使新的提交.当你这样做时,你的 master意志"领先" origin/master:
...--o--o o--o <-- master
\ /
o <-- origin/master
Run Code Online (Sandbox Code Playgroud)
(我把底部o向下移动,以便我可以指向origin/master它.)
git push呢我上面提到的push并不是相反的pull; 它更像是相反的fetch.
当你运行时git push,你的Git会调用其他一些Git.origin在这种情况下,这就是遥控器上的Git .然后它会移交您所做的任何新提交,并提出请求:"请将您设置master为最新提交."
换句话说,我们要求他们的 Git改变他们 master - 我们称之为origin/master- 匹配我们 的东西master.
看看上面那些相同的图纸.当我们进行快进时,我们将我们转移master到了已经从中获取的提交origin/master.当我们什么也没做,我们什么也没做.在任何一种情况下,都没有新的提交:没有什么可以打扰的.如果我们确实推进了,我们会对另一个Git说:"这里没有什么新东西,但请设置你的,master以便它指向这个特定的提交,就像我们的一样."
如果我们确实做了一个新的提交 - 正如我们对合并做的那样,或者当我们做了新的提交时 - 我们确实为它们提供了新的东西.我们将他们的新提交交给他们,然后让他们设置master我们的相同master.
当然,我们也会在推动其他人的比赛.
如果没有其他人已经赢得了推比赛中,他们master仍然会符合我们的origin/master.我们要求推动,好吧,看看上面的图纸.移动origin/master(我们的名字为他们master)前进以匹配我们master,为什么,这是我们之前看到的那些快速前进操作之一!
如果推动会做快进,它通常会成功.
但如果其他人赢了怎么办?如果有什么,以后我们跑git fetch和git merge,我们花了一些时间去提交,同时其他人上了车,我们推前?
好吧,现在我们有了这个:
...--o--o o--o <-- master
\ /
o <-- origin/master
Run Code Online (Sandbox Code Playgroud)
但是这不是真的完全正确的,因为他们对新提交的 master. 他们有其他人推动的承诺. 我们需要运行git fetch并获取它们.让我们这样做,现在 - 现在用新的提交git fetch更新我们- 现在我们有:origin/master
...--o--o o--o <-- master
\ /
o-----o <-- origin/master
Run Code Online (Sandbox Code Playgroud)
现在,为了推动,我们必须合并或重组.我将绘制合并案例.(请注意,合并基础是最底层的最左侧提交.)
...--o--o o--o--o <-- master
\ / /
*-----o <-- origin/master
Run Code Online (Sandbox Code Playgroud)
如果我们进行合并,现在我们可以推动,因为现在我们master的"快速前进"了master.
当然,在我们合并的同时,我们也在竞争其他可能试图推动的人.如果我们输掉比赛,我们可能需要再次获取和合并.
(在所有这些情况下,git rebase是可能更好的事情,而不是做的git merge.请参阅有关重订其他StackOverflow的答案.)
| 归档时间: |
|
| 查看次数: |
1056 次 |
| 最近记录: |