☰
Git安装与配置全攻略:从环境搭建到SSH认证与高频疑难排查
2026/10/9 10:41:43 网站建设 项目流程

最近好几个朋友来问我 Git 安装的事情,每次我都是同一句话:装 Git 本身很简单,真正麻烦的是装完之后那一堆配置和使用习惯。很多人照着网上的教程装完,git --version也出来了,结果一上手就撞墙——SSH 认证失败、换行符把整个文件搞出上千行 diff、提交大文件被远端拒绝、明明写了.gitignore却还在跟踪一堆不该跟踪的文件。这些坑我几乎全部踩过一遍,而且可以说,大部分问题不是出在“用”的时候,而是出在“装”和“配”的环节。

这篇就按我自己实际操作的顺序走一遍:先把 Git 解决什么问题讲清楚,再分平台过安装细节,然后是装完必做的四件事,最后是日常高频命令和疑难杂症排查。不管你用的是 Windows、macOS 还是 Linux,都能照着做。文章里的选项、命令、排查思路都是真实项目里验证过的,不是从文档里抄出来的。

1. 装 Git 之前:先弄明白它到底解决什么问题

1.1 没有版本控制的日子是什么样

我说个真实场景。以前团队里有人用 SVN,有人直接用文件夹备份,项目目录里一堆final_v1、final_v2、最终版、真的最终版。到了上线前一天,谁都不知道哪个文件是新的。更惨的是两个人同时改一个文件,后保存的人把先保存的人的工作覆盖掉,改了半天的工作说没就没。

这不是个别现象。只要代码量超过一个“能记进脑子里”的量级,靠人工管理版本一定会出错。Git 解决的就是这件事:它给每一次改动拍一张快照,哪天改崩了,一条命令就能回到任意历史节点。团队里每个人各自改各自的,最后合并,冲突了也能看到双方改了什么,而不是互相覆盖文件。

另外一个容易被忽视的价值是追踪“为什么”。git log里每一行提交都带作者、时间和提交说明。我后来做项目复盘、排查线上 bug,很多线索就是从提交历史里翻出来的。没有版本控制,这些信息基本靠人脑记忆,时间一长就没了。

1.2 Git 的几个关键概念,用大白话讲

如果你第一次接触 Git,别上来就背命令,先把几个概念过一遍,后面所有操作都围绕它们转。

  • 工作区:你电脑上能看到的那些文件。
  • 暂存区:一个临时存放改动的地方,相当于“准备提交的清单”。git add就是把改动放进清单里。
  • 本地仓库:你电脑上.git目录里保存的完整历史,每次git commit就是往这个历史里写一个快照。
  • 远程仓库:托管在 GitHub、Gitee 或公司服务器上的仓库副本,用来多人协作和备份。git push是往远程传,git pull是从远程拉。
  • 分支:可以在同一条时间线上分出另一个平行的开发线,互不影响,最后再用git merge合回来。生活化理解就一句话:分支是平行世界,合并是把两个平行世界的结果整合成一个。

Git 是分布式的,意思是每个人本地的仓库都包含全部分支的全部历史,不联网也能看提交记录、也能做提交。这一点和 SVN 那种必须连服务器的集中式版本控制完全不同。装完 Git 之后,你实际上是在自己电脑上拥有了一整套完整的历史数据库。

1.3 你的使用场景决定了安装选项

安装 Git 之前,先想清楚你接下来大概会在什么场景里用它。我一般把用户分成三类:

  • 纯单机使用:只是自己写代码、存版本,不连远程仓库。这种情况安装向导里大部分选项默认就可以。
  • 配合 GitHub / Gitee 使用:需要配置 SSH 密钥、远程仓库关联、凭据管理,后面第 3 章的配置基本都要做。
  • 配合 IDE 使用:很多人用 IntelliJ IDEA、VS Code 内置的 Git 功能。IDE 本质上是调用命令行的 Git,所以安装时 PATH 环境变量必须选对,否则 IDEA 里会报“Can't use Git”之类的问题。

这篇文章按最常见的组合来讲:Windows 或 macOS 本机 + Git Bash 命令行 + GitHub/Gitee 远程仓库 + IDEA 图形界面辅助。安装的时候多花两分钟把选项选对,后面能省下半天折腾时间。

