☰
Git常用命令实战指南:从安装配置到疑难杂症排查
2026/10/7 3:32:21 网站建设 项目流程

聊到 Git 常用命令,很多人第一反应是“网上教程一大把,背下来就行”。但实际用起来却常常卡在几个不起眼的地方:装是装好了,克隆仓库却报错连不上;提交代码后才发现把不该提交的文件加进去了;改完分支合并时冲突堆了一屏幕。这篇文章不打算做命令字典,而是把我自己从安装配置、日常提交、分支合并到大文件、疑难杂症排查的完整套路走一遍,所有命令都在命令行实测过。适合刚入门的开发者,也适合用了几年 Git 但总在“能用就行”边缘徘徊的老手查漏补缺。

1. 先把环境收拾利索:Git安装与全局配置

1.1 Windows / Linux 装 Git 的正确姿势

先泼一盆冷水:很多 Git 报错根本不是命令问题,是环境没装好。Windows 上最稳妥的方式是从官网下载安装包,一路 Next 没有坑。安装界面里有几个选项容易被忽略,比如“调整 PATH 环境变量”默认选的是推荐项,不用改;Git Bash 组件默认勾选,强烈建议保留。Git Bash 是 Windows 下最接近 Linux 终端的交互环境,后续很多命令,比如ssh-keygen、grep、cat,在 Git Bash 里跑比 CMD 和 PowerShell 稳定得多。很多人习惯双击 Git GUI,其实命令行才是日常效率最高的入口。

Linux 上用包管理器装更快:Debian/Ubuntu 系执行sudo apt update && sudo apt install -y git,CentOS/RHEL 系执行sudo yum install -y git或者sudo dnf install -y git。装完先别急着建仓库,第一件事是验证版本:git --version。如果提示 “command not found”,大概率是 PATH 没配好,Windows 安装时没选“加入 PATH”,重新装一遍或者手动加环境变量即可。这里强调一句:新版 Git 功能差异不大,不用追求最新,能稳定拉取远程代码就够用。下载安装教程网上很多,但核心其实是两点:装完能执行git命令,以及能顺利连接远程仓库。

1.2 user.name 和 user.email:提交记录的身份证

安装完成后第一件事是设置全局身份,不然后续 commit 会报Please tell me who you are。命令是:

git config --global user.name "你的昵称" git config --global user.email "你的邮箱"

这两项会写入用户主目录下的.gitconfig,以后所有仓库的提交记录都带上这个身份。为什么强调“全局”而不是每个仓库单独设置?因为绝大多数人只有一个常用身份信息,全局设置可以避免新克隆的仓库因为缺身份而提交失败。如果你在不同平台用了不同身份,可以用仓库级配置覆盖:在某个仓库内执行git config user.name "xxx",仓库级配置会优先于全局配置。

查看当前配置用git config --list,能看到所有生效项。如果发现配置不对,直接编辑主目录下.gitconfig即可。这里有个经验:邮箱最好用真实常用的邮箱,因为提交记录里会公开,别人可以通过邮箱联系你;不要临时乱填,后面改历史非常麻烦。另外一个容易忽略的点是文件大小写,.gitconfig写错参数名不会报错,但不会生效,所以改完最好再执行一次git config --list确认。

1.3 SSH 密钥与免密拉取配置

每次 push 都要输账号密码很痛苦,SSH 密钥是最常用的免密方案。生成密钥用ssh-keygen -t rsa -b 4096 -C "你的邮箱",一路回车会在用户主目录生成~/.ssh/id_rsa和~/.ssh/id_rsa.pub。然后把.pub文件内容加到代码托管平台的 SSH 公钥列表里,比如 Gitee、GitHub 的设置页面都有 “SSH keys” 入口。

加完之后务必测试连接:

ssh -T git@gitee.com

Gitee 会返回类似 “Hi xxx! You've successfully authenticated” 的信息。这一步能提前暴露很多隐藏问题:如果提示Permission denied (publickey),先看~/.ssh目录权限,Windows Git Bash 下一般不用管,Linux 下需要chmod 700 ~/.ssh和chmod 600 ~/.ssh/id_rsa;如果提示Host key verification failed,多半是首次连接需要确认指纹,手动连接一次确认即可。

克隆代码时候选择 SSH 地址,形如git@gitee.com:user/repo.git,之后 push/pull 就不会每次要密码了。这里再分享一个小坑:如果你的机器上存在多个 SSH 密钥,Git 默认会先尝试id_rsa,如果托管平台上没注册这个公钥,就会认证失败。解决办法是在~/.ssh/config里为不同域名指定不同的IdentityFile,比如给 Gitee 单独写一段 Host 配置。很多“Git 免密不生效”的问题,最后都是出在这个细节上。

