Git 常见问题

Git 访问 GitHub 速度过慢

现象:git clonegit push 速度极低,只有十几 KB/s,经常超时失败。

根因:不一定是 github.com 本身解析失败。常见情况是 CDN 域名(如 github.global.ssl.fastly.net)解析到海外节点、访问差,或本机 DNS 结果不稳定。硬编码进 hosts 的 IP 会过期,写入前要重新查询。

方案 1:修改本地 hosts 映射

原理:浏览器、Git 访问域名时,优先读本机 hosts 获取 IP;没有记录才向 DNS 查询。可以手动写入域名与 IP 的映射,绕过公共 DNS。

  • 用 DNS 查询网站(例如 ipaddress.com)或站长工具,查询就近 IP:github.global.ssl.fastly.netgithub.com
  • 修改 hosts:Windows 为 C:\Windows\System32\drivers\etc\hosts(需管理员权限);macOS、Linux 为 /etc/hosts。在文件末尾追加记录。
  • 刷新本机 DNS 缓存:Windows 用 ipconfig /flushdns;macOS 用 sudo dscacheutil -flushcache
# IP 只是示例,以你查询到的为准
199.232.69.194 github.global.ssl.fastly.net
140.82.113.4 github.com

备注:改对之后,速度有机会从约 10 KiB/s 提升到 100 KiB/s 以上。IP 失效就再查、再改。

方案 2:使用 GitHub 镜像地址

# 原始地址
git clone https://github.com/xxx/xxx.git

曾经流行的 https://github.com.cnpmjs.org/xxx/xxx.git 已于 2022 年停用(维护方因钓鱼风险认定而关闭)。第三方加速域名更换频繁,也有仿冒站点,不要把过期地址写进脚本。更稳妥的是方案 1、方案 4,或改用 SSH(见下文)。

方案 3:调整 HTTP 传输缓存 http.postBuffer

适用场景:大文件推送、大仓库 clone,HTTPS 推送卡在 chunked 传输或被代理拒掉。

# 缓冲区 10MB,单位字节:10 * 1024 * 1024
git config --global http.postBuffer 10485760

原理:http.postBuffer 默认约 1 MiB。POST 超过这个大小时,Git 会改用 HTTP/1.1 的 Transfer-Encoding: chunked。部分代理、网关不支持 chunked,推送就会失败。把缓冲区调大,尽量一次发完、少走 chunked。不要设得过大,会明显增加内存占用。

方案 4:Git 配置代理

代理分全局和仅针对 GitHub;这些配置只作用于 HTTP、HTTPS,SSH 不受影响

本地代理端口以你的软件为准,下面 1080 只是示例。连本机 HTTP 代理时,http.proxyhttps.proxy 一般都写 http://127.0.0.1:端口(用 CONNECT 隧道),不要写成 https://127.0.0.1。SOCKS 代理用 socks5://127.0.0.1:端口

  1. 全局代理(不推荐,国内 Git 仓库也会走代理,往往更慢)
git config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy http://127.0.0.1:1080
  1. 推荐:只给 GitHub 配代理,不影响其他仓库
git config --global http.https://github.com.proxy http://127.0.0.1:1080
git config --global https.https://github.com.proxy http://127.0.0.1:1080
  1. 清除代理配置
git config --global --unset http.proxy
git config --global --unset https.proxy
git config --global --unset http.https://github.com.proxy
git config --global --unset https.https://github.com.proxy

Git Bash 中文乱码问题

乱码主要来自三处:Git 配置、Bash 终端编码、系统文件编码。

git status 中文文件名显示八进制转义

现象:git status 里中文文件名变成 \345\255\246 这类转义。

原因:core.quotepath 为 true 时,Git 对非 ASCII 路径做 C 风格转义。

git config --global core.quotepath false

也可以直接改 .gitconfig

[core]
    quotepath = false

git log 日志中文乱码

修改全局配置:

git config --global gui.encoding utf-8
git config --global i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8

Git Bash 终端是 GBK 时(见下文把 Character set 改成 GBK),把最后一项改成 gbk,并与终端编码一致。

对应配置文件片段:

[gui]
    encoding = utf-8
[i18n]
    commitencoding = utf-8
    logoutputencoding = utf-8
[svn]
    pathnameencoding = utf-8

修改 Git Bash 的 profile:%GIT_HOME%\etc\profile,末尾追加:

export LESSCHARSET=utf-8

vim、vi 查看文件中文乱码

编辑 %GIT_HOME%\share\vim\vimrc,文件末尾追加:

set fileencodings=utf-8,ucs-bom,cp936,big5
set fileencoding=utf-8
set termencoding=gbk

