常见问题
安装与配置
›git status 显示的中文文件名是一串 \346\265\213 这样的乱码?
这是 Git 默认会对非 ASCII 字符进行转义。执行下面的命令关闭即可:
git config --global core.quotepath false›提示 “LF will be replaced by CRLF” 是什么意思?
这是换行符转换的提示。Windows 使用 CRLF,Linux/macOS 使用 LF。一般无需担心,推荐设置:
# Windows
git config --global core.autocrlf true
# macOS / Linux
git config --global core.autocrlf input团队项目最好在仓库中添加 .gitattributes 文件统一规则,例如 * text=auto eol=lf。
›提交时进入了一个看不懂的编辑器,怎么退出?
那通常是 Vim。按 Esc,然后输入 :wq 回车保存并退出;输入 :q! 回车则放弃并退出。
如果想换成 VS Code:
git config --global core.editor "code --wait"提交与撤销
›提交说明写错了,怎么修改?
如果是最后一次提交,且尚未推送:
git commit --amend -m "正确的提交说明"如果是更早的提交,使用 git rebase -i HEAD~N,把目标提交前的 pick 改为 reword。已推送的提交修改后需要强制推送,请谨慎操作。
›如何撤销最近一次提交?
- 还没推送,想保留修改:
git reset --soft HEAD~1 - 还没推送,想彻底丢弃:
git reset --hard HEAD~1 - 已经推送:
git revert HEAD,它会生成一个新提交来抵消修改,不会改写历史。
›错误的代码已经推送到远程了,怎么办?
如果分支是多人共享的,推荐使用 revert:
git revert <提交哈希>
git push如果是只有你自己使用的分支,可以 reset 后强制推送:
git reset --hard HEAD~1
git push --force-with-lease›不小心执行了 git reset --hard,代码还能找回吗?
只要之前提交过,基本都能找回:
git reflog
# 找到 reset 之前的那条记录,比如 HEAD@{1}
git reset --hard HEAD@{1}但从未提交、也从未 git add 过的修改无法通过 Git 找回。
›已经提交的文件,加入 .gitignore 后还是被跟踪?
.gitignore 只对未跟踪的文件生效。需要先把它从暂存区移除:
git rm --cached <文件>
# 目录使用 -r
git rm -r --cached node_modules
git commit -m "停止跟踪"›把密码或密钥提交到了公开仓库,怎么补救?
第一步:立即更换或吊销该密钥,这是最重要的。
第二步:从历史中彻底清除,推荐使用 git filter-repo:
git filter-repo --path secrets.json --invert-paths
git push --force --all之后通知所有协作者重新克隆仓库。
分支与合并
›merge 和 rebase 应该用哪个?
- merge 保留真实的分支历史,不改写已有提交,适合合并公共分支;
- rebase 让历史保持线性、整洁,但会改写提交,只适合用于尚未推送或只有自己使用的分支。
一个常见的实践是:拉取时用 git pull --rebase,功能完成后通过 Pull Request 合并到主分支。
›遇到合并冲突怎么解决?
- 用
git status找到冲突文件; - 打开文件,找到
<<<<<<<、=======、>>>>>>>标记,保留正确内容并删除标记; git add <文件>标记为已解决;git commit(合并)或git rebase --continue(变基)。
想放弃可以执行 git merge --abort 或 git rebase --abort。
›代码提交到了错误的分支,怎么移过去?
假设本应提交到 feature,却提交到了 main(尚未推送):
# 记下提交哈希,然后在 main 上撤销
git reset --hard HEAD~1
# 切到正确的分支并应用
git switch feature
git cherry-pick <提交哈希>如果 feature 分支还不存在,更简单:先 git branch feature,再在 main 上 git reset --hard HEAD~1。
›master 和 main 有什么区别?
没有功能上的区别,只是默认分支的名字不同。2020 年后 GitHub、GitLab 等平台把新仓库的默认分支改为了 main。可以设置 Git 的默认初始分支名:
git config --global init.defaultBranch main把已有仓库的 master 改名为 main:
git branch -m master main
git push -u origin main然后在托管平台上把默认分支改为 main,再删除远程的 master。
远程仓库
›push 时提示 rejected / non-fast-forward?
说明远程有你本地没有的新提交。先拉取再推送:
git pull --rebase
git push不要随意使用 git push --force,那会覆盖别人的提交。
›推送到 GitHub 提示 Authentication failed / 需要密码?
GitHub 已不支持使用账号密码进行 Git 操作。可以:
- 在 GitHub 创建 Personal access token,推送时用它代替密码;
- 或改用 SSH 方式:生成密钥
ssh-keygen -t ed25519,把公钥添加到 GitHub,然后:
git remote set-url origin [email protected]:用户名/仓库.git›Fork 的仓库如何与原仓库保持同步?
git remote add upstream <原仓库地址>
git fetch upstream
git switch main
git merge upstream/main
git push origin mainGitHub 网页上也提供了 “Sync fork” 按钮。
›推送时提示文件太大(超过 100MB)?
GitHub 限制单个文件不超过 100MB。解决方法:
- 如果文件不需要进入版本控制,从提交中移除并加入 .gitignore;
- 如果需要,使用 Git LFS 管理大文件;
- 如果大文件已经在历史中,需要用
git filter-repo --strip-blobs-bigger-than 100M清理历史。