2. 日常必用的核心命令拆解

2.1 clone 和 remote:先搞清楚仓库从哪里来

日常工作 95% 从 clone 开始。git clone <地址>会把远程仓库完整拉下来,默认就会建立远程分支跟踪。如果是自己本地从零开始,用git init初始化空仓库,然后git remote add origin <地址>关联远程,名字不一定要叫 origin,但这是业内约定俗成,后续所有命令都不用改。查看远程信息用git remote -v,这个命令会显示所有远程仓库的 fetch 和 push 地址,排查远程配置问题时非常有用。

很多人不管三七二十一直接git push,报错no upstream branch时才想起来远程关联问题,这时候可以用git push -u origin main把当前分支推上去,并设置本地分支跟踪 origin/main。-u 参数的含义是 “upstream”,一次性解决后续裸输 push 的烦恼。我在实际项目里见过一种错误:直接把别人仓库的地址 clone 下来,改完代码后往自己远程仓库推送,结果 push 到原仓库没有权限。正确做法是先在托管平台 fork 到自己名下,再 clone fork 后的地址;如果已经 clone 错了,用git remote set-url origin 新地址修改远程地址即可,不需要重新下载代码。

2.2 status、log、diff、stash:把工作区看明白

改完代码别急着提交,先养成看状态的习惯。git status会告诉你三件事:哪些文件已暂存、哪些已修改未暂存、哪些是未跟踪文件。新手最容易犯的错是搞混工作区和暂存区:工作区是你肉眼看到的文件,暂存区是git add之后进入的一个缓冲区,git commit提交的是暂存区里的内容,不是工作区全部内容。这个认知非常关键,很多提交“不完整”的怪问题,都是因为改完文件忘了git add。

git log --oneline --graph --all是我最常用的历史查看命令,一行一个提交,带分支图和所有引用,能快速理清仓库演进。想看某个文件谁改过,用git log -p 文件名,相当于带着补丁看历史。git diff默认比较工作区和暂存区之间的差异;git diff --cached比较暂存区与最后提交之间的差异。提交前我习惯先执行git diff --cached检查一遍,防止把调试日志或临时文件带进提交。

git stash则是临时“收衣服”的命令:正在写一半的代码不想提交,又需要切分支干别的事,执行git stash会把当前修改保存到堆栈,工作区恢复干净;回来后git stash pop恢复。这里有个细节:git stash默认不保存未跟踪文件,需要git stash -u才能连新文件一起保存。踩过坑的人应该都知道,stash 之后找不到新文件有多慌。另外,git stash list可以看堆栈里有几条记录,git stash drop可以清理某条记录,避免堆栈越积越多。

2.3 commit --amend 与 reset 回滚:改了提交别慌

提交代码后发现 message 写错了,或者少加了一个文件,不需要推翻重来。git commit --amend能修改最近一次提交,它会把暂存区内容合并进上一次提交,并重新打开提交信息编辑器。典型用法:

git add 忘记的文件 git commit --amend -m "修正后的提交信息"

执行后你会发现提交记录里只有一条,而不是多出一条“fix”。因为--amend本质是创建了一个新提交替换旧提交,旧的会被丢弃。注意:amend 相当于改写了历史,如果这个提交已经推送到远程且别人也在用,千万不要 amend,否则双方历史会分叉,要 force push 才能对齐,非常麻烦。

git reset是回滚操作,但参数不同后果差很多:

  • git reset --soft HEAD~1:回退到上一个提交,但保留暂存区和工作区改动,适合发现提交信息写错了、想重新提交。
  • git reset --mixed HEAD~1(默认):回退提交并清空暂存区,但工作区改动还在。
  • git reset --hard HEAD~1:回退提交并丢弃所有改动,不可轻易使用。

如果已经 hard reset 后发现改错了,别急着崩溃,Git 还有一个保命命令git reflog。它记录了 HEAD 的所有移动轨迹,能找到任意历史提交的哈希值,再用git reset --hard 哈希切回去。我自己的经验是:回滚之前先执行git reflog留个备份依据,比什么都靠谱。哪怕是你已经认为“彻底删掉”的提交,只要 reflog 记录还在,就能找回来。

2.4 分支与合并:merge 和 rebase 怎么选