termencoding=gbk 面向 GBK 终端;终端是 UTF-8 时改成 utf-8

终端输入中文乱码

编辑 %GIT_HOME%\etc\inputrc,末尾增加:

set output-meta on
set convert-meta off

ls 命令输出中文文件名乱码

不要改 etc/git-completion.bash(升级 Git 会被覆盖,也不是放别名的地方)。写到 Git Bash 的 etc/bash.bashrc 或用户 ~/.bashrc

alias ls='ls --show-control-chars --color=auto'

ipconfig、systeminfo 等 Windows 命令输出乱码

原因:这些工具输出 GBK,Git Bash 窗口默认按 UTF-8 解,对不上。

解决:Git Bash 窗口右键 → OptionsTextLocale 设为 zh_CNCharacter set 设为 GBK

注意:改成 GBK 后,UTF-8 文件名又会乱。只能按当前任务切换编码,没有一劳永逸的方案。

GitHub SSH 密钥配置

SSH(Secure Shell)是加密远程协议。配好密钥后,用 SSH 地址访问 GitHub 不必反复输入账号密码。只对 git@github.com:... 这类地址生效,和 HTTPS 互不通用。

检查本机是否已有 SSH 密钥

# 查看 ~/.ssh 下的密钥。常见公钥:id_ed25519.pub、id_rsa.pub
ls -al ~/.ssh

生成 SSH 密钥对

GitHub 推荐 Ed25519;RSA 仍可用,长度用 4096。

# 推荐
ssh-keygen -t ed25519 -C "your_email@example.com"

# RSA
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

参数说明:

  • -t:算法,ed25519rsa
  • -b:位数,RSA 用 4096;Ed25519 不用这个参数
  • -C:注释,一般填注册邮箱
  • -f:自定义保存路径

提示保存路径时直接回车用默认。然后可以设密钥密码(可选;设了之后每次解锁密钥要输入密码,更安全)。

将私钥交给 ssh-agent 管理

ssh-agent 保管已解锁的私钥,避免每次操作都输入密钥密码。

# Windows Git Bash 启动 agent
eval $(ssh-agent -s)

# 把私钥加进 agent,文件名换成你的(Ed25519 默认是 id_ed25519)
ssh-add ~/.ssh/id_ed25519
ssh-add ~/.ssh/id_rsa