2. Windows / macOS / Linux 三平台安装实操

2.1 Windows:官网下载与安装选项逐个选明白

Windows 安装 Git 我推荐只从官网下载,不要从各种“软件园”下载站拿,那些打包版本经常会捆绑垃圾软件或者改环境变量。打开 git-scm.com,首页会自动识别你的系统,直接点下载 64-bit Git for Windows Setup 就行。

安装向导里真正需要动脑子的选项就那么几个,我逐个说一遍。

安装路径:默认是C:\Program Files\Git,一般不用改。如果你的电脑有权限限制,或者就是不喜欢路径里带空格,可以改成C:\Git,但要注意改成短路径后后续 PATH 也要跟着变。

Select Components(选择组件):这里建议把Git Bash Here和Git GUI Here都勾上。这两个选项会在右键菜单里加上入口,在文件夹里右键就能直接打开 Git Bash 或者图形提交界面,后面用起来非常顺手。.gitignore模板那个选项作用不大,无所谓选不选。

Default branch name(默认分支名):新版本安装向导会让你选默认分支名,推荐改成本地默认分支名为main。当然如果你公司里所有仓库都用master,那也可以保持一致,这个纯看团队习惯,不用纠结。

Adjusting your PATH environment(PATH 环境变量):这一步是新手踩坑最多的。三个选项分别是:

  • Use Git from Git Bash only:只在 Git Bash 里能用 git 命令,cmd 和 PowerShell 里用不了。不推荐,因为后面用 IDEA 时可能找不到 Git。
  • Git from the command line and also from 3rd-party software:命令行和第三方软件都能用 git,这是官方推荐也推荐选这个。
  • Use Git and optional Unix tools from Command Prompt:除了 git,还把一堆 Unix 工具(比如find、sort)塞进 cmd,有概率覆盖 Windows 自带同名命令,不建议。

换行符处理方式:这个选项我单独用一个小节讲,因为它影响面特别大。

Windows 默认文本换行是 CRLF(回车+换行),而 Linux/macOS 用的是 LF(只有换行)。如果不做转换,同一个文件在不同平台上打开,Git 会认为文件内容变了。安装向导里三个选项:

  • Checkout Windows-style, commit Unix-style line endings(默认):检出时转成 CRLF,提交时转成 LF。适合在 Windows 上开发、团队跨平台的场景。
  • Checkout as-is, commit as-is:不转换。适合单平台项目,但跨平台协作容易产生换行符差异。
  • Checkout Unix-style, commit Unix-style:检出和提交都用 LF。适合你明确知道服务器和队友全是 Linux 的场景。

实测下来,绝大多数情况用默认的第一个选项最稳。等你理解了换行符原理之后,再根据团队实际改也行。我见过有人选了第二个选项,结果同事在 macOS 上拉下来,整个文件 diff 全是红色的,其实就是换行符不一致导致的。

剩下的终端模拟器选项默认选 MinTTY 就行,它比 Windows 自带控制台好用。Credential Manager 保持勾选,后面用 HTTPS 协议推送时,它会帮你在系统里记住凭据,实现免密。全部选项确认后,安装完成,在开始菜单里能找到 Git Bash、Git CMD、Git GUI 三项。

想省事的读者也可以用 Windows 包管理器直接一行安装,适合习惯命令行的场景:

winget install --id Git.Git -e --source winget

装完同样建议按 2.4 节验证一下。

2.2 macOS:两条路选一条

macOS 上装 Git 有两种主流方式,我都试过。

第一种是安装 Xcode Command Line Tools,苹果官方提供的命令行工具包。在终端里执行:

xcode-select --install

它会弹窗提示安装,等一段时间就装好了,里面自带 git。好处是和系统集成度高,坏处是版本可能比较旧,有些新特性用不了。如果你只是偶尔用一下 Git,这条路足够。

第二种是用 Homebrew 安装,适合想长期用、想保持最新版的人:

brew install git

装完可以用which git确认一下路径。比较老的 brew 环境会装在/usr/local/bin/git,Apple Silicon 的 Mac 装在/opt/homebrew/bin/git。如果发现which git出来的是系统自带的路径,检查一下 PATH 顺序,保证 brew 的 bin 目录排在系统路径前面。

