简短答案
您忽略了您已运行git push
,出现以下错误然后继续运行的事实git pull
:
To git@bitbucket.org:username/test1.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
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.
尽管Git试图提供帮助,但它的“ git pull”建议很可能不是您想要做的。
如果你是:
- 单独在“功能分支”或“开发人员分支”上工作,然后您可以运行
git push --force
以使用还原后的提交来更新远程服务器(根据user4405677的回答)。
- 同时与多个开发人员一起工作在一个分支上,那么您可能一开始就不应使用
git rebase
。要通过更新dev
来自的更改master
,您应该git rebase master dev
在的git merge master
同时运行(而不是运行)dev
(根据Justin的回答)。
稍长的解释
Git中的每个提交哈希都基于许多因素,其中之一是在它之前的提交的哈希。
如果您对提交进行重新排序,则会更改提交哈希值;重定基础(执行某些操作时)将更改提交哈希。这样,run的结果与git rebase master dev
哪里dev
不同步master
,将创建新的提交(并由此产生哈希值),其内容dev
与上次提交的内容相同,但master
之前插入了提交的内容。
您可能会以多种方式陷入这种情况。我可以想到两种方式:
- 您可能
master
希望基于您的承诺dev
工作
- 您可能已经将提交提交
dev
到远程,然后继续进行更改(重新提交提交消息,重新排序提交,压缩提交等)。
让我们更好地了解发生了什么—这是一个示例:
您有一个存储库:
2a2e220 (HEAD, master) C5
ab1bda4 C4
3cb46a9 C3
85f59ab C2
4516164 C1
0e783a3 C0
然后,您可以更改提交。
git rebase --interactive HEAD~3 # Three commits before where HEAD is pointing
(这是您必须遵守的地方:在Git中有多种更改提交的方法。在此示例中,我更改了的时间C3
,但是您要插入新的提交,更改提交消息,重新排列提交,挤压在一起,等等)
ba7688a (HEAD, master) C5
44085d5 C4
961390d C3
85f59ab C2
4516164 C1
0e783a3 C0
在这里重要的是要注意提交哈希是不同的。这是预期的行为,因为您已更改了某些内容(所有内容)。没关系,但是:
尝试推送将显示一个错误(并提示您应该运行git pull
)。
$ git push origin master
To git@bitbucket.org:username/test1.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
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.
如果运行git pull
,我们将看到以下日志:
7df65f2 (HEAD, master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 (origin/master) C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
或者,显示另一种方式:
现在,我们在本地有重复的提交。如果要运行,git push
我们会将它们发送到服务器。
为了避免进入这一阶段,我们可以运行git push --force
(改为运行git pull
)。这样就可以将带有新哈希的提交发送到服务器而不会出现问题。要在此阶段解决问题,我们可以在运行之前重置为git pull
:
查看reflog(git reflog
),看看在我们运行之前提交哈希是什么git pull
。
070e71d HEAD@{1}: pull: Merge made by the 'recursive' strategy.
ba7688a HEAD@{2}: rebase -i (finish): returning to refs/heads/master
ba7688a HEAD@{3}: rebase -i (pick): C5
44085d5 HEAD@{4}: rebase -i (pick): C4
961390d HEAD@{5}: commit (amend): C3
3cb46a9 HEAD@{6}: cherry-pick: fast-forward
85f59ab HEAD@{7}: rebase -i (start): checkout HEAD~~~
2a2e220 HEAD@{8}: rebase -i (finish): returning to refs/heads/master
2a2e220 HEAD@{9}: rebase -i (start): checkout refs/remotes/origin/master
2a2e220 HEAD@{10}: commit: C5
ab1bda4 HEAD@{11}: commit: C4
3cb46a9 HEAD@{12}: commit: C3
85f59ab HEAD@{13}: commit: C2
4516164 HEAD@{14}: commit: C1
0e783a3 HEAD@{15}: commit (initial): C0
在上方,我们看到的ba7688a
是我们在运行之前所进行的提交git pull
。有了该提交哈希,我们可以重置回那个(git reset --hard ba7688a
)然后运行git push --force
。
我们完成了。
但是,等等,我继续基于重复的提交进行工作
如果您以某种方式没有注意到提交已被重复,并继续在重复的提交之上继续工作,那么您确实为自己弄得一团糟。混乱的大小与重复项之上的提交次数成正比。
看起来像什么:
3b959b4 (HEAD, master) C10
8f84379 C9
0110e93 C8
6c4a525 C7
630e7b4 C6
070e71d (origin/master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
或者,显示另一种方式:
在这种情况下,我们要删除重复的提交,但要保留基于它们的提交-我们希望保持C6到C10。与大多数事情一样,有多种方法可以解决此问题:
要么:
- 在最后一个重复的提交1处创建一个新分支,
cherry-pick
每个提交(包括C6至C10)到该新分支,并将该新分支视为规范分支。
- 运行
git rebase --interactive $commit
,两次重复$commit
提交之前的提交在哪里2。在这里,我们可以彻底删除重复项的行。
1无论选择哪个,ba7688a
还是2a2e220
工作正常,都没有关系。
2在示例中为85f59ab
。
TL; DR
设置advice.pushNonFastForward
为false
:
git config --global advice.pushNonFastForward false