3152 字
16 分钟
Git冲突处理
2026-06-01

前言#

上一篇文章Git协作流程介绍了多人协作时,一个功能从开发到合并的大致流程。

真正写项目时,最容易让人头疼的往往不是提交代码,而是各种异常情况:

  • pull冲突
  • merge冲突
  • push被拒绝
  • 提交错了
  • 分支搞乱了
  • 改了一半代码但突然要切分支

这些问题刚遇到时会很吓人,尤其是终端里突然出现一堆英文提示,很容易不知道下一步该敲什么。

这篇就不讲太多Git原理了,主要记录一些常见问题的处理方法。目标很简单:遇到问题时,知道先看什么,再执行什么命令。

为什么会产生冲突#

先看一个最常见的场景:

你修改 login.js
同事也修改 login.js
你执行 git pull
Git 无法自动决定保留哪份代码
产生冲突

Git能自动合并很多修改。

比如你改了login.js,同事改了README.md,这两个文件互不影响,Git一般能自动合并。

再比如你和同事都改了login.js,但你改的是第10行,同事改的是第80行,Git大多数时候也能自动合并。

真正容易冲突的是:

同一个文件
同一个位置
被不同人改了不同内容

这时Git不知道应该保留你的版本,还是保留同事的版本,所以它会停下来,让你手动处理。

冲突本身不是Git坏了,而是Git不敢替你乱选。

merge冲突#

假设你在main分支,想把feature-login分支合并进来:

Terminal window
git merge feature-login

如果两边修改了同一个位置,可能会看到类似提示:

CONFLICT (content): Merge conflict in login.js
Automatic merge failed; fix conflicts and then commit the result.

这时先不要慌,先看状态:

Terminal window
git status

git status会告诉你哪些文件处于冲突状态。

打开冲突文件后,一般会看到这种内容:

<<<<<<< HEAD
本地内容
=======
另一分支内容
>>>>>>> feature-login

这里的含义是:

  • <<<<<<< HEAD=======之间,是当前分支的内容
  • =======是分隔线
  • =======>>>>>>> feature-login之间,是待合并分支的内容
  • >>>>>>> feature-login表示这些内容来自feature-login

处理冲突时,不是简单删除某一边就完事,而是要根据实际需求改成最终正确的代码。

处理步骤一般是:

  1. 打开冲突文件
  2. 删除<<<<<<<=======>>>>>>>这些冲突标记
  3. 保留或合并正确内容
  4. 保存文件
  5. 重新加入暂存区
  6. 提交合并结果

命令是:

Terminal window
git add login.js
git commit

如果有多个冲突文件,就都处理完后再git add

Terminal window
git add 文件1 文件2
git commit

pull为什么会冲突#

很多人会觉得奇怪:

Terminal window
git pull

不是拉代码吗,为什么也会冲突?

原因是git pull并不是单纯下载代码,它本质上等于:

git pull = git fetch + git merge

也就是说,git pull会先把远程的新提交下载下来,然后再把远程分支合并到你当前分支。

既然它内部做了merge,那当然也可能产生merge冲突。

所以遇到pull冲突时,处理方式和merge冲突基本一样:

Terminal window
git status
# 手动修改冲突文件
git add 冲突文件
git commit

如果你不确定哪些文件冲突了,永远先看:

Terminal window
git status

这个命令会告诉你当前Git卡在哪一步。

rebase冲突#

有些团队或个人习惯用rebase来同步代码,比如:

Terminal window
git pull --rebase

或者:

Terminal window
git rebase main

rebase也可能冲突。

冲突文件里的标记看起来也差不多,还是这种形式:

<<<<<<< HEAD
当前内容
=======
你的提交内容
>>>>>>> 提交ID

处理文件的方式一样:打开文件,删掉冲突标记,改成最终正确内容。

不同的是,rebase处理完冲突后,不是执行git commit,而是:

Terminal window
git add 文件名
git rebase --continue

如果后面还有冲突,就继续处理,再继续:

Terminal window
git add 文件名
git rebase --continue

如果这次rebase越处理越乱,想放弃,可以:

Terminal window
git rebase --abort

