git push 时发生 error: failed to push some refs to 错误 (解决办法)
出现问题的原因:在github上更新了README.md,没有更新到本地仓库。而在本地git仓库又修改了文件,这时使用 git push origin master 推送到远程仓库后就出现了下面的问题:
解决办法:
使用git pull origin master 命令将远程仓库和本地仓库进行连接。之后可能会出现
Merge branch 'master' of提示问题,编辑不了文字,可直接按 shift+! 进入编辑状态输入 wq 后可以了。
产生原因分析
当多人合作开发一个项目时,本地仓库落后于远程仓库是一个非常正常的事情,可参考下图。
1 A-B-C(master) 2 \ 3 D(origin/master)
具体情境如下:
- 我当前拉取的远端版本为
B
,此时修改了代码,并在本地仓库 commit 一次,但并未 push 到远端仓库。 - 另一位开发者在
B
的基础上,同样 commit 了一次并 push 到远端仓库。那么这个时候,我再 push 自己的代码就会发生错误,如下。
这个时候我们会选择,先 pull,再 push。Ok,push 成功,但是此时我们查看 log 就会发现除了我们自己提交的那条日志之外,会多出一条 "Merge branch 'master' of ..."。
那么,为什么会出现这种现象呢?其实是与 Git 的工作原理有关,对 Git 比较了解的人应该会知道,无论是 pull
、push
亦或是 merge
操作,其实背后都是有很多的不同的模式的。
在进行 pull 操作的同时,其实就是 fetch+merge 的一个过程。我们从 remote 分支中拉取新的更新,然后再合并到本地分支中去。
- 如果 remote 分支超前于本地分支,并且本地分支没有任何 commit 的,直接从 remote 进行 pull 操作,默认会采用
fast-forward
模式,这种模式下,并不会产生合并节点,也就是说不会产生多余的那条 log 信息 - 如果想之前那样,本地先 commit 后再去 pull,那么此时,remote 分支和本地会分支会出现分叉,这个时候使用 pull 操作拉取更新时,就会进行分支合并,产生合并节点和 log 信息。这两种状态分别如下图所示:
1 # fast-forword 2 A-B-D(origin/master) 3 \ 4 C'(master) 5 6 # merge 7 A-B-C-E(master) 8 \ / 9 D(origin/master)
如何避免
为了去除自动生成的 log 信息,有以下几种解决方案:
- 如果你使用的是 Git Bash,直接使用
git pull --rebase
。如果拉取不产生冲突,会直接 rebase,不会产生分支合并操作,如果有冲突则需要手动 fix 后,自行合并。 - 如果使用的是 GUI,例如 TortoiseGit,可以先 fetch,再手动 rebase 就可以了。
关于 rebase 和 merge
关于什么时候使用 rebase,什么时候使用 merge,开发者总结了几条规则:
- 从 remote 分支拉取更新到本地时,使用 rebase。
- 当完成 bug 修复或新功能时,使用 merge 将子分支合并到主分支。
- 没有人应该 rebase 一根共享的分支。