Git中文社区

常见问题

安装与配置

›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"
›从 GitHub 克隆仓库非常慢,怎么办?

可以尝试以下方法:

  1. 浅克隆,只下载最新版本:git clone --depth 1 <地址>;
  2. 把仓库导入 Gitee 后再从 Gitee 克隆;
  3. 如果有可用的代理,只为 GitHub 设置代理:
git config --global http.https://github.com.proxy http://127.0.0.1:7890

更多代理技巧与 SSH 代理配置,请参阅代理设置教程或使用代理设置向导。

提交与撤销

›提交说明写错了,怎么修改?

如果是最后一次提交,且尚未推送:

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 合并到主分支。

›遇到合并冲突怎么解决?
  1. 用 git status 找到冲突文件;
  2. 打开文件,找到 <<<<<<<、=======、>>>>>>> 标记,保留正确内容并删除标记;
  3. git add <文件> 标记为已解决;
  4. 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
›pull 时提示 refusing to merge unrelated histories?

这通常是因为本地仓库和远程仓库是分别初始化的(例如在平台上建仓库时勾选了 README)。如果确认要合并:

git pull origin main --allow-unrelated-histories
›Fork 的仓库如何与原仓库保持同步?
git remote add upstream <原仓库地址>
git fetch upstream
git switch main
git merge upstream/main
git push origin main

GitHub 网页上也提供了 “Sync fork” 按钮。

›推送时提示文件太大(超过 100MB)?

GitHub 限制单个文件不超过 100MB。解决方法:

  1. 如果文件不需要进入版本控制,从提交中移除并加入 .gitignore;
  2. 如果需要,使用 Git LFS 管理大文件;
  3. 如果大文件已经在历史中,需要用 git filter-repo --strip-blobs-bigger-than 100M 清理历史。