1. 通用排查步骤
遇到任何 Git 异常,优先执行以下命令:
bash
git status -sb
git branch -vv
git remote -v
git log --oneline --graph --decorate --all -n 20
作用:
git status -sb:看当前分支、工作区是否干净。git branch -vv:看本地分支与远程分支关联关系。git remote -v:看远程地址是否正确。git log --oneline --graph --decorate --all -n 20:看最近提交图和分支位置。
如果有重要未提交改动,先备份:
bash
git stash push -u -m "backup before fixing git issue"
或者创建临时分支保留现场:
bash
git switch -c backup/git-issue-yyyymmdd
2. fatal: not a git repository
现象
text
fatal: not a git repository (or any of the parent directories): .git
原因
当前目录不是 Git 仓库,或没有进入包含 .git 的项目目录。
解决方案
- 确认当前目录:
bash
pwd
# Windows PowerShell
gl
- 进入正确项目目录:
bash
cd <项目目录>
- 如果是新项目需要初始化:
bash
git init
- 如果是误删
.git,从远程重新 clone 通常最安全。
3. Your local changes would be overwritten by merge
现象
text
error: Your local changes to the following files would be overwritten by merge
原因
本地有未提交改动,执行 pull、merge、checkout 时会被远程或目标分支覆盖。
推荐解决方案
方案一:保留改动并提交。
bash
git status
git add .
git commit -m "wip: save local changes"
git pull --rebase
方案二:临时保存改动。
bash
git stash push -u -m "save before pull"
git pull --rebase
git stash pop
方案三:确认不要本地改动后丢弃指定文件。
bash
git restore <文件路径>
git pull
风险提示:不要直接使用 git reset --hard,除非确认所有本地改动都不需要。
4. The following untracked working tree files would be overwritten
现象
text
error: The following untracked working tree files would be overwritten by checkout/merge
原因
本地有未跟踪文件,目标分支或远程也有同名文件,切换或合并会覆盖本地文件。
解决方案
- 查看未跟踪文件:
bash
git status -sb
- 如果要保留,加入 stash:
bash
git stash push -u -m "save untracked files"
- 如果确认不要这些文件,先预览清理:
bash
git clean -n
- 删除未跟踪文件:
bash
git clean -f
- 删除未跟踪目录:
bash
git clean -fd
风险提示:不要直接执行 git clean -fdx,它会删除被 .gitignore 忽略的文件。
5. Merge conflict 合并冲突
现象
text
CONFLICT (content): Merge conflict in xxx.java
Automatic merge failed; fix conflicts and then commit the result.
原因
两个分支修改了同一文件的相同区域,Git 无法自动判断保留哪一方。
文件中的冲突标记
text
<<<<<<< HEAD
当前分支内容
=======
被合并分支内容
>>>>>>> feature/xxx
解决方案
- 查看冲突文件:
bash
git status
-
手动编辑冲突文件,删除
<<<<<<<、=======、>>>>>>>标记。 -
确认业务逻辑正确后加入暂存区:
bash
git add <冲突文件>
- 如果是 merge:
bash
git commit
- 如果是 rebase:
bash
git rebase --continue
- 如果是 cherry-pick:
bash
git cherry-pick --continue
放弃本次操作
放弃 merge:
bash
git merge --abort
放弃 rebase:
bash
git rebase --abort
放弃 cherry-pick:
bash
git cherry-pick --abort
6. Push rejected / non-fast-forward
现象
text
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs
原因
远程分支比本地分支新,本地直接 push 会覆盖远程提交,Git 拒绝。
推荐解决方案
- 先获取远程更新:
bash
git fetch origin
- 如果是个人分支,推荐 rebase:
bash
git pull --rebase
# 解决冲突后
git push
- 如果是共享分支,推荐 merge:
bash
git pull
git push
- 如果确实需要强推,优先用:
bash
git push --force-with-lease
风险提示:--force-with-lease 也会改写远程历史,必须确认不会覆盖他人提交。
7. Updates were rejected because the remote contains work that you do not have locally
现象
text
Updates were rejected because the remote contains work that you do not have locally.
原因
与 non-fast-forward 类似,远程已有本地没有的提交。
解决方案
bash
git pull --rebase
# 如有冲突,解决后 git rebase --continue
git push
如果分支是多人共享,使用:
bash
git pull
git push
8. branch has no upstream branch
现象
text
fatal: The current branch feature/xxx has no upstream branch.
原因
本地新分支还没有关联远程分支。
解决方案
bash
git push -u origin feature/xxx
作用:推送分支并建立 upstream,以后可以直接 git pull 和 git push。
9. src refspec main does not match any
现象
text
error: src refspec main does not match any
常见原因
- 本地没有
main分支。 - 仓库没有任何 commit。
- 分支名实际叫
master或其他名称。
解决方案
- 查看本地分支:
bash
git branch
- 如果没有任何提交,先提交:
bash
git add .
git commit -m "init"
- 如果当前分支是
master,推送master:
bash
git push -u origin master
- 或重命名为
main:
bash
git branch -m master main
git push -u origin main
10. remote origin already exists
现象
text
error: remote origin already exists.
原因
当前仓库已经配置了名为 origin 的远程仓库。
解决方案
查看已有远程:
bash
git remote -v
如果地址不对,修改:
bash
git remote set-url origin <新地址>
如果要删除后重新添加:
bash
git remote remove origin
git remote add origin <新地址>
11. Authentication failed / 认证失败
现象
text
Authentication failed for 'https://...'
fatal: Authentication failed
原因
- 用户名或密码错误。
- 平台不再支持账号密码,需要 Personal Access Token。
- 凭据管理器中缓存了旧密码。
- 仓库权限不足。
解决方案
- 确认仓库地址和账号权限:
bash
git remote -v
-
如果使用 HTTPS,生成并使用 Personal Access Token。
-
清理 Windows 凭据缓存:
text
控制面板 -> 凭据管理器 -> Windows 凭据 -> 删除对应 Git 凭据
-
再次 push/pull 时重新输入账号和 token。
-
或改用 SSH 地址。
12. Permission denied (publickey)
现象
text
git@xxx: Permission denied (publickey).
fatal: Could not read from remote repository.
原因
SSH key 未配置、未加载、未添加到代码平台,或远程地址使用了 SSH 但当前机器没有权限。
解决方案
- 检查是否有 SSH key:
bash
ls ~/.ssh
- 生成 key:
bash
ssh-keygen -t ed25519 -C "your.email@example.com"
- 查看公钥并添加到代码平台:
bash
cat ~/.ssh/id_ed25519.pub
- 测试连接:
bash
ssh -T git@github.com
# 或企业 GitLab 地址
ssh -T git@your-gitlab-host
- 如果不想配置 SSH,切换为 HTTPS:
bash
git remote set-url origin https://example.com/group/project.git
13. SSL certificate problem
现象
text
SSL certificate problem: unable to get local issuer certificate
原因
企业内网 Git 服务、自签名证书、代理证书或证书链不被本机信任。
推荐解决方案
- 安装企业证书到系统可信根证书。
- 配置 Git 使用正确 CA 证书:
bash
git config --global http.sslCAInfo <证书路径>
- 如果是代理问题,配置代理证书或改用 SSH。
不推荐但临时可用:
bash
git config --global http.sslVerify false
风险提示:关闭 SSL 校验会降低安全性,不建议长期使用。
14. fatal: refusing to merge unrelated histories
现象
text
fatal: refusing to merge unrelated histories
原因
两个仓库没有共同历史。例如本地 git init 后又关联了一个已有远程仓库。
解决方案
如果确认要合并两个无关历史:
bash
git pull origin main --allow-unrelated-histories
然后解决冲突并提交。
更安全方案:重新 clone 远程仓库,再把本地文件复制进去提交。
15. detached HEAD
现象
text
You are in 'detached HEAD' state.
原因
当前不是在某个分支上,而是直接检出了某个 commit 或 tag。
影响
可以修改和提交,但提交不属于任何分支,容易丢失引用。
解决方案
如果只是查看代码,切回分支:
bash
git switch main
如果已经在 detached HEAD 下提交了代码,先创建分支保留:
bash
git switch -c rescue/detached-work
然后再决定合并到目标分支。
16. rebase in progress / merge in progress
现象
text
You are currently rebasing.
MERGE_HEAD exists.
原因
上一次 rebase 或 merge 没有完成。
解决方案
查看状态:
bash
git status
如果要继续:
bash
git add <已解决文件>
git rebase --continue
# 或
git commit
如果要放弃:
bash
git rebase --abort
# 或
git merge --abort
17. cannot lock ref / reference broken
现象
text
cannot lock ref 'refs/remotes/origin/xxx'
常见原因
- 远程分支名大小写或路径冲突。
- 本地远程引用缓存异常。
- 并发 Git 操作导致锁文件残留。
解决方案
- 清理远程引用:
bash
git remote prune origin
git fetch origin
- 如果仍失败,检查是否存在冲突分支名,例如:
text
feature/foo
feature/foo/bar
Git 引用路径可能冲突。
- 若确认没有 Git 操作正在运行,可删除
.git下残留 lock 文件。操作前先关闭 IDE、终端中的 Git 进程。
18. index.lock exists
现象
text
fatal: Unable to create '.git/index.lock': File exists.
原因
上一次 Git 操作异常中断,留下锁文件;或者另一个 Git 进程正在运行。
解决方案
- 确认没有正在运行的 Git 命令、IDE Git 操作。
- 关闭可能占用的 IDEA、SourceTree、Git GUI。
- 删除锁文件:
bash
rm .git/index.lock
Windows PowerShell:
powershell
Remove-Item .git\index.lock
风险提示:只有确认没有 Git 进程运行时才删除。
19. bad index file sha1 signature / index file corrupt
现象
text
bad index file sha1 signature
fatal: index file corrupt
原因
Git 索引文件损坏,可能由异常关机、磁盘问题、工具中断导致。
解决方案
- 删除索引文件:
bash
rm .git/index
Windows PowerShell:
powershell
Remove-Item .git\index
- 重建索引:
bash
git reset
- 再检查状态:
bash
git status
20. unable to unlink old file / Permission denied
现象
text
unable to unlink old 'xxx': Permission denied
原因
文件被程序占用,Git 无法覆盖或删除。Windows 下常见。
解决方案
- 关闭占用文件的程序,如 IDEA、Node、Java 进程、终端、文件预览器。
- 检查杀掉相关进程。
- 重新执行 Git 操作。
- 如果是权限问题,以合适权限打开终端,但不要随意更改整个仓库权限。
21. Filename too long
现象
text
Filename too long
原因
Windows 路径长度限制导致 Git 无法检出长路径文件。
解决方案
启用 Git 长路径支持:
bash
git config --global core.longpaths true
同时建议:
- 将项目放在较短路径,如
E:\work\project。 - 避免深层嵌套目录。
- Windows 系统也可启用 Win32 长路径策略。
22. LF will be replaced by CRLF / CRLF will be replaced by LF
现象
text
warning: LF will be replaced by CRLF
warning: CRLF will be replaced by LF
原因
不同系统换行符不一致。
解决方案
Windows 常用:
bash
git config --global core.autocrlf true
Linux/macOS 常用:
bash
git config --global core.autocrlf input
团队更推荐使用 .gitattributes 统一:
text
* text=auto
*.sh text eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
23. 文件大小写改名不生效
现象
把 user.java 改为 User.java 后,Git 没有识别或其他系统出问题。
原因
Windows/macOS 默认文件系统大小写不敏感,Git 对大小写改名识别不稳定。
解决方案
使用中间名改两次:
bash
git mv user.java user_temp.java
git mv user_temp.java User.java
git commit -m "rename user.java to User.java"
24. working tree clean 但代码不是最新
现象
git status 显示干净,但代码不是远程最新。
原因
git status 只说明本地工作区干净,不代表已同步远程。
解决方案
bash
git fetch origin
git status -sb
git branch -vv
如果当前分支落后:
bash
git pull --rebase
25. 误删分支
现象
本地分支被删除,但其中有重要提交。
解决方案
- 查看 reflog:
bash
git reflog
-
找到删除前的 commitId。
-
重新创建分支:
bash
git switch -c recovered/branch <commitId>
如果远程分支还在:
bash
git fetch origin
git switch --track origin/<分支名>
26. 误 reset 或误 rebase 后想恢复
现象
执行 reset/rebase 后提交不见了。
解决方案
- 查看 reflog:
bash
git reflog
-
找到操作前的 commitId。
-
创建恢复分支:
bash
git switch -c recovered/before-reset <commitId>
- 确认内容后再合并或 cherry-pick。
27. tag already exists
现象
text
fatal: tag 'v1.0.0' already exists
原因
本地已经有同名 tag。
解决方案
查看 tag:
bash
git tag --list v1.0.0
如果本地 tag 错了,可删除本地 tag 后重建:
bash
git tag -d v1.0.0
git tag -a v1.0.0 -m "release v1.0.0"
如果远程也有同名 tag,谨慎处理:
bash
git push origin --delete v1.0.0
git push origin v1.0.0
风险提示:发布 tag 不建议随意移动,移动 tag 需要团队确认。
28. ambiguous argument
现象
text
fatal: ambiguous argument 'xxx': unknown revision or path not in the working tree
原因
Git 无法判断 xxx 是分支、tag、commit 还是文件路径,或该引用不存在。
解决方案
- 更新远程引用:
bash
git fetch --all
- 查看分支/tag 是否存在:
bash
git branch -a
git tag
- 如果是文件路径,加
--分隔:
bash
git log -- path/to/file
29. cannot delete branch checked out
现象
text
error: Cannot delete branch 'feature/xxx' checked out
原因
不能删除当前正在使用的分支。
解决方案
先切换到其他分支:
bash
git switch develop
git branch -d feature/xxx
如果未合并但确认要删除:
bash
git branch -D feature/xxx
30. The branch is not fully merged
现象
text
error: The branch 'feature/xxx' is not fully merged.
原因
要删除的分支有提交未合入当前分支。
解决方案
- 查看差异:
bash
git log --oneline 当前分支..feature/xxx
-
如果需要保留,先合并或 cherry-pick。
-
如果确认不需要,强制删除:
bash
git branch -D feature/xxx
31. submodule 目录为空或代码不对
现象
子模块目录为空,或不是期望版本。
原因
克隆时没有初始化 submodule,或子模块指针未更新。
解决方案
bash
git submodule update --init --recursive
如果需要拉取子模块远程最新:
bash
git submodule update --remote --recursive
32. 大文件无法推送
现象
text
remote: error: File xxx is larger than allowed size
原因
提交了超过平台限制的大文件。
解决方案
- 如果大文件还没推送,只在最近提交中:
bash
git rm --cached <大文件>
git commit --amend
- 添加到
.gitignore:
text
*.zip
*.jar
node_modules/
target/
- 如果必须管理大文件,使用 Git LFS:
bash
git lfs install
git lfs track "*.zip"
git add .gitattributes
git add <大文件>
git commit -m "track large file with lfs"
- 如果大文件已经进入历史并推送,需要用历史清理工具处理,操作前必须团队确认。
33. .gitignore 不生效
现象
已经加入 .gitignore,但文件仍出现在变更列表。
原因
文件已经被 Git 跟踪,.gitignore 只对未跟踪文件生效。
解决方案
从 Git 索引移除但保留本地文件:
bash
git rm --cached <文件路径>
目录:
bash
git rm -r --cached <目录路径>
然后提交:
bash
git add .gitignore
git commit -m "chore: update gitignore"
34. chmod/file mode 变化导致大量文件变更
现象
很多文件内容没变,但 Git 显示权限变化。
原因
跨系统或文件系统导致可执行位变化。
解决方案
关闭文件模式跟踪:
bash
git config core.filemode false
如果要全局设置:
bash
git config --global core.filemode false
35. Git pull 后出现很多 merge commit
原因
每次 git pull 默认使用 merge,远程有更新且本地也有提交时会生成 merge commit。
解决方案
个人功能分支可使用:
bash
git pull --rebase
也可配置默认 pull rebase:
bash
git config --global pull.rebase true
注意:共享分支是否允许 rebase 要按团队规范执行。
36. 推错分支
现象
本来要推到 feature 分支,却推到了 develop 或 main。
解决方案
如果错误提交还没合并、且目标分支允许 revert:
bash
git revert <commitId>
git push
如果是自己的远程 feature 分支推错名字:
bash
git push origin 正确本地分支:正确远程分支
如果已经污染共享分支,不要擅自 reset 或 force push,应先通知团队并确定处理方式。
37. 合错分支
现象
把 feature 合到了错误目标分支。
安全解决方案
如果已经产生 merge commit 并推送,使用 revert 撤销 merge:
bash
git revert -m 1 <mergeCommitId>
git push
说明:
-m 1表示保留 merge commit 的第一个父分支,即目标分支主线。- 适合撤销已推送的 merge。
如果没有推送,可按团队规范使用 reset,但要先确认没有他人基于该提交开发。
38. cherry-pick 后重复提交或冲突很多
原因
- 目标分支已经包含相同改动但 commitId 不同。
- cherry-pick 的提交依赖前置提交。
- 两边代码差异太大。
解决方案
- 检查目标分支是否已有类似提交:
bash
git log --oneline --grep="关键字"
-
只 cherry-pick 必要提交,按依赖顺序执行。
-
如果冲突太多,考虑合并整个分支或手动移植。
-
放弃本次 cherry-pick:
bash
git cherry-pick --abort
39. rebase 冲突反复出现
原因
rebase 会逐个重放提交,如果多个提交都改了同一区域,可能多次冲突。
解决方案
- 每次解决冲突后:
bash
git add <文件>
git rebase --continue
- 如果冲突过多,可放弃 rebase 改用 merge:
bash
git rebase --abort
git merge origin/develop
- 如果分支提交很多且杂乱,可先交互式整理提交,但共享分支慎用。
40. Git 操作被 IDEA 占用或显示异常
现象
- 命令行和 IDEA 显示状态不一致。
- IDEA 一直 indexing 或 Git refreshing。
- 文件锁定导致 Git 操作失败。
解决方案
- 等待 IDEA Git 刷新完成。
- 在 IDEA 中执行
File -> Synchronize。 - 关闭 IDEA 后再执行命令行 Git 操作。
- 必要时
File -> Invalidate Caches... -> Invalidate and Restart。 - 复杂冲突建议用命令行确认状态,再回 IDEA 处理具体文件。
41. 最安全的处理思路
遇到不确定问题时,按以下顺序处理:
- 先查看:
git status -sb。 - 先备份:
git stash push -u -m "backup"或新建临时分支。 - 再获取:
git fetch origin,不要一上来pull。 - 看图谱:
git log --oneline --graph --decorate --all -n 30。 - 确认当前分支、目标分支、远程地址。
- 能用
revert就不要在共享分支上用reset。 - 能用
--force-with-lease就不要用--force。 - 执行删除、覆盖、强推前,先和团队确认。
42. 常用恢复命令速查
| 场景 | 推荐命令 |
|---|---|
| 本地改动怕丢 | git stash push -u -m "backup" |
| 误删分支 | git reflog + git switch -c recovered <commitId> |
| 误 reset | git reflog + 新建恢复分支 |
| 合并冲突想放弃 | git merge --abort |
| rebase 冲突想放弃 | git rebase --abort |
| cherry-pick 想放弃 | git cherry-pick --abort |
| 已推送提交要撤销 | git revert <commitId> |
| 暂存错文件 | git restore --staged <文件> |
| 工作区文件改错且不要 | git restore <文件> |
| 远程引用脏了 | git remote prune origin |
| 远程比本地新 | git pull --rebase 或 git pull |