分支是 Git 的灵魂。git branch查看本地分支,git branch 新分支名创建分支,git checkout 新分支名或git switch 新分支名切换分支。新版 Git 推荐用switch,语义更清晰,checkout同时承担很多职责,容易混。创建并切换分支用git switch -c 新分支名,比先 branch 再 checkout 少敲一条命令。

分支合并两种思路:git merge和git rebase。merge 会把两个分支的历史“捏”在一起,产生一个合并提交,优点是保留真实历史,缺点是一条线上混了一堆 merge commit,log 不好读。rebase 则是把自己分支的提交“挪”到目标分支顶端,历史呈线性,更干净,但本质上改写了自己分支的提交,多人协作时不要去 rebase 别人正在使用的分支。我的建议是:个人分支尽量 rebase 到最新 main 再合并,共享分支老老实实用 merge,别整花活。

冲突处理是绕不过的坎。执行 merge/rebase 后出现冲突时,git status会列出冲突文件,编辑器里会出现类似<<<<<<< HEAD、=======、>>>>>>> branch-name的标记。我处理冲突的顺序是:先打开每个冲突文件,手动保留需要的代码,删掉冲突标记;然后git add这些文件;最后执行git merge --continue或者git rebase --continue完成收尾。切忌直接 commit,很多初学者在这个环节提交出一堆 “Merge branch” 垃圾提交,后续回溯时想哭都来不及。

3. 进阶场景与命令组合

3.1 git lfs 使用:大文件别再往仓库塞

普通 Git 仓库不适合存大文件,默认会有 100MB 左右的限制,仓库体积膨胀后 clone 会越来越慢。大文件可以交给 Git LFS。安装后先执行git lfs install,在仓库里声明要跟踪的文件类型,例如:

git lfs install git lfs track "*.psd" git lfs track "*.zip"

然后正常 add、commit、push 即可。.gitattributes文件会被自动更新,记录 LFS 跟踪规则。注意git lfs install只需在机器上执行一次,它会为当前用户写入全局钩子;git lfs track则是每个仓库单独配置。如果换了一台电脑,克隆带 LFS 的仓库之前要先装 Git LFS 并执行git lfs install,否则会遇到 “could not find lfs” 或文件无法 checkout 的问题。

LFS 有一个很容易踩的坑:clone 仓库时默认会尝试拉取所有 LFS 文件,网络不好或者文件很大时就会卡住。临时跳过 LFS 文件可以设置环境变量GIT_LFS_SKIP_SMUDGE=1 git clone <地址>,之后手动按需拉取git lfs pull。如果你只想让某个仓库不拉取特定 LFS 文件,可以用git config --global --unset lfs.fetchexclude清理之前设置的排除项,配合lfs.fetchexclude指定文件类型或路径。有时候git lfs clone卡住不是文件多,而是某个 LFS 服务器连接不稳定,排查时先看命令输出停在哪一步,再针对性处理。

3.2 .gitignore 不生效:多半是你把文件 add 进去了

不少人在项目根目录建了.gitignore,写了一堆node_modules、*.log,结果git status里还是能看到这些文件,气得直呼“过滤文件没有作用”。真相是:.gitignore对已经被 Git 跟踪的文件是无效的。如果你在写 ignore 规则之前执行过git add,文件已经进了暂存区/索引,Git 会继续跟踪,之后 ignore 规则不会把它移除。

解决办法是先撤销跟踪,但保留磁盘文件:

git rm -r --cached node_modules git add . git commit -m "清理已经被跟踪的目录"

--cached参数的含义是只从 Git 索引里删除,不碰工作区文件。执行完再检查git status,你会发现 ignore 规则生效了。另外,.gitignore的规则匹配有自己的语法:目录末尾加/表示只匹配目录;*不匹配目录层级,**可以跨层级;规则里写!是取反。我建议想搞清楚文件为什么没被忽略时,用git check-ignore -v 文件名查看是哪条规则在起作用,排查效率高很多。还有一个冷知识:.gitignore只能忽略未跟踪文件,一旦文件已经被跟踪,哪怕后来删掉再重新 add,依然会被跟踪。

3.3 授权测试场景:Git目录泄露如何恢复源码

这个场景比较特殊,但如果做安全测试的同学遇到了,会非常头疼。所谓“Git 目录泄露”,指的是网站部署时把.git目录一起发布到了 Web 根目录,变成静态文件可以被直接访问。访问http://target/.git/config如果能返回内容,基本就确认泄露了。这通常意味着目标网站的完整源码、历史提交甚至配置信息都暴露在公网。

