目录
1、问题描述
2、分析问题
3、解决问题
3.1、先合并之前的历史,再进行提交——提倡使用
3.2、丢弃之前的历史,强推——谨慎使用
当要push代码到git时,出现提示:
$ git push origin master
To ../remote/
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to '../remote/'
Dealing with “non-fast-forward” errors:(From time to time you may encounter this error while pushing)
To prevent you from losing history, non-fast-forward updates were rejected. Merge the remote changes before pushing again. See the 'non-fast forward' section of 'git push --help' for details.
This error can be a bit overwhelming at first, do not fear. Simply put, git cannot make the change on the remote without losing commits, so it refuses the push. Usually this is caused by another user pushing to the same branch. You can remedy this by fetching and merging the remote branch, or using pull to perform both at once.
In other cases this error is a result of destructive changes made locally by using commands like git commit --amend or git rebase. While you can override the remote by adding --force to the push command, you should only do so if you are absolutely certain this is what you want to do. Force-pushes can cause issues for other users that have fetched the remote branch, and is considered bad practice. When in doubt, don’t force-push.
上面这段是从博主那摘抄的(2012年的文章),其实这和上面那张图的内容有很多相似之处,因为技术的发展和经验的积累,现在的git的功能也越来越完善,它不仅提示出错(具体原因),还会给出一些建设性意见,以供你参考。
我们知道git的一大好处就是可以团队合作开发,但是这就涉及到一个问题,怎么保证远程仓库的一致性?这也是它不得不处理的一个重要问题!
我们可以这样理解这个问题就是:别人上传到远程仓库后,你没有及时的同步(、拉取)到本地,但是你同时又添加了一些内容(提交),以致于你在提交时,它会检测到你之前从远程仓库拉取的时候的仓库状态和现在的不一样。于是,它为了安全起见拒绝了你的提交(然后就报了这个错误)。
再者我们可以简单来理解这个问题:我们从字面上理解“non-fast-forward”,可以认为是“不能快速前进”,我觉得有个广告说得好:车到山前必有路……但是路有好走的路,也有不好走的路;而遇到不好走的路时(比如前方遇到拦路石,或者是前方出现岔路),我们就不得不停下来思考“以后的路该怎么走”了,我们“不仅要低头赶路,也要抬头看路”就是这个意思。
“不能快速前进”的原因是因为路不一样了,变得不好走了;体现在git里面就是提交历史出现分叉,主线不再是一条直线,而是在前端出现了分叉,git不知道该如何前进,所以报错了,让你来觉得走哪条路!
于是你有2个选择方式:
(1)先把git的东西fetch到你本地然后merge后再push
$ git fetch origin master
$ git merge origin FETCH_HEAD
先抓取远程仓库的更新到本地,然后与你的本地仓库合并,(如果有冲突就要解决冲突后再合并,冲突问题比较复杂,这里就不详细说了),这样就可以使远程仓库和你本地仓库一致了,然后就可以提交修改了。
(2)这2句命令等价于
$ git pull origin master
但是使用git fetch + git merge 更加安全。
(3)git pull --rebase origin master
重定基,可以是历史更加统一,即使提交历史趋向于一条直线。
补充:他们之间的关系
git pull = git fetch + git merge FETCH_HEAD
git pull --rebase = git fetch + git rebase FETCH_HEAD
强推,即利用强覆盖方式用你本地的代码替代git仓库内的内容
$ git push -f 或者 $ git push --force
官方文档提示:This flag disables these checks, and can cause the remote repository to lose commits; use it with care.(即:此标志禁用这些检查,并可能导致远程存储库丢失提交;小心使用。)
俗话说得好:“强扭的瓜不甜”,强制(暴力)执行总会产生一些不好的结果,应慎重考虑是否使用该命令!!!
不仅在此处,在平时使用时,也要非常注意,除非你真的是想覆盖远程仓库(你真的知道自己在干嘛!),不然最好不要强制执行。
推荐阅读(英文):Dealing with non-fast-forward errors
2019年7月28日10:02:13 更新部分内容。