有些公司电脑没有管理员权限,brew install可能会失败,这时候可以直接去官网下载 macOS 安装包(git-scm.com/download/mac),图形化安装完就能用,不需要 sudo 权限。

2.3 Linux:包管理器一行命令搞定

Linux 是 Git 的老家,安装基本就是一条命令的事。Debian/Ubuntu 系:

sudo apt update && sudo apt install git -y

CentOS/RHEL 7 及以前用 yum,8 及以后用 dnf:

# CentOS 7 sudo yum install git -y # CentOS 8+ sudo dnf install git -y

需要注意,系统自带的包管理器版本可能偏老。比如 Ubuntu 20.04 仓库里的 Git 可能是 2.25 左右,而最新版已经到 2.4x 了。对于绝大多数开发场景,仓库自带版本完全够用。如果确实需要新版,那就走编译安装,但编译之前要装好依赖:autoconf、curl-devel、expat-devel、gettext-devel、openssl-devel这些。实际体验下来,为追新版本去编译安装性价比很低,除非你有明确的功能需求。

2.4 安装完先跑这三个命令确认

不管哪个平台,装完都建议依次执行三个命令,确认安装没问题:

git --version

这条命令出来类似git version 2.xx.x.windows.x,说明核心安装没问题。

# Windows 用 where git,macOS/Linux 用 which git where git # 或者 which git

这条确认 Git 的可执行文件在哪里,也能看出 PATH 环境变量是否生效。如果提示找不到 git,多半是 PATH 没配置好或者终端窗口没重开。

git config --list

这条列出当前生效的配置。这时大概率是空的,因为还没设置过任何东西,能看到几条默认值也正常。接下来就进入可用的第一步——配置。

3. 安装后必做的四件事:账号、密钥、换行符、默认分支

3.1 配置用户名和邮箱,commit 才有人认领

很多人装完 Git 直接就开始提交,结果遇到这个报错:

Author identity unknown *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name"

Git 的每次提交都必须记录作者是谁,不设置就只能一直卡壳。按照提示执行:

git config --global user.name "你的名字" git config --global user.email "你的邮箱"

这里有两件容易被忽略的小事。

第一,邮箱尽量用你注册 GitHub/Gitee 时用的邮箱,这样提交记录能和你账号对上。GitHub 对提交邮箱还有隐私保护策略,用 noreply 邮箱也可以,看个人偏好。

第二,--global参数意味着这个配置对当前电脑上的所有仓库生效。配置优先级是:仓库内的.git/config>--global全局配置 > 系统级配置。如果你在某些特定仓库里需要用不同身份(比如个人仓库和公司仓库分开),可以不带--global,在那个仓库目录里单独执行一遍。查看当前生效的完整配置:

git config --list

修改的话直接重新执行设置命令覆盖,想删除某一项把参数换成--unset就行。

3.2 SSH 密钥配置:实现免密推送的核心

用 HTTPS 协议访问远程仓库当然可以,但每次 push 都要输用户名和密码或令牌,很烦。更优雅的方案是配置 SSH 密钥,配置好后推送拉取完全免密。

生成密钥的推荐算法是 Ed25519,比传统的 RSA 短、快、安全。在 Git Bash 或终端里执行:

ssh-keygen -t ed25519 -C "你的邮箱"

一路回车就行。默认会生成在~/.ssh/id_ed25519和~/.ssh/id_ed25519.pub。

查看公钥内容,把整段复制出来。Windows 下可以这样:

clip < ~/.ssh/id_ed25519.pub

macOS 下:

pbcopy < ~/.ssh/id_ed25519.pub

然后去平台添加:

  • GitHub:右上角头像 → Settings → SSH and GPG keys → New SSH key。
  • Gitee:设置 → 安全设置 → SSH 公钥。

把复制的内容粘贴进去,标题随意。添加完之后测试连接:

ssh -T git@github.com

看到类似Hi xxx! You've successfully authenticated的提示,就说明连接通了。Gitee 对应的测试命令是ssh -T git@gitee.com。

如果你同时用 GitHub、Gitee 还有公司内网 GitLab,同一个密钥放多个平台是可以的,一个公钥可以添加在多个平台上。但如果你的公司内网服务器不支持 Ed25519 算法,那就生成一个 RSA 密钥备用:

ssh-keygen -t rsa -b 4096 -C "你的邮箱"