在获得目标授权的前提下,可以尝试把.git目录完整下载到本地,然后利用 Git 自身机制恢复工作区文件。简单做法是用工具递归下载.git目录,或者用wget/curl带上递归参数;如果下载完整,本地进入该目录执行git checkout .就能还原当前分支最新代码。如果下载不完整,还可以通过git cat-file --batch-all-objects列出所有对象,再逐个还原 blob 对象,恢复历史文件内容。

我把这段话写出来,是想提醒两类人:对开发者来说,部署时务必把.git目录挡在 Web 服务之外,比如在 Nginx 或 Apache 配置里禁止点开头目录访问;对安全从业者来说,只能在授权范围内测试,未经授权对任何目标进行探测都属于违法操作。Git 是团队协作工具,也是安全边界清单上的一环,这个坑比大多数命令问题都严重。很多做渗透测试的老手都遇到过目标站暴露.git的情况,利用好了可以直接“抄源码”,但务必管住手。

3.4 多远程源与子模块进阶

除了默认的 origin,一个本地仓库可以同时关联多个远程源。比如你从开源项目克隆了一份,想保持跟上游更新,同时又把自己改动推到自己的仓库,可以这样配置:

git remote add upstream 上游地址 git remote -v # 查看所有远程 git fetch upstream git merge upstream/main

这种场景在代码维护中很常见:本地仓库既能用origin推自己的分支,又能用upstream同步上游修复。注意 fetch 和 pull 的区别:fetch 只把远程更新下载到本地引用,不会合并到工作区;pull 等于 fetch + merge。多人协作时,我建议手动 fetch 后查看git log HEAD..upstream/main的差异,再决定怎么合并,避免被 pull 的默认行为带乱节奏。如果只是想看看上游改了哪些文件,git diff HEAD..upstream/main --stat比直接 merge 更安全。

子模块git submodule用于在一个仓库里引另一个仓库的固定版本。git submodule add <地址> 路径添加,克隆含子模块的仓库时用git clone --recurse-submodules <地址>,否则子模块目录是空的,需要git submodule update --init --recursive拉取。这块命令不多,但坑在于子模块的更新机制是“指针式”的,主仓库只记录子模块的 commit 哈希,不在主仓库里存内容,所以忘执行 update 是最常见的问题。如果你发现子模块目录为空,先别急着重新 clone,先执行那串 update 命令往往就解决了。

4. 常见问题排查实录

4.1 SSH 认证失败与本地代理残留

SSH 认证失败几乎是排行榜第一的 Git 问题。命令提示Permission denied (publickey),原因大致有几类:密钥没加到托管平台、本地 ssh-agent 没加载密钥、本机存在多个密钥但 Git 用了错误的那一个、~/.ssh目录权限不对。排查顺序建议:先ssh -T git@gitee.com看返回,如果还是 publickey,执行ssh-add -l查看当前会话加载了哪些密钥,没有就ssh-add ~/.ssh/id_rsa。如果使用了非默认文件名,需要在~/.ssh/config里写清楚IdentityFile指向;同时确认known_hosts没有残留冲突记录,必要时删除对应行再连一次。

另一个高频报错是git clone时报连接 127.0.0.1 的 7890 端口失败。这个 7890 是本地代理类工具常见的监听端口,Git 之所以会去连它,是因为全局配置或系统环境变量里残留着代理设置。排查方法分两步:

git config --global --get http.proxy git config --global --get https.proxy

如果输出了代理地址,用git config --global --unset http.proxy和git config --global --unset https.proxy清除。再看环境变量:

env | grep -i proxy

如果有HTTP_PROXY、HTTPS_PROXY变量,可以用unset HTTP_PROXY HTTPS_PROXY临时去掉,或者修正为当前可用代理地址。这类问题本质是 Git 的 http 层走了错误代理,和网络本身通不通没关系。我自己遇到时,会先用git -c http.proxy= clone ...的方式临时覆盖验证,确认是代理导致后,再去清理持久配置,效率很高。还有一种情况是.git/config里仓库级别的代理配置,需要进仓库执行git config --unset http.proxy才能清掉。

4.2 CRLF 换行符问题:让团队不再互相制造 diff