这个命令会取消本次rebase,回到rebase之前的状态。

简单记:

merge 冲突解决完:git add -> git commit
rebase 冲突解决完:git add -> git rebase --continue

push被拒绝#

推送时看到这种提示也很常见:

failed to push some refs

或者提示远程分支比本地更新。

常见原因是:

远程仓库已经有新提交
但你本地还没有这些提交
所以Git拒绝直接推送

比如你和同事都在同一个分支上开发。同事先推送了代码,你本地还没拉取他的提交,这时你直接git push,Git就可能拒绝。

比较常见的解决方式是:

Terminal window
git pull --rebase
git push

意思是先把远程的新提交拿下来,再把你的提交放到后面,然后重新推送。

如果git pull --rebase过程中出现冲突,就按前面rebase冲突的方式处理:

Terminal window
git status
# 手动修改冲突文件
git add 文件名
git rebase --continue
git push

不要一看到push失败就立刻强制推送。强制推送可能会覆盖别人已经推上去的提交,尤其是在公共分支上很危险。

临时保存修改#

有时你代码写到一半,突然要切到别的分支修bug。

这时如果直接切分支,Git可能会提示:

Please commit your changes or stash them before you switch branches.

意思是:你当前还有未提交修改,先提交或者临时保存起来。

如果这些代码还没写完,不适合提交,可以用stash临时保存。

保存当前修改:

Terminal window
git stash

查看保存列表:

Terminal window
git stash list

恢复最近一次保存:

Terminal window
git stash pop

pop会恢复修改,并把这条stash记录从列表里删除。

如果只想恢复但保留stash记录,可以用:

Terminal window
git stash apply

删除某条stash:

Terminal window
git stash drop

如果有多条stash,可以指定名字:

Terminal window
git stash pop stash@{0}
git stash drop stash@{0}

stash适合临时救急,不建议长期把重要代码放在里面。重要修改最好还是及时提交到分支上。

撤销未提交的修改#

如果文件改坏了,还没有提交,可以用restore恢复。

恢复单个文件:

Terminal window
git restore 文件名

恢复当前目录下所有未提交修改:

Terminal window
git restore .

注意,这个操作会丢失工作区修改。

执行前最好先看一下:

Terminal window
git diff

确认这些修改真的不要了,再执行restore

取消暂存#

如果文件已经git add了,但还没commit,想把它从暂存区拿出来:

Terminal window
git restore --staged 文件名

这个命令只是取消暂存,不会删除文件内容。

比如你执行了:

Terminal window
git add .

结果发现把不该提交的文件也加进去了,就可以:

Terminal window
git restore --staged 文件名

然后重新选择真正要提交的文件。

回退提交#

如果已经提交了,但发现提交错了,可以用reset

先查看提交历史:

Terminal window
git log --oneline

比如最近一次提交写错了,想撤销这个commit,但代码还想保留:

Terminal window
git reset --soft HEAD~1

--soft的意思是:

撤销 commit
保留代码修改
保留暂存状态

如果想撤销提交,并且让修改回到未暂存状态,可以用:

Terminal window
git reset --mixed HEAD~1

--mixedgit reset默认模式,通常可以不写。

最危险的是:

Terminal window
git reset --hard HEAD~1

它的意思是:

撤销 commit
代码修改也一起删除

所以--hard一定要慎用。执行前最好确认这次提交里的代码真的不要了。

如果提交已经推送到远程,并且别人可能已经基于它继续开发,就不要随便reset --hard再强推,这很容易影响别人。

使用revert撤销提交#

多人协作时,更推荐用revert撤销已经提交的内容。

命令是:

Terminal window
git revert 提交ID

revertreset的区别可以简单理解成:

reset:把历史往回挪
revert:新增一个反向提交

比如某个提交添加了三行代码,revert会生成一个新的提交,把这三行代码删掉。

它不会删除历史记录,所以更适合多人协作。

简单建议:

  • 自己本地还没推送的提交,可以考虑reset
  • 已经推送到远程的提交,优先考虑revert
  • 公共分支上不要随便reset --hard

reflog:Git的后悔药#