还有一种情况是电脑上有多组密钥(比如个人电脑和公司电脑、不同平台用不同密钥),这时候需要写~/.ssh/config来做区分。我自己的配置大致长这样:

Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519_gitee

写好之后,对不同的 Host 会自动使用对应的密钥,不用手动切换,非常省事。实测中 80% 的“SSH 认证失败”问题都出在密钥没配置好或者多密钥指向错误上,后面第 5 章会专门讲排查步骤。

3.3 全局配置建议:换行符和中文显示

除了用户名和邮箱,建议顺手做几项全局配置,都是日常使用中真实踩过坑后的经验。

换行符配置取决于你的平台:

# Windows 上推荐 git config --global core.autocrlf true # macOS/Linux 上推荐 git config --global core.autocrlf input

core.autocrlf true的含义是:检出代码时自动把 LF 转成 CRLF,提交时自动把 CRLF 转回 LF。这样做的好处是,你在 Windows 上编辑代码、其他队友在 macOS/Linux 上编辑代码,仓库里存的始终是 LF,不会出现“整文件被判定为改动”的尴尬。input的含义是:提交时把 CRLF 转成 LF,但检出时不主动转,保持原本内容。

再执行一条很实用的配置:

git config --global core.quotepath false

这是让中文文件名和中文路径正常显示。Git 默认会把非 ASCII 字符转义成\xxx的八进制格式,打开这条配置后,git status里就能直接看到中文文件.md而不是一串转义字符。这个问题在 Windows 上尤其常见,不做配置的话,看到中文文件名全是乱码。

还有两条建议顺手配掉:

git config --global init.defaultBranch main git config --global push.default simple

init.defaultBranch main让新仓库默认分支名是main,省得每次还要手动改分支名。push.default simple是 Git 2.0 之后的默认安全行为,只推送当前分支到同名的远程分支,避免误推所有分支。

3.4 关联远程仓库:把本地代码推到 GitHub / Gitee

本地仓库和远程仓库关联的核心命令是git remote。先在 GitHub 或 Gitee 上新建一个空仓库(不勾选 README、.gitignore 那些初始化文件,免得历史不干净),复制仓库的 SSH 地址,然后执行:

git remote add origin git@github.com:你的用户名/仓库名.git

origin只是远程仓库的默认名字,约定俗成,你也可以叫别的名字,但建议保持默认。

关联之后,推送本地代码:

git branch -M main git push -u origin main

第一条把当前分支重命名为main(如果还没改的话),第二条推送并建立远程分支的关联关系。加上-u之后,以后在这个分支上直接git push、git pull就可以了,不用每次写全远程名和分支名。

查看关联情况:

git remote -v

这里会出现两个地址,一个 fetch 一个 push,内容一样。如果你看到的是 HTTPS 地址,说明之前用的是 HTTPS 协议。两种协议可以混用,但日常体验差别明显。我也顺便说明一下热词里常见的“git 设置代码库 token”:如果用 HTTPS 方式,现代 Git 支持用 personal access token 代替密码,第一次 push 时输入一次 token,凭据管理器会记住,之后也免密。但对比之下,SSH 密钥配置一次长期有效,体验更干净。我的建议是统一用 SSH。

4. 日常高频操作:从第一次提交到分支合并

4.1 完整走一遍提交流程

假设你现在有一个新项目目录,里面有代码文件,第一次想用 Git 管理起来。进入项目目录后执行:

git init

这条命令会创建.git目录,本地仓库就建立起来了。然后看一下当前状态:

git status

这时会显示一堆未跟踪的文件。初次提交前先暂存再提交,是 Git 最基本也最重要的使用习惯。执行:

git add README.md git add src/

git add的作用是把改动放进暂存区。为什么不能直接提交工作区的所有文件?因为暂存区允许你只提交一部分改动,比如这个文件内容还没写完,可以先把另一个文件单独提交,这样历史记录更干净。我之前见过有人只用git add .一把梭,结果把临时文件、密钥、构建产物全都提交进去了,后面清理非常痛苦。

确认暂存内容没问题后提交:

git commit -m "init: 添加项目初始代码"

提交信息要写清楚,这一点再怎么强调都不过分。我自己写提交信息的原则是:别人看这条信息就能知道这次改动解决了什么问题。比如fix: 修复登录接口返回码错误就比update好一百倍。查看历史:

git log --oneline --graph

带--graph可以看到分支图形,提交历史像一棵树一样展开,直观理解“分支”是怎么回事。

日常开发中我推荐形成一个肌肉记忆:改完代码先git status看看改了哪些文件,再git diff确认具体改动内容,没问题再git add和git commit。很多人直接提交,等 push 之后才发现把调试用的日志代码也提交上去了,还得再补一个 revert,纯属多绕了一圈。

4.2 分支、合并与冲突处理

分支是 Git 最核心的能力之一。开一个新分支开始开发,不影响主分支上的稳定代码。创建并切换分支:

git switch -c feature/login

这条命令相当于git branch feature/login加git checkout feature/login两步。Git 2.23 之后推荐用git switch,语义更清晰。切回主分支用:

git switch main

在新分支上提交若干改动之后,切回主分支,把新分支合并进来:

git merge feature/login

如果两个分支改的是同一文件的同一区域,Git 会报冲突。冲突文件里会出现这样的标记:

<<<<<<< HEAD 这是主分支的版本 ======= 这是 feature/login 分支的版本 >>>>>>> feature/login

处理方式很朴素:打开文件,把这几个标记行删掉,手动保留下你要的最终内容,然后git add这个文件,再git commit完成合并提交。

关于git merge和git rebase的区别,我多说两句。merge会生成一个合并节点,保留两条分支原本的走向,历史看起来像网状。rebase是把当前分支的提交“重放”到目标分支顶端,历史变成一条直线,很干净。但 rebase 会改写提交哈希,适用于还没 push 的本地提交。对于已经推到远程的分支,不要随意 rebase,否则队友拉取时会碰到一串莫名其妙的冲突。

平时用 IDEA 写代码的同学,可以在 IDEA 里操作分支合并:底部工具栏 VCS → Git → Branches,选择要合并的分支点 Merge or Rebase。图形界面里能直观看到哪些文件冲突、哪些文件被谁改了。另外 IDEA 从远程拉取已有项目也很简单:File → New → Project from Version Control,粘贴仓库地址,选好目录就能克隆下来。很多人问“IDEA 怎么合并分支”“IDEA 怎么拉取 Git 项目”,其实就是这两条路径,比命令行还要直白。

有个常见报错值得单独提一下:

fatal: refusing to merge unrelated histories

这个错误通常发生在一个新初始化的本地仓库和一个远程仓库历史不相关时。比如你本地已经提交了代码,远程仓库也初始化了 README,两边没有公共提交,合并就会触发这个保护机制。确认你是故意要合并两个不相关仓库的话,加参数:

git pull origin main --allow-unrelated-histories

但使用前要想清楚,这会把两边完全不相关的历史强行拼在一起,容易产生不可预期的文件覆盖。

4.3 修改历史:amend、revert、cherry-pick 怎么用

开发过程中经常会有“刚才提交写错了”的后悔药时刻。三种常用操作我说清楚。

git commit --amend用于修改最近一次的提交。比如提交信息手误打错字,或者漏掉了一个文件想补进去:

git commit --amend -m "fix: 修复空指针异常(改后)"

如果你已经git add了额外的改动,直接执行git commit --amend --no-edit,会用暂存区内容替换上一次提交,同时保留原来的提交信息。这里的红线是:只对本地的、还没推送到远程的提交使用 amend。如果已经 push 了,amend 之后历史就分叉了,你再强推会搞乱队友的工作区。

git revert用于安全地撤销某个已经推送的提交。它不是把历史删掉,而是生成一个新的反向提交,把你指定的那次改动抵消掉:

git revert 提交哈希

这样做的最大好处是不改写历史,所有协作者的仓库都不会因为这次回滚而出现冲突。撤销线上 bug 修复时,我优先用 revert 而不是 hard reset。

git cherry-pick用于把某一次提交单独挑到当前分支上来,常用于“这个修复在 main 上已经做了,但我现在的 release 分支也需要同样修复”的场景:

git cherry-pick 提交哈希

