简答
你忽略了你运行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 中的每个提交哈希都基于许多因素,其中之一是之前提交的哈希。
如果您重新排序提交,您将更改提交哈希;变基(当它做某事时)会改变提交哈希。这样,运行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