ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Git命令大全:从安装配置到分支合并与撤销回滚

Git命令大全:从安装配置到分支合并与撤销回滚 Git 大概是程序员每天敲得最多的命令之一。我入行前几年一直靠着git add、git commit、git push三连击走天下也没觉得有什么问题。直到后来参与多人协作、独立维护项目分支才意识到 Git 这条命令链远比想象中要深。尤其是遇到要回滚发布版本、改错了提交信息、Push 之后才发现代码有问题这些场景光靠三板斧根本应付不来。这篇内容我打算把 Git 从安装、配置、日常操作、分支合并、远程协作、撤销回滚到高频报错完整捋一遍。不追求把每个参数都抄一遍而是把日常开发里用得上、出了问题能救命的命令讲透并带上我自己踩过的一些坑。无论你是刚装好 Git 的新手还是已经写了一阵子命令、想补全细节的老手这套清单应该都能覆盖到你接下来的使用场景。1. 环境准备装好 Git配好第一行身份电脑上能用git --version打出版本号是后面一切操作的前提。大部分发行版其实已经预装了 Git只是版本可能偏旧如果你需要新特性或者公司统一了版本要求就得自己装。很多人忽略的是装一个顺手顺手的工具链比背命令更重要。1.1 Git 安装三大平台一次到位Linux 用户走包管理器最省事。Debian/Ubuntu 系用sudo apt update sudo apt install git -yWindows 用户常见的是下载 Git for Windows 安装包它会自带一个 Git Bash 模拟环境很多人在 Windows 上敲 Linux 命令都靠它。macOS 上如果你装了 Xcode Command Line Tools系统会自带 Git想主动管理版本就用 Homebrewbrew install git这里有个容易被忽略的细节安装完成后先验证一下版本再看一下默认配置到底在哪一层。很多后续出现“明明配置了却不起作用”“这个命令为什么找不到”的问题根源都在作用域和安装路径上。确认安装成功git --version输出类似git version 2.39.2就说明环境通了。国内网络下载慢的话可以考虑用国内镜像站拉安装包但为了安全尽量去官网或可信的包管理器源别随意从第三方网站复制粘贴脚本。1.2 初始配置名字、邮箱、换行符与默认编辑器Git 提交时会把用户名和邮箱写进提交记录里所以装完第一步是配置身份。这里的作用域有三个层级--system对应整台机器--global对应当前系统用户--local只对当前仓库生效。日常开发一般只用--global但如果你要处理多个工作身份比如公司的 GitLab 和个人的 GitHub就需要学会用--local做覆盖。git config --global user.name 你的名字 git config --global user.email youexample.com这里有个实际切换身份的技巧在企业仓库目录里如果想临时覆盖全局身份直接在当前仓库下配置就行git config --local user.name workname git config --local user.email workcompany.com除了身份信息还有两个高频配置。第一个是默认编辑器Git 在执行commit --amend或rebase时需要打开编辑器默认可能是 vim。如果不怕 vim 还好怕的话可以设置成 VS Codegit config --global core.editor code --wait第二个是换行符处理。Windows 和 Linux/macOS 的换行符不同Git 提供core.autocrlf做自动转换。在 Windows 上多建议设置git config --global core.autocrlf true在 mac/Linux 上则建议input防止文件被反复修改换行符导致 Diff 混乱。还要检查当前所有配置git config --list如果你想看某个具体配置是怎么生效的加上作用域来看最靠谱git config --global --list只看当前用户的配置git config --local --list看仓库级别配置。2. 日常命令跟踪、暂存、提交与日志这部分是使用频率最高的命令。但在深入之前一定要先建立 Git“三层结构”的心智模型工作区working directory、暂存区staging area/index、版本库repository。你改文件改动先落在工作区通过git add把改动挪进暂存区再通过git commit把暂存区固化成一笔新提交。平时说的“提交了”其实就是让改动永久落在了版本库里。2.1 看状态与暂存git status 和 git add我在项目里习惯随时敲git status。它不是一条花哨的命令但能准确告诉你当前是在哪个分支、有几个文件改动、哪些改动还没被暂存。这个命令的输出就是你的“位置感”尤其协调多人代码时几乎所有误操作都源于“我以为自己在另一个分支上”。常见的暂存姿势有这几种git add . # 把当前目录的所有改动加入暂存区 git add src/app.js # 只暂存某个文件 git add docs/ # 暂存整个目录 git add -p # 分批次暂存同一个文件的多个改动块git add -p是进阶用法但非常实用。当你在同一个文件里改了两处逻辑只想把第一处提交、第二处留着继续调时它能让你一个 hunk 一个 hunk 地选择暂存哪些。配合git diff看改动细节就能做到非常干净的提交历史。2.2 提交与修正git commit 和 git commit --amend最基础的提交命令是git commit -m fix: 修复登录超时问题但我更推荐熟练后使用多段信息。git commit不加-m会打开默认编辑器你可以在里面写多行提交信息。规范一点的提交信息格式是type(scope): subject比如feat(auth): 增加短信登录、fix(cart): 修复删除商品后数量未刷新。这样的历史扫过去一眼就能明白每个提交改了哪块。经常出现的操作是提交后发现少加了一个文件或者提交信息里有错别字。这时候就该git commit --amend出场了。它可以修改最近一次提交的提交信息也可以把新的暂存改动合进上一次提交git add src/forgot.js git commit --amend -m fix: 修复忘记密码发送邮件的异步问题--amend的本质是用一个新的提交对象替换原来的最近提交。所以说到底它会改写历史在本地用没问题但如果这个提交已经被你 Push 到远程、且其他人已经拉取过就不要随便用。在多人共享分支上使用 amend 会把别人的提交历史搅乱所以补丁式修正是本地提交专用。2.3 日志姿势git log、git show 与 git blame提交记录是项目最直观的“时间线”但默认的git log输出太满。我常用的查看姿势是git log --oneline --graph --all--oneline压缩成一行--graph显示分支的合并图--all会包含所有分支的提交记录。想找某个人的提交可以加--authorname想看最近几条可以加-5想查某个文件的历史则用git log --follow -- src/lib/parser.js如果你要查某一行代码是谁在哪个提交里改的git blame是最直接的git blame src/order.ts它会把每一行对应的 commit 哈希、作者、时间都列出来排查“这行是谁加的”时特别管用。配合git show commit看某一个提交的完整改动定位问题的效率会高很多。3. 分支与合并多线开发的分叉与收拢分支是 Git 的一大核心能力。没有分支时大家挤在一根主线上代码很容易互相踩踏有了分支你可以放心地开一条新线改需求等验证完成再并回主线。这也是从单人开发走向多人在线协作的必经之路。3.1 分支的查看、新建、切换、重命名与删除基础命令大家都会但有几个细节值得展开。git branch # 查看本地分支 git branch -a # 查看本地远程分支 git branch feature/pay # 新建分支 git checkout feature/pay # 切换分支 git switch feature/pay # 切换分支推荐的新用法推荐优先使用git switch和git restore因为checkout身兼多职容易被误导。git switch -c feature/order是新建并切换一步到位git branch -m old-name new-name可以重命名分支删除本地分支用git branch -d feature/finished注意-d和-D的区别-d只有在分支改动已合并且没有被推送时才允许删除-D是强制删除。简单理解-d会帮你确认这分支没有丢失必要的工作-D则是“我有信心不要了”。刚上手时建议尽量用-d反而会逼你检查分支状态。3.2 分支合并merge 与 rebase 怎么选把一条分支的改动并回目标分支最朴素的方式是git checkout main git merge feature/paymerge会保留两个分支各自的历史并为合并行为生成一个“合并提交”。优点是不改动已有提交安全缺点是提交图上会出现很多分叉和交错的点历史不够线性。如果想要一条更线性的历史可以用rebasegit checkout feature/pay git rebase mainrebase的原理是把当前分支上的改动“摘下来”重新放到目标分支的最新提交后面。结果是整个分支像一条直线阅读起来很舒服。代价是它会改写当前分支上的提交哈希所以永远不要对已经推送到公共远程分支、且别人也在用的提交执行 rebase。我自己的习惯是功能分支在自己手上、没有提交到公共远端的多用 rebase 保持整洁一旦涉及多人共用或要保留真实开发过程的恢复到 merge并配合--no-ff保留合并节点git merge --no-ff feature/pay--no-ff会强制生成一个合并提交好处是让后人知道这里曾经有过一条功能分支被合并沉淀过而不是简单地快进。3.3 合并冲突的定位与解决只要多人同时改同一区域迟早会遇到冲突。冲突的本质是 Git 无法自动判断哪边是对的所以它把问题交给你来定。遇到冲突时先别慌。git status会列出“Unmerged paths”的文件打开这些文件就能看到冲突标记 HEAD 你当前分支的版本 合并进来的分支版本 feature/pay手动保留需要的部分、删掉标记行然后重新暂存git add src/conflict.ts git commit如果你想在这一步放弃合并可以用git merge --abort这个方法会回到合并之前的状态。解决冲突时建议先用git diff理解两边的改动意图不要图省事直接“全部保留”。冲突往往不是“A或B选一个”而可能是“A的新增逻辑 B的修复逻辑应该同时存在”所以多花几分钟读上下文比事后修线上 Bug 便宜得多。4. 远程协作clone、push、pull 与免密登录进了公司仓库、参与开源项目你的 Git 操作就离不开远程仓库了。远程协作核心就两件事把代码拉下来和把代码推上去。其余细节基本都围绕这两件事转。4.1 从远程克隆、拉取、推送到远程拿到一个仓库链接最常用的命令是git clone gitgithub.com:user/project.git克隆下来之后本地会自动建立一个origin指向远程仓库。日常和远程同步有两个命令量级不一样git fetch origin # 只把远程分支和提交抓到本地不改变工作区 git pull origin main # 等于 fetch merge会直接把远程改动合并到当前分支很多人上来就直接用git pull其实“先git fetch再看git diff再决定怎么合”是更稳的顺序。因为fetch只是下载数据不会自动改你的工作区你可以先看看远程分支更新了什么避免被莫名合并一个你不想要的大改动。推送则是git push origin main第一次推送新分支时需要建立上游关联git push -u origin feature/pay-u会记住本地分支与远程分支的对应关系往后这条分支直接敲git push就行。如果你想删除远程分支有几种写法git push origin --delete feature/old git push origin :feature/old第二种写法在旧文档里很常见本质是推送一个空分支来“清空远程分支”。4.2 SSH 免密密钥生成与三种配置方式每次推送都要输用户名密码确实烦人尤其一天要 push 十几次的人。免密最常见的路径是配置 SSH 密钥。先检查本地有没有ls ~/.ssh没有就生成一个ssh-keygen -t ed25519 -C youexample.com生成后把~/.ssh/id_ed25519.pub的内容复制到代码托管平台的 SSH Keys 设置里。然后验证ssh -T gitgithub.com能输出欢迎信息就说明通了。之后仓库地址尽量用 SSH 格式gitgithub.com:user/project.git就再也不用输密码。如果你更习惯 HTTPS 地址也有两种免密方式。一种是启用系统凭据管理器git config --global credential.helper store这样第一次输入密码后会被明文保存在~/.git-credentials文件里。另一种是用缓存方式git config --global credential.helper cache --timeout7200缓存两小时内免密安全度比明文存储高一些。在公司环境里多推荐第二、三种因为安全性更好。SSH 一旦配置成功后续不用维护账号密码而且也不容易受平台登录策略变动影响。4.3 远程分支查看与跟踪关系远程协作最怕“不知道本地分支对应的是哪个远程分支”。查看跟踪关系用git branch -vv git remote show origingit branch -vv会在每个本地分支旁边标注它跟踪的远程分支比如main [origin/main]一眼看清本地和远程的连接关系。如果你在本地新建了一个分支想让它与远程已有的分支关联可以这样git branch --set-upstream-toorigin/feature/pay feature/pay或者用更简洁的git push -u origin feature/pay关于远程分支的“删除本地但保留远程”和“删除远程但保留本地”的边界新手经常混淆。规则其实很简单git branch -d操作本地git push origin --delete操作远程两者互不影响。5. 撤销与后悔药reset、revert、stash“刚提交完就后悔”几乎是 Git 使用者的宿命。好在 Git 提供了多档后悔药但每一档的撤销范围、安全边界都不一样。用错了一档可能会丢东西所以这道命令一定要理解透。5.1 reset 的三个模式soft、mixed、hardgit reset的核心动作是把当前分支的 HEAD 指针往回移动并配合参数决定怎么处理暂存区和工作区。git reset --soft HEAD~1 # 移动 HEAD但保留暂存区和工作区 git reset --mixed HEAD~1 # 默认模式移动 HEAD清空暂存区但保留工作区 git reset --hard HEAD~1 # 移动 HEAD彻底丢弃暂存区和工作区改动用生活化类比--soft像按了倒退键但人还没走--mixed像把所有东西从包里倒回桌上--hard像按了格式化所有未提交的改动直接消失。实际场景里--soft最常用在“我想把最近几个琐碎提交合并成一个再重新提交”时。先git reset --soft HEAD~3然后git commit全部重新提交成一个干净的新提交。--hard只在确定要把工作区改动全都扔掉时用比如你拉了一堆实验性改代码想全部清掉。5.2 revert远程分支上的安全撤销如果已经成为共享提交或者改动已经推送到了远程就不要再reset了因为reset会改历史别的同事已经基于旧的提交继续加新提交你这边硬改历史会让他们抓狂。正确的姿势是git revertgit revert commit-hash它会生成一个“反向提交”把某个提交的改动撤销掉并保留一条新的提交记录。好处是历史完全保留原来的提交还在只是多了一条“撤销它”的记录。这在多人协作分支上是唯一比较友好的撤销手段。如果你要撤销一个 merge 提交还需要额外加参数git revert -m 1 merge-commit-hash-m 1的意思是保留第一父提交作为主线。这个参数确实容易踩坑没加会提示“这是合并提交请指定 -m”。遇到这种场景先查清提交结构再操作。5.3 stash临时工作保存还有一种场景你正在功能分支上改到一半老板让你切到另一个分支看线上 Bug。改动还没到值得提交的程度但直接切走又怕弄乱。这时用git stashgit stash # 保存当前工作区改动到暂存栈 git stash list # 查看暂存列表 git stash pop # 恢复最近一次保存的改动 git stash show # 查看保存内容如果你改了代码但还没git addstash默认会保存已暂存和未暂存的修改但不保存未跟踪文件。想连新文件一起收进去就加-ugit stash -u我个人的习惯是切换分支前若有半成品一律先stash再切绝不带着一堆改动直接切。因为 Git 的切换规则虽然会尽量保留改动但遇到目标分支和当前分支对同一个文件有冲突时切换会被直接打断处理起来更麻烦。6. 高频踩坑常见报错与排查速查不管多熟练Git 一定会出各种报错。有些报错看着吓人其实一分钟就能解决有些则埋着目录结构或身份信息的问题。我把几个高频报错整理成排查思路省得你再靠搜索引擎翻半天。6.1 致命错误fatal: not a git repository 及其同类fatal: not a git repository (or any of the parent directories): .git是很常见的报错。它的含义是在当前目录往上找都没找到.git目录。常见原因有三个你确实站在一个有 Git 仓库的目录之外目录是空的还没执行过git init.git目录被误删或损坏。排查思路是先用ls -la | grep .git看有没有.git。如果没有要么切换到正确的仓库目录要么执行git init初始化。如果原本有.git但突然不见了多半是复制目录时用了不同步的方式或者被某些工具误删了。另一个高频问题叫“detached HEAD”状态。这时 Git 提示你在“游离的 HEAD”上也就是说当前没有指向任何分支只能看到某个具体提交的对象。经常发生在你git checkout commit-hash的时候。在这个状态下做的提交不会属于任何分支很容易“丢”。碰到的解法是立即用一个分支接住git switch -c temp-detached在这个临时分支上把工作保存起来再合并到正常分支。6.2 认证失败Permission denied 与 Terminal prompts disabled推送代码时遇到的报错五花八门但最终指向大多是“认证失败”。如果报错内容是remote: Invalid username or password.且你在用 HTTPS 方式连接那么核心是账号密码或凭据缓存问题。先确认远程地址git remote -v如果是https://开头考虑切换到 SSH 地址避免反复输密码git remote set-url origin gitgithub.com:user/project.git如果是下面这种fatal: could not read Username for https://github.com: terminal prompts disabled说明 Git 没有找到可交互的终端或者凭据 helper 没配好。常见于某些自动化脚本里。短期内你可以在命令行里用GIT_ASKPASSssh之类的方式临时强制它弹密码框但长期方案还是 ssh key。6.3 分支远落后于远端、误删提交、仓库体积膨胀日常开发里还有几类“慢性病”本地分支远远落后于远端经常 pull 不动。此时可以先用git fetch --prune origin把远程已删除的分支信息清理掉再git pull --rebase保持线性更新。误删了提交。误删之后别慌先用git reflog查看分支指针的历史轨迹找到误删提交的哈希然后用git reset --hard hash拉回来。reflog默认会保留 30-90 天的记录是找回“本地丢失提交”的主要手段。仓库体积越来越大。Git 不适合保存大体积的二进制文件。如果早期不小心提交过几十 MB 的大文件历史记录会一直拖着它。最简单的前置防护是准备一份.gitignore把构建产物、临时文件、依赖目录挡在外面。如果已经污染了历史可以使用git filter-repo做历史清理但也意味着要重新写所有协作者的历史这事一般得团队统一、选低峰时段操作。结尾一个小技巧最后分享一个切身体会。Git 命令本身并不难背难的是在不同场景下立刻选出最优的那一条。我给自己的习惯是日常任务尽量用git status和git diff看清楚自己的位置再做操作涉及撤销时先分清“这个提交有没有同步给其他人”涉及合并时先问自己是想要“聚合历史”还是“线性历史”。这几条原则一旦想清楚Git 就从一个命令集合变成了一套思维方式。还有一个非常推荐的小技巧把高频操作写成 shell 别名。比如我把git add -p配成ga -p把git log --oneline --graph --all配成glg输入负担低也少了敲错单词的烦恼。Git 命令大全的内容不在多而在于你真正记住并在实战中用过的那些命令组合它们才是属于你的命令大全。
返回列表