如果你误删了提交,或者reset过头了,可以先看reflog

Terminal window
git reflog

输出大概像这样:

abc123 HEAD@{0}: reset: moving to HEAD~1
def456 HEAD@{1}: commit: 添加登录页面

git log主要看当前分支能看到的提交历史。

git reflog记录的是HEAD移动过的位置。很多误操作之后,提交虽然从普通日志里看不到了,但还能在reflog里找到。

找到想恢复的提交ID后,可以:

Terminal window
git reset --hard def456

注意,reset --hard会让当前代码回到那个提交对应的状态,执行前确认工作区没有要保留的修改。

如果不想直接回退,也可以先新建一个分支保住现场:

Terminal window
git switch -c recover-branch def456

这样更稳一点。

强制推送#

强制推送命令是:

Terminal window
git push --force

它的风险很大,因为它可能覆盖远程分支历史。

比如远程分支上有同事刚推送的提交,你本地没有这些提交,直接--force可能会把同事的提交顶掉。

如果确实需要强制推送,更推荐:

Terminal window
git push --force-with-lease

简单理解:

--force:直接用本地历史覆盖远程历史
--force-with-lease:如果远程分支被别人更新过,就拒绝覆盖

--force-with-lease不是完全没有风险,但比--force更安全。

日常建议:

  • 自己的功能分支,确认没人共用时,可以谨慎使用
  • 公共分支,比如maindevelop,不要随便强推
  • 不确定时,先问团队成员,不要直接覆盖远程

常见问题#

commit说明写错了怎么办#

如果只是最近一次提交说明写错了,还没推送,可以:

Terminal window
git commit --amend

它会修改最近一次提交。

也可以直接写新说明:

Terminal window
git commit --amend -m "新的提交说明"

如果这个提交已经推送到远程,修改后通常需要强制推送。多人协作时要谨慎。

push到错误分支怎么办#

先不要继续操作,先确认当前分支和提交历史:

Terminal window
git branch
git log --oneline

如果只是把提交推到了自己的错误分支,可以把正确提交cherry-pick到目标分支,再在错误分支上用revert撤销。

如果推到了公共分支,建议不要自己直接reset --hardpush --force,先和团队确认处理方式。

删除错分支怎么办#

如果只是删除了本地分支,可以先用reflog找提交:

Terminal window
git reflog

找到提交ID后重新建分支:

Terminal window
git switch -c 分支名 提交ID

如果远程分支还在,也可以直接重新拉:

Terminal window
git fetch origin
git switch -c 分支名 origin/分支名

reset过头了怎么办#

先看:

Terminal window
git reflog

找到reset之前的提交ID,然后恢复:

Terminal window
git reset --hard 提交ID

如果当前工作区还有想保留的修改,不要立刻--hard,可以先stash或者新建分支保存现场。

merge和rebase冲突有什么区别#

冲突文件的处理方式差不多,都是:

打开文件
删除冲突标记
保留正确内容
git add

区别在最后一步:

merge 冲突:git commit
rebase 冲突:git rebase --continue

如果不想继续:

Terminal window
git merge --abort
git rebase --abort

分别用于取消当前的mergerebase

总结#

遇到Git冲突时,可以先按这条线处理:

冲突
git status
编辑冲突文件
git add
git commit / git rebase --continue

不要一看到冲突就乱敲命令。先用git status看清楚Git现在卡在哪一步,再决定是commitrebase --continue,还是abort

常见场景可以记这个表:

场景命令
查看状态git status
临时保存git stash
恢复修改git restore 文件名
取消暂存git restore --staged 文件名
回退提交git reset
安全撤销git revert 提交ID
查看历史git log --oneline
找回误删提交git reflog
继续rebasegit rebase --continue
取消rebasegit rebase --abort

Git很多问题看起来吓人,其实大部分都有固定处理流程。只要提交前多看statusdiff,公共分支上少用危险命令,出了问题先别急着强推,基本都能处理回来。

Git冲突处理
https://blog.aloys233.top/posts/git冲突处理/
作者
Aloys23
发布于
2026-06-01
许可协议
CC BY-NC-SA 4.0

评论