公钥配置到 GitHub 账号

  1. 复制公钥(只复制 .pub,不要把没有 .pub 的私钥发出去
# macOS
pbcopy < ~/.ssh/id_ed25519.pub

# Windows Git Bash
clip < ~/.ssh/id_ed25519.pub

也可以直接打开 ~/.ssh/id_ed25519.pub 复制。RSA 则把文件名换成 id_rsa.pub

  1. GitHub 网页:头像 → SettingsSSH and GPG keysNew SSH key
  2. Title 填备注,把完整公钥粘贴进去,保存。

测试 SSH 连通 GitHub

ssh -T git@github.com

首次连接会提示核对主机指纹,类似:

The authenticity of host 'github.com (IP ADDRESS)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

核对须与 GitHub 官方公布的指纹 一致,再输入 yes。GitHub 在 2023 年更换过 RSA 主机密钥,网上旧教程里的 nThbg6kX... 已经作废。当前官方指纹:

  • RSA:SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s
  • ECDSA:SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM
  • Ed25519:SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU

连接成功会看到:

Hi xxx! You've successfully authenticated, but GitHub does not provide shell access.

修改已有私钥的密码

不必重新生成密钥对:

ssh-keygen -p

按提示输入私钥路径、旧密码、新密码。

给 SSH 密钥设密码:本机密钥泄露后,没有密码也用不了。ssh-agent 会缓存已解锁的密钥,日常开发不用反复输入。

merge 与 rebase 的区别

二者都是把一个分支的改动并到另一个分支,但实现、历史形态和风险不同。

git merge

语法:当前在 A 分支,执行 git merge B

  • 三方合并:A 的 HEAD、B 的 HEAD、二者共同祖先,对比两边相对祖先的差异。
  • 同一位置两边都改了,就要手解冲突。
  • 不能快进时,会生成新的合并提交两边原有提交都还在,历史呈网状。若 B 已经是 A 的祖先,默认快进,只移动指针,不产生合并提交。

优点:

  • 原始提交都在,好追溯、好回滚。
  • 不改已有 commit 的哈希。

缺点:频繁合并会让历史分叉多,日志里出现大量合并提交。

git rebase(变基)

不要在已经推送、多人共用的分支上 rebase。 只用于本地还没推、或只有你在用的分支(若已推过,需要 --force-with-lease 且所有人都知情)。

语法:当前在 A 分支,执行 git rebase B

  • 把 A 上独有的提交摘下来,接到 B 的最新提交后面,逐个重放。
  • 冲突按每一个提交解,不是 merge 那样一次解完。
  • 完成后这些提交会有新的哈希,历史变成一条线。

优点:历史干净、线性,适合整理自己的本地分支。

缺点:

  • 重写历史、改变哈希;公共分支 rebase 再强推,别人基于旧哈希的工作会对不上。
  • 冲突要逐次处理,量大时更烦。
  • 原来的分叉交汇痕迹没了。

小结

  • merge:保留历史,允许分叉,适合公共分支协作;
  • rebase:重写历史,抹平分叉,适合本地私有分支整理。

git pull、git fetch、git remote update

  • git pull:取回远程更新并合并进当前分支。默认等价 git fetch + git merge FETCH_HEAD;若配置了 pull.rebase,则是 fetch + rebase。会改工作区,容易产生冲突。
  • git fetch:下载远程分支的新提交,不合并。只更新远程跟踪引用(如 origin/main),工作区不动。适合先看再合并。
  • git remote update:更新已配置的全部远程的跟踪分支,不合并。多个 remote 时好用。
# 取 origin 上各分支的最新提交,不合并
git fetch

# 指定远程
git fetch origin

# 只取指定分支
git fetch origin main

# 把远程 main 写到本地新建(或更新)temp 分支,不切换
git fetch origin main:temp

git reset 与 git revert

两者都能撤销提交,但对历史的影响不同。

git reset

直接移动 HEAD(当前分支指针),指定位置之后的提交从 git log 里消失,git reflog 里暂时还能找到。

reset 改历史,只适合尚未推到远程的提交。已经在公共分支上的提交不要 reset 再 git push --force,会覆盖别人基于旧历史的工作。

git revert

不删旧提交,再生成一条反向提交,抵消目标提交的改动。整条历史还在。

适合已经推到公共分支的回滚,普通 git push 即可,不必强制推送。

例如提交链 ... → A → B,要去掉 B 的改动:

  • git reset A:历史变成 ...→A,B 丢掉;
  • git revert B:历史变成 ...→A→B→C,C 的内容效果回到 A。

注意:revert 掉一次合并提交之后,再 merge 同一条源分支,那些被撤销的改动不会自动回来。

解决:把这条 revert 再 revert 一次,或在源分支上制造新提交(cherry-pick、squash 后再提交)。

Git 换行符问题

  • Linux、macOS:LF\n
  • Windows:CRLF\r\n

跨平台协作时让 Git 做换行转换,避免满仓库「整文件都改了」其实只是换行符。

# Windows:检出成 CRLF,提交时转回 LF
git config --global core.autocrlf true

# Linux、macOS:提交时把 CRLF 收成 LF,检出不主动改成 CRLF
git config --global core.autocrlf input

参数:

  • true:检出 CRLF,提交 LF;Windows 常用
  • input:只在提交时标准化为 LF;Linux、macOS 常用
  • false:不转换,文件里是什么就是什么;跨平台仓库容易把换行差异提交上去

常见报错处理

报错 1:fatal: Could not read from remote repository.

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

现象:SSH 访问 GitHub 失败,测试连接提示 22 端口超时。

ssh: connect to host github.com port 22: Connection timed out

根因:本机网络或防火墙拦了 SSH 默认 22 端口。

解决:编辑 ~/.ssh/config(没有就新建),让 GitHub 的 SSH 走 443:

Host github.com
    HostName ssh.github.com
    User git
    Port 443

原理:GitHub 在 ssh.github.com:443 上提供 SSH,多数网络放行 443。

报错 2:packet_write_wait: Connection to xxx port 22: Broken pipe

remote: Enumerating objects: 283, done.
remote: Counting objects: 100% (283/283), done.
remote: Compressing objects: 100% (18/18), done.
packet_write_wait: Connection to 13.229.188.59 port 22: Broken pipe
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

现象:git pushgit pull 大仓库时,SSH 中途断开。

根因:会话长时间看起来空闲,被防火墙或 NAT 掐掉。

解决:改本机 ~/.ssh/config,让客户端发保活包。ClientAliveCountMaxsshd 服务端配置,写在自己电脑的 ssh 客户端配置里无效。

Host *
    # 每 60 秒发一次保活
    ServerAliveInterval 60
    # 连续 3 次无响应再断开
    ServerAliveCountMax 3

参考资料

Checking for existing SSH keys(GitHub Docs)

GitHub 的 SSH 指纹

git-config 官方文档

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-09-03 01:55:15

results matching ""

    No results matching ""