资讯动态

Git客户端使用教程:提交、分支合并、冲突处理与撤销回退

发布时间:2026/10/28 3:33:12 来源:尧图企业网站定制
拿 Git 客户端这件事来说我见过太多人卡在同一个地方命令背了一堆一到真正提交代码就手抖怕点错按钮把同事的分支搞乱怕push报一屏红字看不懂怕合并冲突里那串像乱码。这篇内容就是给这类状态的人准备的不管你是刚进项目组第一次接触版本管理还是用了两三年但一直靠复制同事的命令活着都能从里面找到能直接抄的部分。我会从 Git 客户端的整体使用链路讲起——安装配置、日常提交、分支合并、撤销回退再到新手最常撞上的那批报错每个环节都掰开讲清楚为什么这么做同时把我在实际项目里踩过的坑和绕过的弯路一并摆出来省得你重复交学费。1. Git 客户端的整体认知与选型思路1.1 先把四个区域的模型立起来新手用 Git 出问题九成不是命令记不住而是脑子里没有一张东西现在在哪儿的地图。Git 的管理模型其实就四个位置工作区你编辑器里能看到、能改的文件、暂存区Index准备进下一次提交的内容清单、本地仓库.git目录里那堆对象提交真正落地的地方、远程仓库团队共用的那一份。你在客户端里点的每一个按钮本质都是在这四个位置之间搬运文件。这个模型听起来抽象打个生活化的比方工作区是你家厨房的操作台菜切了一半、调料摆得到处都是暂存区是一个托盘你把这次要端上桌的菜挑出来放上去本地仓库是冰箱托盘上的东西封好、贴上标签存进去远程仓库则是公司食堂的公共冷柜你把冰箱里的东西送过去别人才能取用。git add是往托盘上放菜git commit是把托盘封进冰箱并贴标签git push是把冰箱里的东西送到公共冷柜git pull是从公共冷柜取回来。为什么一定要把这张图刻进脑子因为新手最典型的两类事故都源于没有这张图。第一类是我明明改了代码为什么同事拉下来没有——改动还在工作区连托盘都没上更别说进冰箱了。第二类是我提交了一堆不该提交的东西——比如本地调试用的配置文件、临时日志、编译产物因为用了git add .一把梭全被塞进托盘。这两个问题的解法都不在命令层面而在对区域模型的理解上。我个人的习惯是动手前先跑一次git status看清楚每个文件现在处在哪个格子。输出里Changes not staged for commit是工作区里改过但没上托盘的Changes to be committed是已经在托盘上的Untracked files是 Git 压根还没开始管的新文件。把这三行读懂比背二十条命令有用得多。1.2 命令行与图形客户端怎么分工关于该用命令行还是图形客户端这个争论我的结论很直接两个都要会但主力用一种另一种当救命工具。图形客户端的优势在于可视化的提交历史和差异对比看分支图、看某一行代码是谁在哪个提交里改的、看两个分支差了多少个提交鼠标点两下就清楚了用命令行反而费劲。命令行的优势在于精确和可复现——git reset --soft HEAD~1这种操作图形客户端里对应哪个按钮、点下去到底是软重置还是硬重置很多人根本分不清一旦点错就是真丢代码。选择具体客户端时我建议按这三条来筛是否清晰展示暂存区。好的客户端会把未暂存和已暂存分成两栏让你逐个文件、甚至逐行挑选要提交的内容。只能一键全部提交的客户端长期用下来一定会培养出乱提交的习惯。是否保留命令预览。部分客户端在执行操作时会显示等价的命令行这对学习极有帮助用着用着就把命令记住了。冲突解决界面是否好用。三方对比、逐块选择保留哪一边这个功能在合并冲突时能省掉大量手工编辑。至于具体装哪一款市面上的主流图形客户端功能差异不大挑一个界面顺眼、更新活跃的就行不必纠结。真正需要花时间的是理解每个操作背后的 Git 语义工具只是外壳。提示不管用哪个客户端都建议同时装一份命令行环境。图形客户端出问题时命令行是你唯一能确认到底发生了什么的地方。1.3 新手最容易走偏的三个认知第一个认知偏差是Git 等于备份。不少人把提交当成 CtrlS一天提交几十次每次提交信息写update、修改、1。这样做的后果是历史记录彻底失去价值——出问题时你想回滚到某个可用状态面对一屏update根本无从下手。提交应该是一个有意义的逻辑单元修了一个 bug、加了一个功能点、重构了一个函数各自成一次提交。第二个偏差是分支是很危险的东西。恰恰相反分支是 Git 最安全的机制。在独立分支上做实验搞砸了删掉就行主干一点不受影响。真正危险的是在主干上直接改、直接提交、直接推送出问题没有缓冲。我带的项目里主干分支一律设置保护任何人都必须走分支加合并的流程。第三个偏差是报错就是操作失败。Git 的大量报错其实是保护机制在拦你比如push被拒是因为远程有你本地没有的提交硬推上去会覆盖别人的工作。看懂提示里让你做什么比慌着重试有用。2. 客户端安装与初始配置的实操细节2.1 装完之后必须改的四项配置安装过程没什么可讲的一路下一步即可。真正决定后续体验的是装完之后的初始配置。很多人装完就直接开工结果第一周就撞上中文文件名显示成八进制转义、Windows 和 Mac 同事互相提交导致整个文件全部标红、每次推送都要输密码这些事。下面这四项装完立刻配。身份信息这是每次提交都会写进历史里的配错了以后要改历史会很麻烦git config --global user.name 你的名字或代号 git config --global user.email 你的常用邮箱邮箱建议和代码托管平台上注册的邮箱保持一致否则平台无法把你的提交和账号关联起来贡献图上不会显示。换行符策略这是跨平台协作的头号杀手。Windows 用 CRLF类 Unix 系统用 LF如果不统一一个在 Windows 上改了一行的文件提交到仓库里会显示整个文件每一行都变了代码评审时完全没法看。# Windows 环境 git config --global core.autocrlf true # macOS / Linux 环境 git config --global core.autocrlf inputtrue的含义是检出时转成 CRLF、提交时转回 LFinput是提交时转 LF、检出时不动。更稳妥的做法是在仓库根目录放一个.gitattributes文件把这套规则固化到项目里这样不管谁用什么系统、什么客户端配置行为都一致* textauto eollf *.png binary *.jpg binary中文路径显示不配这一项git status里中文文件名会显示成\346\226\207\344\273\266.txt这样的转义形式git config --global core.quotepath false默认分支名新建仓库时不再用历史遗留的master改成main和主流托管平台的默认约定对齐git config --global init.defaultBranch main顺手再配一个pull的默认行为避免每次拉取都弹提示git config --global pull.rebase false这一项选false表示拉取时用合并方式选true表示用变基方式。新手阶段建议先用false冲突处理起来更直观等熟悉了再考虑切到true保持历史线性。2.2 免密访问凭据管理与密钥的取舍每次推送都输账号密码用不了两天就会烦。两种免密方案各有适用场景说清楚区别你就不难选。凭据缓存方案配置简单适合个人机器# 把凭证交给系统凭据管理器长期保存 git config --global credential.helper manager # 或者临时缓存 15 分钟单位是秒 git config --global credential.helper cache --timeout900这种方式的问题是凭证和当前这台机器绑定换机器要重新配如果对安全有要求长期明文保存凭证也不是好主意。密钥方案生成一对密钥公钥交给托管平台私钥留在本地ssh-keygen -t ed25519 -C 你的备注信息一路回车即可如果想加口令保护可以在这里设置。生成后把公钥文件~/.ssh/id_ed25519.pub的内容整段复制粘贴到托管平台的密钥设置页面。验证是否配通ssh -T git你的托管平台域名看到欢迎信息就说明通了。密钥方案的优势是跨设备迁移方便、细粒度可控可以给不同项目配不同密钥缺点是初次配置的门槛稍高。注意私钥文件绝对不能提交到仓库也不能发给任何人。一旦私钥泄露等同于账号被接管。养成习惯把.ssh目录排除在任何同步和备份工具之外。2.3 仓库初始化与克隆的路径选择有两种起步方式选错了会在第一步就埋雷。本地已有代码要纳入版本管理cd 你的项目目录 git init git add . git commit -m 初始化项目结构 git remote add origin 仓库地址 git push -u origin main注意git add .之前一定要先写好.gitignore。我见过太多人先提交再补忽略规则结果编译产物、依赖目录、IDE 配置全进了历史后面清理起来要动历史重写非常折腾。从远程拉取已有项目git clone 仓库地址 # 只拉取最近一次提交适合大仓库快速查看 git clone --depth 1 仓库地址克隆会自动完成三件事下载全部历史、创建远程别名origin、检出默认分支。这里有个新手常问的点克隆下来之后想切换到别的分支用git switch 分支名就行不需要重新克隆。3. 日常提交链路的完整走法与细节3.1 从改代码到推送的六步标准流程日常开发里最高频的循环是这六步我把每一步的意图讲透你就能自己判断什么时候该跳过、什么时候不能省。第一步同步远程。开工前先git fetch拿到远程最新状态再用git status看看本地分支和远程差了多少git fetch origin git statusfetch只下载不合并比直接pull安全因为它不会在你没准备好的时候改动工作区。第二步建分支。除非是改一个错别字否则都建议开分支git switch -c feature/login-check分支名用类型/简短描述的格式比如feature/、fix/、refactor/一眼能看出这个分支在干什么。第三步看改动。提交前先看一遍自己改了什么这一步很多人会跳过然后就出现了提交了调试代码git diff # 工作区 vs 暂存区 git diff --staged # 暂存区 vs 上次提交第四步精细暂存。不要无脑git add .按文件挑甚至按代码块挑git add src/login.js # 交互式挑选可以按块决定是否暂存 git add -pgit add -p是我最推荐新手养成习惯的命令它会把改动拆成一个个小块逐块问你要不要提交这一块。用它你可以把一次修改里的功能代码和顺手改的格式分开提交历史会干净很多。第五步提交。提交信息的写法后面单独讲这里只说格式类型: 简短描述。第六步推送。首次推新分支要建立追踪关系git push -u origin feature/login-check之后直接git push即可。3.2 提交信息的写法与原子提交原则提交信息的价值在你需要排查问题时才会显现。想象一下半年后线上出故障你要找出是哪次改动引入的历史里如果全是update、fix bug那你只能一行行看diff工作量翻十倍。我用的格式很简单一句话标题加可选的正文git commit -m fix: 修复登录态过期后未跳转的问题 -m 原因是拦截器里判断条件写成了 导致过期时间点本身也被放过。改为 并补充了边界测试。标题控制在 50 个字符以内能概括这次改动做了什么正文说明为什么这么改而不是重复代码里已经能看出来的改了什么。类型前缀用固定的几个词团队统一后可以据此自动生成变更日志feat新功能、fix修复、refactor重构、docs文档、test测试、chore杂项。原子提交这个原则值得单独强调一次提交只做一件事。如果你在一次提交里既加功能又改格式还顺手重命名了几个文件那么当这个提交引发问题时你没法只回退其中一部分。反过来如果拆成三次提交回退就变得精确可控。实践中检验方法是如果你发现提交信息要用并且来连接两件事就该拆开。3.3 图形客户端里按钮背后的真实动作用图形客户端的人常有一个困惑界面上那么多按钮点下去到底发生了什么我把最常点的几个和对应命令列出来建议你在客户端里操作一遍的同时开着命令行跑git status对照看两次之后就有感觉了。客户端常见按钮等价命令实际作用范围Stage / Addgit add 文件把工作区改动放进暂存区Unstagegit restore --staged 文件把文件从暂存区撤回工作区改动保留Discard Changesgit restore 文件直接丢弃工作区改动不可恢复Commitgit commit -m暂存区内容写入本地仓库Amend / 修改上次提交git commit --amend重写最近一次提交会改变提交哈希Pullgit fetchgit merge拉取并合并远程改动Force Pushgit push --force覆盖远程历史高风险操作这张表里最需要警惕的是Discard Changes和Force Push。前者点下去没有任何确认你的本地改动瞬间消失Git 也找不回来因为压根没进过暂存区和仓库后者会把远程历史强行覆盖成你本地的样子如果别人在这期间推过代码那些提交就没了。团队协作中应该把强制推送的权限收紧或者至少统一成带保护的--force-with-lease它会在远程有你不了解的新提交时拒绝执行。4. 分支模型与合并操作的实战处理4.1 建立一套自己能说清楚的分支规则分支策略不需要多复杂但必须有而且团队里每个人都要能一句话说清我该从哪个分支切、切完往哪合。我见过太多小团队因为没定规则出现把功能分支合到测试分支又把测试分支合回主干的混乱局面。适合中小团队的规则可以压缩成三条主干分支main只接受通过评审的合并不直接提交开发过程在feature/xxx分支上从主干预最新代码切出修紧急问题时用fix/xxx分支合完立刻删。分支的生命周期应该短一个分支挂两周以上就会和主干严重偏离合并成本指数级上升。日常操作就这几条git branch # 列出本地分支 git switch main # 切到主干 git pull # 同步最新 git switch -c feature/xxx # 从当前切出新分支 git branch -d feature/xxx # 合并后删除分支 git push origin --delete feature/xxx # 删除远程分支删除分支时有-d和-D的区别小写d会在分支未合并时拒绝删除并提醒你大写D强制删除。建议一直用-d除非你非常确定那个分支上的提交不再需要。4.2 merge 和 rebase 的真实区别与选择这两个命令新手最迷糊我用一个具体场景说明。假设主线上有提交 A→B你从 B 切出分支后提交了 C→D同时这期间别人往主线推了 E。用mergeGit 会创建一个新的合并提交 F把两条线接起来历史图形是一个分叉再汇合的菱形。好处是完整保留了什么时候从哪切的、什么时候合的这个过程信息缺点是历史图会变复杂尤其分支多的时候像一团麻。用rebaseGit 会把 C、D 两个提交摘下来先接到 E 后面再依次重新应用结果是 A→B→E→C→D 一条直线。好处是历史干净易读缺点是 C 和 D 的哈希变了如果这两个提交已经被别人拉走过就会造成两边的历史冲突。我的实践原则是本地分支、还没推送到远程的提交用 rebase 保持整洁已经推送并被别人基于其工作的分支用 merge 保持安全。这条线画清楚基本不会出问题。# 拉取远程主干并用变基方式接入本地分支 git pull --rebase origin main # 或者手动操作 git fetch origin git rebase origin/main用 rebase 时如果中间某个提交产生冲突处理流程是解决冲突文件 →git add 文件→git rebase --continue。想中途放弃就git rebase --abort会完整回到 rebase 之前的状态这个逃生通道一定要记住很多人一遇到 rebase 冲突就慌了。注意绝对不要对已经合并进主干的分支做 rebase 后强推。历史被改写后其他人本地的引用全部错位后续操作会非常痛苦。4.3 合并冲突的完整处理流程冲突本身不可怕可怕的是慌。冲突的本质是同一个文件的同一区域两个分支做了不同的修改Git 无法替你决定留哪一边于是把两边内容都留在文件里让你人工裁决。冲突发生时文件里会出现这样的标记 HEAD 当前分支的内容 要合进来的分支的内容 feature/xxx处理流程固定四步。第一git status找出所有both modified的文件这就是冲突文件清单。第二逐个打开编辑删掉、、这三行标记把内容改成最终想要的样子——可以是保留一边也可以是两边合并后重写。第三git add 冲突文件告诉 Git 这个文件解决完了。第四git commit完成合并提交或者在 rebase 场景下用git rebase --continue。这里有几个实操心得值得说。不要用编辑器的接受当前/接受传入一路点过去尤其是在双方都改了同一段逻辑的情况下机械选择会丢掉一边的修复。解决完一定跑一遍编译或测试冲突解决正确但逻辑错误的情况非常常见比如一边改了函数签名、一边调用了旧签名文本上不冲突但代码跑不起来。冲突文件多的时候分批处理先git add已解决的剩下的慢慢来git status会实时告诉你还剩哪些。如果实在搞不定想重来git merge --abort或git rebase --abort可以完整回退到操作前状态工作区不会留下烂摊子。5. 撤销回退的四种武器与选用场景5.1 reset、restore、revert、stash 的边界新手问得最多的问题就是我搞砸了怎么回去。Git 提供了多个工具用错工具比不用更危险所以先把边界划清楚。git restore管工作区和暂存区不碰历史git restore 文件路径 # 丢弃工作区改动 git restore --staged 文件路径 # 从暂存区撤回改动保留 git restore --sourceHEAD~1 文件路径 # 把文件恢复成上一次提交的样子第一个命令要格外小心工作区改动一旦丢弃就找不回来因为从来没被 Git 记录过。git reset管提交历史三个档位的区别必须背下来git reset --soft HEAD~1 # 撤销上次提交改动回到暂存区 git reset --mixed HEAD~1 # 撤销上次提交改动回到工作区默认行为 git reset --hard HEAD~1 # 撤销上次提交改动直接丢弃记忆技巧是从保留程度想soft保留得最多改动还在托盘上mixed中间改动回到操作台hard一点都不留。--hard是最危险的那个执行前必须确认工作区没有未提交的改动。git revert管的是已经推送到远程的提交。它不删除历史而是生成一个新提交内容正好是撤销目标提交的改动git revert 提交哈希这是团队协作里撤销已发布提交的正确方式。你用reset把本地历史删了远程还在下一次推送必然冲突用revert则是往前加一步所有人都能正常拉取。git stash管的是临时把活儿存起来git stash push -m 调试到一半的样式调整 git stash list git stash pop # 取出并删除这条记录 git stash apply # 取出但保留记录典型场景是你正在改功能突然要切分支去修紧急问题但当前改动还不适合提交。stash把改动打包收起来工作区恢复干净处理完再取回来。5.2 reflog最后一道保险上面这些操作里最让人崩溃的是误执行reset --hard或者误删分支。这时候git reflog是救命稻草。它记录了 HEAD 的每一次移动包括提交、重置、合并、切换分支默认保留 90 天。git reflog # 找到误操作之前的那个哈希 git reset --hard 那个哈希我用这个功能救回过两次误删的分支。要点是发现搞砸了立刻停手不要再做新的操作直接查reflog。如果中间又做了多次操作找到正确位置会麻烦一些但通常还是能定位到。提示reflog只记录本地操作且只在本地存在。它不是备份方案重要分支该打标签就打标签该推远程就推远程。6. 新手高频问题速查与排查手法6.1 推送被拒、游离头指针、误提交的应对推送被拒提示 non-fast-forward。原因是远程有你本地没有的提交Git 拒绝覆盖。正确的处理顺序是先看差异再合并git fetch origin git log --oneline HEAD..origin/main # 看看远程多了什么 git log --oneline origin/main..HEAD # 看看本地多了什么 git pull --rebase origin main # 或 git merge origin/main git push绝对不要第一反应就用--force。硬推会覆盖远程如果那里面有同事的提交等于直接删了别人的工作。游离头指针detached HEAD。这个状态出现在你直接checkout到某个提交哈希或某个远程分支时此时 HEAD 没有指向任何分支你做的提交不属于任何分支切走就会丢失。解决方式是立刻基于当前位置建分支git switch -c rescue-branch如果是想回到之前的正常状态git switch -可以切回上一个分支。误提交了不该提交的文件。分两种情况。文件刚提交还没推送git rm --cached 敏感文件路径 git commit --amend如果已经推送了仅仅删除文件是不够的历史里还留着。需要从所有历史中清除这属于重写历史操作必须和团队沟通后统一执行否则所有人的本地仓库都会和远程不一致。预防永远优于补救——.gitignore在第一次提交前就写好。提交到了错误的分支。比如本该在功能分支上的提交落在了主干上# 在错误分支上记下提交哈希然后 git switch 正确的分支 git cherry-pick 哈希 git switch 错误的分支 git reset --hard HEAD~1cherry-pick是把某个提交单独摘过来应用的利器处理这类问题非常顺手。6.2 忽略规则失效与整文件变更的排查.gitignore 写了但没生效。这是最高频的困惑原因几乎总是同一个文件在写忽略规则之前就已经被 Git 跟踪了忽略规则对已跟踪文件不起作用。解决办法是先让它脱离跟踪git rm -r --cached 目标目录 git commit -m chore: 移除已跟踪的构建产物之后.gitignore才会对这个目录生效。改了 一行diff 显示整个文件全变。这是换行符不一致导致的。排查方式是看文件的实际行尾git ls-files --eol 文件路径输出里i/lf表示索引里是 LFw/crlf表示工作区是 CRLF。解决靠.gitattributes统一规则配好之后可能需要重新规范化一次git add --renormalize . git commit -m chore: 统一换行符文件名大小写改了但 Git 没反应。在大小写不敏感的文件系统上比如 Windows 默认配置Git 可能识别不到仅大小写变化的改名git mv 旧文件名 新文件名用git mv而不是在文件管理器里直接重命名能避免这类问题。克隆下来文件权限全部变化。常见于跨系统协作某一边的可执行位设置不同。检查git config core.filemode必要时设为false忽略权限位差异。7. 几条来自实际项目的协作约定7.1 提交前的自查清单我带过的项目里最后沉淀下来一份很短的提交前自查清单贴在团队文档最上面新人进来第一周照着做出问题的概率明显下降git status确认没有误加的文件尤其是.env、日志、编译产物、IDE 配置目录。git diff --staged通读一遍暂存内容确认没有调试用的console.log、写死的测试地址、注释掉的整段逻辑。分支名和提交信息能让人看懂在做什么不用打开代码就能大致判断。推之前git fetch一次看看远程有没有新东西避免推送被拒后手忙脚乱。这几条看起来啰嗦但实际上每次花不到两分钟。和事后回滚、改历史、跟同事解释比起来划算得多。7.2 我踩过的坑和个人体会说几个具体教训。第一不要在没提交的情况下执行reset --hard。我有一次调试到一半想把工作区弄干净重来顺手执行了硬重置结果半小时的改动全没了。从那以后我形成了一个固定动作任何破坏性操作前先git stash一下多一层保险成本几乎为零。第二分支不要挂太久。曾经有个分支拉了三周没合并最后合并时冲突文件三十多个解决了整整一天还引入了两个隐蔽的逻辑 bug。现在的做法是尽量把大功能拆成小块两三天合一次主干冲突少、心理负担也小。第三图形客户端的一键提交全部是效率陷阱。它让你提交得很快也让你提交得很脏。我建议哪怕用图形客户端也坚持逐个文件勾选慢慢就形成了对改动范围的敏感度。第四遇到看不懂的报错先把完整输出复制下来搜一搜别急着试命令。Git 的报错信息其实写得相当清楚大部分都明确告诉了你下一步该做什么比如 hint: Updates were rejected because the remote contains work that you do not have locally这句就是让你先拉取。读懂提示比盲目试错效率高得多。最后分享一个我觉得收益最高的小习惯给自己的log配个别名用图形化的方式看历史。git config --global alias.lg log --oneline --graph --decorate --all之后git lg就能看到一张带分支线条的提交图哪个分支从哪切出来、合并点在哪一目了然。新手阶段多看看这张图脑子里的分支模型会越来越清晰很多操作该不该做看图就能判断出来。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