这里要特别解释一下热词里问的“git pick 和 fetch 有什么区别”。cherry-pick是把某个明确的提交“复制”到当前分支,它操作的是单次提交,本地会生成一个全新的提交。fetch是把远程仓库的最新提交记录和对象下载到本地,但完全不合并、不改变你的工作区。它们是完全不同层面的命令,名字上容易混淆,但使用场景没有重叠。区分的关键是问自己一句话:我是想让某个改动出现在当前分支(用 cherry-pick),还是只想看看远程有没有更新(用 fetch)?

说到 fetch 就顺便把 pull 讲透。git pull = git fetch + git merge。如果你不想贸然把远程改动合并到本地(可能先想看看远程改了什么),就先git fetch,然后git log origin/main查看差异,确认没问题再手动git merge origin/main。我平时在团队协作时的习惯是先 fetch 再 merge,而不是直接 pull,好处是可以拦住很多没做完的半成品提交。

4.4 .gitignore 过滤文件形同虚设?问题出在这

热词里有一条叫“git 的过滤文件 没有作用”,这个坑我当年入坑时也踩过,现象是:明明在.gitignore里写了node_modules/,执行git status之后node_modules还是出现在未跟踪列表里。

原因其实一句话就能讲明白:.gitignore只对未被跟踪的文件生效,已经被 Git 跟踪的文件不受它控制。如果你之前已经把node_modules或者某个配置文件提交进了仓库,之后再在.gitignore里写它的规则,Git 会无视这条规则,因为文件“已经在库里了”。

正确的处理方式是先把已跟踪的文件移出跟踪列表,再提交一次变更:

git rm -r --cached node_modules

--cached参数的意思是只从 Git 索引里移除,不影响磁盘上的文件。执行完再git status,你会发现 node_modules 变成了未跟踪状态,这时候.gitignore的规则就生效了。最后提交一次改动,把这次变更固化为历史。

.gitignore的写法也有几个容易混淆的点。比如:

# 忽略根目录下的 build 目录 /build # 忽略任意层级的 build 目录 build/ # 忽略所有 .log 文件 *.log # 但保留重要日志 !important.log

规则里,/开头的路径锚定仓库根目录,不带/的会匹配任意层级。!表示排除。

这里还要提一个红线级别的建议:不要把密钥文件提交到仓库里,再用 .gitignore 去忽略。很多人会把.env、config.yml这种带数据库密码的文件先git add了,再补写进 .gitignore。问题是,只要这条记录进了历史,.gitignore只能保证未来不再跟踪,之前的提交里永远留着这个文件的快照,任何人 clone 后都能用git log翻出来。安全做法是一开始就不 add,或者用后面第 5 章说的 filter-repo 把历史里的敏感文件彻底抹掉。

5. 常见问题与疑难杂症排查实录

这部分内容是我在帮助同事和网友排查 Git 问题时遇到的真实案例,整理成速查形式,按优先级从高到低排列。

5.1 SSH 认证失败排查步骤

报错长这样:

git@github.com: Permission denied (publickey). fatal: Could not read from remote repository.

按照这个顺序逐项排查,效率最高。

先确认公钥是否真的添加到了平台上。执行:

cat ~/.ssh/id_ed25519.pub

复制输出的内容,到 GitHub/Gitee 的 SSH 公钥设置页面检查是否一致。很多时候是添加时漏掉了一个字符,或者把没复制全的公钥贴上去了。

再看密钥是否被 ssh-agent 加载。Windows 的 Git Bash 里经常出现这个情况:密钥文件存在,但 ssh-agent 没有加载它。执行:

ssh-add -l

如果输出The agent has no identities,就先启动 agent 并加载密钥:

eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519

加载成功后再测试:

ssh -T git@github.com

如果还是不行,用调试模式跑一遍,看详细日志:

ssh -vT git@github.com

日志里会打出走了哪个私钥文件,是否能从服务端得到响应。重点看有没有出现Offering public key并且后面跟的是不是git@github.com对应的密钥。如果是,基本能定位到密钥路径或者配置问题。我有一次排查了很久,最后发现是~/.ssh/config里给 GitHub 指定了错误的IdentityFile,导致系统一直拿公司内网的密钥去认证 GitHub,把配置改对之后立刻就通了。

还有一个 Windows 下常见的隐藏坑:如果 Git 是用管理员权限安装的,系统生成的密钥文件权限可能被 Windows 锁定,导致 SSH 无法读取。处理方式是打开文件属性,确保当前用户有完全控制权,或者直接重新生成一份密钥放到用户目录下的~/.ssh。