Windows 默认用 CRLF(回车+换行)作为行尾,Linux/macOS 默认用 LF。如果一个团队混用系统,Git 会把“行尾风格不同”也当成文件改动,于是出现明明只改了一行,diff 里整个文件都标红的情况。Git 的core.autocrlf参数就是干这个的:

  • Windows 上设置git config --global core.autocrlf true:提交时把 CRLF 转成 LF,检出时转回 CRLF,照顾 Windows 编辑器。
  • Linux/macOS 上设置git config --global core.autocrlf input:只把 CRLF 转成 LF,检出不转换。

更治本的做法是仓库根目录放一个.gitattributes文件,强制指定文件的行尾风格:

* text=auto *.sh text eol=lf *.bat text eol=crlf

.gitattributes随仓库分发,所有协作者自动遵守,不受本地 config 影响。已经错乱的文件想一次性修正,可以用git add --renormalize .按属性重新标准化文件内容,再提交一次。我个人的习惯是:新仓库先提交.gitattributes,旧仓库则先统一团队成员的 core.autocrlf 设置,再处理存量文件,不然纯靠口头约定,总有一天会被同事 Windows 编辑器悄悄“修”一次。如果你看到git status里全是 “warning: CRLF will be replaced by LF” 这类提示,不用慌,按上面的方式统一规则,提示会自然消失。

4.3 LFS clone 卡住与拉取仓库指定版本

git lfs clone卡住多半是大文件拉取慢,或者网络对超大文件不友好。前面提过GIT_LFS_SKIP_SMUDGE=1跳过 LFS 文件,这里再补充一个场景:克隆一个历史很长的仓库,只想看某个 tag 或 commit 的代码,不需要完整历史。常见做法:

git clone --depth 1 --branch v1.0.0 仓库地址

--depth 1是浅克隆,只拉最新一层提交;--branch可以指定分支或标签。如果已经完整克隆了,指定版本就是用git checkout v1.0.0或git checkout <commit哈希>,查看完后想回到主分支,直接git switch main即可。注意 checkout 指定 commit 会进入 detached HEAD 状态,此时不要直接在它上面提交,建议先创建分支再改代码。

如果 LFS 文件拉不下来但代码本身能用,也可以临时设置git config --global lfs.fetchexclude "*.zip"来排除某些 LFS 类型,等需要时再git lfs pull --include="*.zip"单独拉取。按需拉取是处理大仓库的常用策略。还有一种情况:明明仓库里没有 LFS 文件,但 clone 时提示 “Downloading file”,可能是仓库历史上有过 LFS 跟踪,后来又取消了,这种历史 LFS 对象默认也要拉取,同样可以用跳过 LFS 的方式处理。

4.4 常用命令速查表与易错点

最后整理一份我实际项目里最常用的速查表,适合贴在终端旁边:

操作命令说明
查看状态git status查看工作区、暂存区变化
查看简洁日志git log --oneline --graph --all分支历史一目了然
暂存所有改动git add -A包含新增、修改、删除
提交git commit -m "描述"提交暂存区内容
推送并关联远程git push -u origin main首次推送常用
拉取并合并git pull相当于 fetch + merge
切换分支git switch -c 新分支名创建并切换分支
合并分支git merge 分支名把指定分支合入当前分支
暂存修改git stash -u连未跟踪文件一起暂存
恢复暂存git stash pop恢复并删除堆栈记录
修改最近提交git commit --amend -m "新信息"只能用于未推送的提交
回滚到指定提交git reset --hard 提交哈希慎用,会丢改动
找回误删提交git reflog查看 HEAD 历史轨迹
查看远程地址git remote -v确认 fetch/push 地址

易错点再强调三件事:第一,git pull前先git stash或提交本地改动,避免未提交修改和远程更新冲突;第二,不要git push --force到共享分支,如果一定要强刷,先在群里喊一声;第三,提交信息写清楚“为什么改”,比写“改了一堆 bug”有用得多。另外,有些 IDE 在操作 Git 时会自动带上一长串参数,比如git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks ...,看到这种命令不要慌,它只是在调用 Git 时临时加了配置,对仓库本身没有副作用。

我个人现在的习惯是:任何一台新电脑装完 Git,第一件事就是设好全局身份和 SSH 密钥,任何新仓库先提交.gitattributes,任何重要分支动历史之前先git reflog瞄一眼。这三个习惯帮我在过去几年省掉了大量无效操作。Git 常用命令其实是越用越熟的,关键是知道每条命令背后在动哪一部分数据——工作区、暂存区、提交、引用。把这个模型想明白了,很多报错你瞄一眼就能猜到原因。这份命令指南就当是我陪你把这些角落都走了一遍,后续如果再遇到什么奇葩问题,欢迎回来对照排查。

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

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

立即咨询