Git 常用命令实战:从安装配置到分支管理、撤销回滚与远程协作

发布时间:2026/9/26 16:55:07
Git 常用命令实战:从安装配置到分支管理、撤销回滚与远程协作 1. 安装与环境准备1.1 Git 安装方式小结Git 是当下开发者绕不开的工具就算平时用 IDE 的图形按钮提交代码底层的还是这一套命令。与其等出了问题对着错误提示干瞪眼不如先把常用指令摸透。这篇文章没有废话也不按什么“入门到精通”的套路来纯粹是我这么多年干活时反复在敲的命令从安装、配置、日常提交到分支合并、后悔药、远程推送一条条拆开讲明白。先收下环境这一关。不同系统装 Git 的方式不太一样说几个我实测过最省心的LinuxDebian/Ubuntu 系sudo apt install gitLinuxCentOS/RHEL 系sudo yum install gitmacOS装了 Homebrew 就直接brew install git没装的话去官网下 pkg 安装包也行Windows推荐用 Git for Windows它自带一个 Git Bash 终端模拟 Linux 环境很多命令行为跟 macOS/Linux 保持一致踩坑少装完先跑一句验证git --version能输出版本号就说明装好了。Windows 用户如果是在 CMD 里敲的记得把 Git 的 bin 目录加到 PATH正常安装包会帮你勾选不用手动折腾。1.2 首次使用前的必做配置这一步很多人跳过去了结果就是第一次git commit报错或者提交记录里出现一串乱码一样的名字。Git 每次提交都会记录“谁做的”靠的不是登录账号而是本地的全局配置。所以开工前先配置身份git config --global user.name 你的名字 git config --global user.email 你的邮箱注意这里填的邮箱最好是你代码托管平台上常用的邮箱因为平台会把提交邮箱和你账号关联起来。我记得早年有个同事随便填了个邮箱提交记录挂在了一个陌生账号名下找都找不回来非常尴尬。还有几个我建议顺手配掉的git config --global init.defaultBranch main git config --global core.autocrlf input git config --global core.quotepath falseinit.defaultBranch是把新仓库的默认分支从master改成main跟 GitHub/Gitee 新建仓库的默认保持一致少一点心智负担。core.autocrlf是换行符策略Windows 上建议设成trueMac/Linux 设成input避免出现整个文件所有行都被标记为修改的“换行符灾难”。core.quotepath false这个对中文用户特别友好不然git status显示中文文件名时全是一堆反斜杠转义看着头大。查看当前配置用git config --list想改某一条就重新执行对应的 config 命令。配置作用域分三层system、global、local默认不写作用域时操作的是 local 层它会覆盖 global 的相同配置很适合不同项目用不同身份的情况。实际工作中我在公司电脑上就靠这个区分个人项目和公司项目。2. 日常开发最常用的基础指令2.1 初始化仓库与克隆远程项目拿到一个新项目一般就两种情况从零开始或者把远程已有的仓库拉下来。从零开始在项目目录里执行git init执行完目录下会多一个.git隐藏文件夹这就是仓库的核心所有版本历史都存这里面。这里提醒一句千万不要手贱去删.git目录删了等于历史全没了。如果远程已经有人建好了仓库用clone拉一份到本地git clone 仓库地址仓库地址一般有两种形式HTTPShttps://github.com/user/repo.gitSSHgitgithub.com:user/repo.gitHTTPS 每次 push 都要输账号密码不过可以用凭据管理器记住。SSH 需要配置密钥后面第六章会专门说。我个人的习惯是走 SSH一劳永逸。clone 有个小参数我经常用git clone -b dev 仓库地址这个可以指定克隆某个分支而不是默认的 main/master。有些仓库默认分支是坏的或者不是你想用的这个能省掉一次切分支的麻烦。2.2 状态检查、暂存与提交日常开发三连status看状态add暂存commit提交。git status这条一定是最高频的命令没有之一。它会告诉你当前工作区干不干净哪些文件改过、哪些是新文件、哪些已进入暂存区。我个人的习惯是任何操作之前先跑一遍git status就像你开车前先看一眼仪表盘尤其是准备执行 reset 或 checkout 这种危险命令时这一眼能救你命。add是把改动放入暂存区也就是告诉 Git“我要把这些文件纳入下一次提交”git add 文件名 # 暂存指定文件 git add . # 暂存当前目录所有改动 git add src/ utils/ # 暂存多个目录有些新手喜欢无脑git add .我的建议是提交前先用git status和git diff确认一下哪些文件动了。尤其是项目里可能有本地配置文件、临时文件无脑 add 会把不该提交的东西带进去。如果确实想全加也要先看一遍列表确认没有.env之类的敏感文件。然后提交git commit -m 提交说明提交说明就是 commit message这里多说两句。写好提交信息比写好代码还重要因为半年后你回头看历史靠的就是这些信息。一个比较通用的格式是type: subject比如fix: 修复登录接口空指针异常 feat: 新增用户导出功能 docs: 更新 READMEtype可以是feat新功能、fix修 bug、docs文档、refactor重构、test测试等。这是我见过最省事的规范既不过度工程化又能让历史记录一眼扫明白。2.3 提交信息的补救git commit --amend有没有遇到这种情况提交完发现 message 打错字了或者漏了一个文件没加进去git commit --amend它会打开编辑器让你修改上一次的提交信息。如果只是想顺带补文件先 add 再 amendgit add 漏掉的文件.txt git commit --amend执行完之后上一次提交就被“覆盖”成了一个新的提交不会多出一条历史记录。这里有一条非常重要的红线amend只适合处理还没有推送到远程的提交。如果这个提交已经 push 出去了别人可能基于它做了分支你这边一 amend两边的提交哈希就对不上了后面会引发一连串合并冲突。所以我的原则是本地 commit 后发现小问题随便 amend已经 push 的老老实实用git revert后面会讲。3. 分支管理与远程协作3.1 分支的创建、切换与合并分支是 Git 相比 SVN 最大的优势。你可以理解成平行宇宙在dev分支上改代码不会影响main等开发完了再合并回来。查看当前分支git branch创建新分支git branch feature-login切换分支git switch feature-loginGit 2.23 之后推荐用switch语义更清晰。老一点的命令git checkout feature-login也能用但checkout身兼数职既能切分支又能丢弃文件改动新手容易混淆。更常用的是“创建并切换”一步到位git switch -c feature-login等于git branch feature-logingit switch feature-login。合并分支回到主分支git switch main git merge feature-login如果合并时没有冲突Git 会直接走 fast-forward把 main 的指针挪到 feature-login 上。如果有冲突就会进入冲突解决流程这个在 3.3 细说。3.2 远程仓库remote、push、pull、fetch本地分支搞完了得把代码推到远程不然合作的人看不到。关联一个远程仓库git remote add origin https://github.com/user/repo.gitorigin是远程仓库的默认别名你叫它什么都行但行业约定俗成就是origin。查看远程仓库列表git remote -v第一次推送时需要指定上游分支git push -u origin main-u是--set-upstream的简写意思是“把本地的 main 分支和远程的 main 分支关联起来”。加过一次之后后续直接敲git push就行了。拉取远程更新git pull这里必须讲一个很多人栽过的坑git pull默认执行的是fetchmerge。如果你的本地提交和远程提交出现了分叉Git 会自动创建一个 merge commit历史会变得很乱。更推荐的做法是git pull --rebase这会把你在本地还没推送的提交“摘下来”暂存到一边先把远程的提交拉下来再把你自己的提交按顺序“放”上去历史保持线性干净很多。我自己把pull.rebase设为默认配置了git config --global pull.rebase true设完之后git pull就等价于git pull --rebase省心。3.3 合并冲突的解决思路冲突这玩意儿第一次遇到的人基本都会慌。别慌它没那么可怕。什么时候会有冲突两个人改了同一个文件的同一个区域Git 不知道怎么自动合并就会把这个文件标记为冲突状态。冲突状态的文件打开之后长这样 HEAD 这里是当前分支的内容 这里是合并进来的分支的内容 feature-login和之间的是当前分支版本和之间的是被合并分支版本。你要做的就是把该留的留下该删的删掉包括这三种标记符号一个都不能留。处理完保存文件然后git add 冲突解决后的文件 git commitGit 会自动生成一条 merge commit。如果你不确定怎么解决我建议到 IDE 里看VS Code 和 IntelliJ 系列都有可视化冲突解决界面谁会保留、谁会丢弃点几下就好。有一条经验冲突解决时先看清哪个版本是最近的。宁可少留不要乱留把模棱两可的逻辑拿出来跟当事人对一下千万别“凭感觉留一份”。4. 撤销与回滚4.1 工作区、暂存区、本地仓库三个区域的底层认知要理解撤销操作先得搞清楚 Git 的三个区域。我用个购物类比工作区Working Directory你的项目目录相当于手里的草稿纸改代码都是在这里发生的暂存区Index/Staging Area相当于购物车你把看中的商品改动的文件放进去等待结算本地仓库HEAD相当于已经结账打包回家的货架commit就是结算的动作每个文件在这三个区域之间移动的状态就是git status里看到的那些提示modified工作区有改动但还没 addstaged已经 add待 commitcommitted已经 commit和 HEAD 一致理解了这三个区域撤销操作就只是“把文件恢复到某个区域的状态”的问题了。4.2 各种撤销场景对应指令表先给一个速查表再做详细解释场景指令风险程度丢弃工作区某个文件的改动git restore file或git checkout -- file危险改动不可找回把暂存区的文件退回到工作区git restore --staged file低风险内容不会丢撤销上一次提交并保留改动git reset --soft HEAD~1低风险撤销上一次提交并取消暂存git reset HEAD~1默认 mixed低风险撤销上一次提交并删除改动git reset --hard HEAD~1极度危险撤销某一次已推送的提交git revert commit安全会生成新提交不推荐用git checkout恢复文件因为它和“切换分支”是同一个命令容易误解。新版 Git 提供git restore语义明确我只推荐这个。4.3 reset、revert、clean 的正确打开方式先说git reset。它有三种模式区别在于“回撤之后改动还在不在”--soft只移动 HEAD 指针暂存区和工作区都不动。相当于提交 history 没了但代码改动都在等着你重新提交--mixed默认移动 HEAD 指针并重置暂存区但工作区不动。改动保留但在工作区需要重新 add--hard移动 HEAD 指针同时重置暂存区和工作区。改动彻底消失找不回来一个我常用的场景刚 commit 完发现里面有个多余文件想拆成两个提交。用git reset --soft HEAD~1把提交撤掉但改动全部保留在暂存区然后重新 add 拆分。git reset --hard要慎用它不会保留任何备份。但如果只是恢复到之前某次提交而且你的分支已经推到远程了可以考虑git reset --hard origin/main来“强制同步”到远程状态。再说git revert。它不删历史而是生成一个“反向提交”把之前的改动抵消掉。这适合已经 push 出去的提交。因为历史里会留下完整的操作记录团队成员看到的是“有人用一次提交撤销了另一次提交”非常透明。我自己作为团队里经常 review 代码的人特别反感有人对已推送的提交用reset --hard因为一旦别人基于之前的提交继续开发后面强行 push 会把别人辛辛苦苦推上去的提交冲掉。这个场景必须用revert。最后提一下git clean。它清理的是工作区里未跟踪的文件比如编译生成的临时文件。我偶尔会用git clean -fd-f是强制删除-d是连同目录一起删。这个命令不会询问太多执行前一定先看git status确认哪些是未跟踪文件否则误删了就凭空消失。5. 查看历史与代码排查5.1 git log 的常用参数一眼看懂提交记录Git 历史记录我用得最多的是几个参数组合git log --oneline --graph --decorate --all--oneline每条提交只用一行显示包含短哈希和提交信息--graph用线条画出分支合并走向网络图效果特别适合理解分支结构--decorate显示分支/标签指向了哪个提交--all显示所有分支而不只是当前分支还可以带作者过滤和时间过滤git log --author张三 --since2024-01-01 --until2024-06-01这个我在做月度复盘或者代码审计时经常用能快速统计某个人在某段时间的提交量。想搜索某段代码是哪个提交引入的git log -S 某段字符串-S也叫“pickaxe”它会找出新增或删除这个字符串的所有提交。定位 bug 是谁引入的这个命令比人肉翻代码高效一百倍。查看某次提交的改动内容git show commit哈希5.2 用 blame 定位“罪魁祸首”git blame是我排查问题时的神器。它可以显示文件每一行最后被谁修改、在哪次提交里改的git blame 文件名只看某几行git blame -L 100,120 文件名看到某一行是问题代码但不知道为什么这么写时拿提交哈希去问当事人是最直接的。当然blame不是为了“追责”而是为了理解代码演化过程。很多时候你看到一段奇怪的代码骂骂咧咧点进去一查发现是半年前你自己写的那体验可酸爽了。正因为这样我养成了写提交信息时把“为什么这样改”也写进去的习惯能帮未来的自己和同事省很多时间。5.3 用 diff 看清楚改动细节代码审查和提交之前git diff是必备的一步。查看工作区相对暂存区改了什么git diff查看暂存区相对上次提交改了什么git diff --cached或--staged查看两个分支之间的差异git diff 分支A 分支B查看某次提交改了什么git show 哈希特别是git diff --cached提交前扫一眼防止把调试代码、敏感信息、无意义的空格变化一起提交上去。我有个坏毛病就是喜欢改完代码顺手多敲几个空格这种噪音会让diff变得很难看如果被 reviewer 看到虽然没问题但阅读体验很差。所以提交前我会挨个文件看 diff把不该有的格式调整拆到单独的 commit 里。6. SSH 密钥配置与远程推送实战6.1 生成密钥并添加到代码托管平台前面说过 SSH 方式推送可以免输密码这里详细走一遍。首先生成密钥对。我推荐用 ed25519 算法生成快、安全性强ssh-keygen -t ed25519 -C 你的邮箱example.com一路回车把文件保存在~/.ssh/下。如果你之前已经生成过 RSA 密钥不想覆盖它可以在提示输入文件名时改个名比如id_ed25519_gitee。生成的公钥文件是~/.ssh/id_ed25519.pub查看内容cat ~/.ssh/id_ed25519.pub复制输出的一整段内容去代码托管平台GitHub 或 Gitee的设置页面找到“SSH Keys”粘贴保存。验证是否配置成功ssh -T gitgitee.com第一次连接会提示你确认 host key输yes。成功后平台会返回一段欢迎语看到类似 “Hi xxx! Youve successfully authenticated” 就成了。6.2 手动关联远程仓库并推送在托管平台上新建一个空仓库然后把本地代码推上去。步骤git init git add . git commit -m 初始提交 git remote add origin gitgitee.com:你的用户名/仓库名.git git push -u origin main如果仓库里已经有 README 等文件直接 push 会失败提示远程包含本地不存在的提交。这时要么先git pull --rebase origin main要么干脆建空仓库不勾选“初始化 README”。第一次 push 一个大项目时会比较慢属于正常现象。后续再推送就只是一些增量数据了。6.3 多平台多密钥管理的实际经验如果你同时用 GitHub 和 Gitee甚至还有公司内部的 GitLab同一对密钥是不能跨平台用的不同平台的账号体系不同也不建议所有平台都用同一个密钥。正确做法是给每个平台生成不同的密钥然后在~/.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这样 SSH 连接时会按 Host 自动选择对应的密钥文件不用每次手动指定。我最早没有配这个为了图省事把同一个密钥加到两个平台后面发现有人在 GitHub 上用我的身份推送代码吓得我赶紧把密钥撤掉重新配。密钥泄漏的排查很麻烦所以从一开始就分别管理是正确的姿势。7. 高频问题速查与避坑心得问题原因解决方式push 被拒绝提示 non-fast-forward远程有新提交本地没有git pull --rebase后重新 push每次 push 都要输密码用了 HTTPS 且未缓存凭据配置 SSH 密钥或用git config --global credential.helper store注意安全性提交信息写错了手滑 / 忘改git commit --amend修改最近一次不小心提交了敏感文件误将.env等加入暂存区立即从历史移除参考git filter-branch或第三方工具并立刻去平台撤销/更换密钥误删了本地分支git branch -D删错了用git reflog找到分支指向的哈希git branch 名字 哈希重建文件中文名显示乱码核心配置缺少core.quotepath false执行git config --global core.quotepath false合并冲突出现一堆重复代码换行符混乱统一core.autocrlf配置git reflog这条值得单独说一下。它记录的是 HEAD 指针每次移动的历史相当于 Git 的操作“黑匣子”。哪怕你对一个分支执行了git reset --hard只要 reflog 里还有记录就能找回之前的状态。我吃过一次亏之后现在每次执行破坏性命令前都会快速看一下 reflog 和 status。操作流程是git reflog git branch 救援分支 目标哈希reflog的日志不会永久保留默认过期时间是 90 天但关键时刻就是救命的稻草。还有一条经验在团队协作里不要对已经推送的分支做amend或reset --hard。如果你真的做了那被强行覆盖的同事基本要骂人了。已经推送的代码要修改历史走revert留一条完整的记录比“悄悄改写历史”要干净得多。最后讲一个我踩过好多次的坑提交前不看 status 和 diff。尤其是项目比较大时随手git add .结果把自己配了一下午的本地调试配置也提交上去了。后来我给自己定了一条规则执行任何会影响代码的命令之前必须先看一遍git status和git diff确认改动范围完全在自己预期内。这是 Git 使用中最简单同时也是最有效的一条自律。命令行确实高效但效率不应该建立在侥幸之上。命令那么多真正能记住的其实不多我这些年也只用其中不到十个但把每个用熟练、用对场景远远好过背熟一百个却总在重要时刻把分支搞乱。如果你刚接触 Git建议从status、add、commit三件套练起然后把log、branch、merge玩顺最后再碰reset、revert这类危险操作。一切顺利之后记得常备reflog这个守护神它会在你最慌乱的时候给你兜底。