5.2 大文件提交失败的解决方案

推送时遇到这种报错很经典:

remote: error: File xxx.zip is 150.00 MB; this exceeds GitHub's file size limit of 100.00 MB

先说清一个前提:Git 工具本身没有硬性的大文件限制,限制来自托管平台。GitHub 单文件上限 100MB,Gitee 同样在 100MB 量级。但更值得说的是,把大文件放进 Git 仓库本身就是一件不划算的事:Git 每次提交都会保存文件快照,一个大文件的多个版本会把仓库撑到几个 GB,克隆一次慢到怀疑人生。

解决方案分情况。

如果大文件不需要版本管理(比如构建产物、安装包、数据库导出备份),正确做法是不入库。通过.gitignore规则排除掉,需要分发时放到对象存储或者共享网盘。

如果大文件确实需要纳入版本管理,用 Git LFS(Large File Storage)。大致流程是:

# 安装 Git LFS(如果之前没用过) git lfs install # 跟踪指定类型的大文件,以 psd 素材为例 git lfs track "*.psd" # 把 .gitattributes 提交到仓库 git add .gitattributes git commit -m "chore: 使用 Git LFS 管理大文件" # 之后正常 add/commit/push git add design.psd git commit -m "feat: 添加设计稿" git push

LFS 的原理是把大文件本体存到远端 LFS 服务器,仓库里只保存一个指针文件。克隆时按需下载大文件内容,从而保持主仓库体积可控。团队使用 LFS 时要确保每个人都执行git lfs install,否则 checkout 时只拿到指针文件,解不开实际内容。

如果大文件已经在历史里了,问题就比较麻烦。删除当前文件再提交,历史里还是有这个文件,仓库体积并不会变小。处理手段是重写历史,比如git filter-repo。这里要强调:重写历史会把所有涉及提交的哈希全部改变,必须和团队所有人确认好,没人有其他本地分支再操作,否则会互相污染。实际操作中,我宁愿重新建立一个干净仓库重新推开发代码,也不轻易对多人协作的仓库执行历史重写。

保险的办法是从源头堵住:在团队仓库里加一个 pre-commit hook,提交时检查暂存文件是否超过约定大小(比如 50MB),超了就拒绝提交。这个规则对防止“手滑提交大文件”非常有效。

5.3 .git 目录泄露的排查与防护

“git 目录泄露”是搜索引擎里出现频率很高的词,我说说从开发者角度应该怎么理解和应对。背景是:如果把项目目录直接放在 Web 服务器的静态文件根目录下,访问者可以通过/.git/config、/.git/HEAD等方式访问到 .git 目录里的内容,进而把整个代码仓库从服务器上拉下来。

自查方式是直接访问自己的站点域名,看这两个路径是否有响应:

https://你的域名/.git/HEAD https://你的域名/.git/config

如果返回 200 并且能看到ref: refs/heads/main或一堆配置项,说明你的开发库被公开了。

防护手段分三个层面。第一,Web 服务器层面禁止访问.git目录。以 Nginx 为例,在站点配置里加这段规则:

location ~ /\.git { deny all; return 403; }

Apache 可以在.htaccess里加类似规则。第二,部署路径层面,不要把仓库根目录直接当成 Web 根目录,部署时只发布构建产物到静态目录。第三,代码层面,确保仓库里没有硬编码的密钥,检查git log历史中有没有出现过密码和 token。

如果已经泄露了,第一时间是轮换所有可能被翻出来的密钥、密码、Access Token,然后处理敏感历史。推荐用git filter-repo把包含敏感信息的文件从整个历史里清除掉,重新推送。需要特别说明:即使删除了 .git 目录的访问权限,只要历史里还保留着密钥文件,这个泄露风险就依然存在,所以“清历史”比“封目录”更重要。

顺带说一句,网上确实有人用“git 目录泄露”这个漏洞去下载别人的源码,但作为开发者,把重点放在“怎么防”“怎么查”上才是正路。

5.4 其他高频报错速查表

这几个报错是日常开发中出现频率最高的,我整理成表格,仅供参考,应对思路也都是实测好用的。

报错信息常见原因处理方式
Please tell me who you are未配置 user.name / user.email执行第 3.1 节的配置命令
git open /dev/null or dup failed: No such file or directory常见于 Windows 下 Git 环境异常、磁盘空间不足或终端会话异常先重启 Git Bash,清理临时目录,确认磁盘剩余空间足够;仍不行就以管理员权限重装 Git
fatal: refusing to merge unrelated histories两个仓库没有共享历史确认意图后加--allow-unrelated-histories
LF will be replaced by CRLF换行符配置不一致按第 3.3 节设置core.autocrlf
fatal: Not a git repository在非仓库目录执行了 Git 命令先用git status确认当前目录是否在仓库内
远程 push 时提示认证失败密钥未配置或凭据过期按第 5.1 节排查 SSH,HTTPS 场景检查 token
error: src refspec main does not match any本地还没有名为 main 的分支或分支名不一致先git branch -M main再 push

还有一个高频词“git submodule”,也简单说明。git submodule用于在一个仓库里引用另一个仓库的某个固定提交版本。适用场景是:你的项目依赖了另一个 Git 仓库的特定版本,希望把这个仓库作为一个子目录托管进来。相关命令是:

git submodule add git@github.com:xxx/lib.git lib git submodule update --init --recursive

子模块用起来比普通目录麻烦,属于“不到必要不引入”的机制,大多数项目用包管理器解决依赖就够了,不需要上 submodule。

6. 常用命令速查表与给新手的几点建议

6.1 高频命令速查表

把几个核心操作整理成速查表,方便对着敲。

操作命令说明
初始化仓库git init在当前目录建立 Git 仓库
查看状态git status显示工作区和暂存区的变更情况
暂存文件git add <文件名>把文件改动加入暂存区
提交git commit -m "提交说明"把暂存区内容固化为一次提交
查看历史git log --oneline --graph查看提交历史,带图形化分支展示
查看改动git diff查看尚未暂存的详细差异
创建并切换分支git switch -c <分支名>一步完成创建新分支和切换
切换分支git switch <分支名>切换到已有分支
合并分支git merge <分支名>把指定分支合并到当前分支
关联远程git remote add origin <地址>关联远程仓库
推送到远程git push -u origin main首次推送并建立关联;之后直接git push
拉取更新git pull从远程拉取并合并
暂存未完成的工作git stash临时保存当前修改;恢复用git stash pop
撤销工作区改动git restore <文件名>把文件恢复到最近一次提交状态
取消已暂存的文件git reset HEAD <文件名>从暂存区移除,不改动工作区内容

6.2 三条实战建议

结合我这几年的使用经验,给刚入门的读者三条建议,不算什么高深的原理,都是教训换来的。

第一条,提交信息认真写。团队协作里,一个清晰规范的提交说明比代码注释还重要。回滚、查 bug、做版本发布,全靠提交信息定位范围。我自己习惯的格式是“类型 + 简述”:feat: 添加用户注册接口、fix: 修复支付回调重复通知、chore: 升级依赖版本。坚持一段时间,你会发现回滚和排查效率明显提升。

第二条,每个提交只做一件事。别把“改了样式、修了 bug、优化了接口”混在一个提交里。一旦线上出问题要回滚,混在一起的提交就非常难取舍——回滚了有 bug 的提交,样式改动也一起没了。拆开提交虽然麻烦一点,但后端可维护性的收益远大于那几秒钟的省事。

第三条,从第一天就用.gitignore。初始化仓库的时候就写好忽略规则,把node_modules/、target/、*.log、.env这些提前排除掉。如果等到仓库跑了一阵子再来补,就会出现第 4.4 节说的“已跟踪文件不受 ignore 控制”的尴尬,还要额外做一次解除跟踪的提交。第一天安装 Git 时顺手把模板配上,后面一直受益。

最后再说一点个人体会。Git 安装真的只是半小时的事,真正决定你使用体验的是装完之后的配置和长期养成的工作习惯。我见过太多人安装了半年,还在用 HTTPS 地址配密码,提交信息随手写“aaa”,每次合并远程代码都靠猜冲突怎么处理。这些问题都不是大问题,但会持续地、缓慢地消耗你的时间。把这篇文章里的配置一次做完、命令多敲几遍,后面开发就能把 Git 当背景板用,不用再为工具本身分神。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询