刚进公司实习那阵子带我的老哥把仓库一拉劈里啪啦打了一串 git checkout -b feature/xxx然后留下一句“以后代码都走这个分支写完提交、推上去、建 Merge Request有问题喊我”人就走了。我当时是真懵——大学里做课程设计也用过 Git但无非就是 add、commit、push 三连到了多人协作的仓库里什么分支策略、冲突标记、amend 改写历史、stash 临时保存全都变成了一锅粥。为了不再当那个“把 main 弄坏的人”我把实习第一个月踩过的坑和用顺手的命令整理成了这篇实战笔记。它不是从 Git 原理讲起的教科书而是给刚接触 Git 的实习生、刚转正的新人以及那些“看了很多教程但到了真实仓库还是不敢下手”的人一份可以照着抄的干活指南。1. 先把环境搞定安装、初始化配置与镜像源1.1 Windows / macOS / Linux 的三种安装姿势Windows 上安装 Git 最简单的方式就是去官网下载安装包一路 Next。但有几个选项值得注意选择调整 PATH 的时候建议选第二项“Git from the command line and also from 3rd-party software”这样你不仅能在 Git Bash 里用 git在 PowerShell、CMD、以及 IDEA 和 VS Code 的终端里也能直接敲 git 命令换行符转换建议保持默认的第一项“Checkout Windows-style, commit Unix-style line endings”这个选项对大部分团队都最省心。如果官网下载速度不太理想可以改用清华 TUNA 开源镜像站的 Git 发布目录版本和官方同步下载体验会好很多不用到处找乱七八糟的“一键安装包”。macOS 用户如果有 Homebrew一条 brew install git 就搞定了Linux 用户根据发行版不同执行 apt install git 或 yum install git 都可以。装完之后打开终端输入 git --version能输出版本号就说明环境没问题。另外Windows 上还会有人习惯用“小乌龟”TortoiseGit 这种 GUI 工具右键就能提交、拉取确实方便但我真心建议命令行基础别丢。原因很简单实习的时候别人随手给你甩个命令你得能看懂他在干什么线上出问题排查的时候图形界面往往不如命令行直接。1.2 装完马上要做的全局配置Git 安装完并不是“能用了”第一件事是配置身份信息否则提交记录里显示的是随机生成的 unknown 用户代码评审的时候别人都不知道这条提交是谁做的。需要执行git config --global user.name 你的名字 git config --global user.email 你的企业邮箱名字建议用真实姓名或公司内部 ID邮箱最好用公司邮箱因为很多企业内部的 GitLab/Gitee 会通过邮箱和账号关联个人信息没对上提交就没法统计到你的名下。配置完之后可以用 git config --list 查看当前所有配置确认一下有没有遗漏。还有一个容易被忽略的配置是换行符。Windows 上文件默认用 CRLF 换行而 Linux、macOS 习惯用 LF如果没有统一规则你改一行代码Git 可能会把整个文件标记为修改diff 看起来巨大无比reviewer 会崩溃。团队一般会约定 core.autocrlf 行为如果你不太确定可以在 Windows 上设置 git config --global core.autocrlf input尽量让提交到仓库的文件统一使用 LF。另外建议配一下默认分支名 git config --global init.defaultBranch main这样以后 git init 创建的分支就叫 main不至于每次还要手动改名。这套东西配完后面会省掉一堆莫名其妙的麻烦。2. 每天都要用的核心命令状态、提交、改动撤销2.1 先学会看状态status、diff、log实习第一天带教师兄跟我说“80% 的 Git 问题都是因为没搞清自己现在在哪个状态。”这句话我现在都记得。Git 里有三个基本区域工作区是你电脑上看到的文件暂存区是你 git add 过的东西本地仓库是已经 commit 的版本记录。我用一个生活化比喻帮自己记工作区是草稿纸暂存区是待办清单本地仓库是归档柜。写代码就是在草稿纸上写写画画写清楚一部分就打勾放进待办清单最后一起归档到柜子里。所以最该养成的习惯是随时 git status。它会告诉你当前在哪个分支、哪些文件修改了、哪些是新文件还没跟踪、哪些已经加到暂存区。提交之前再用 git diff 看看未暂存的具体改动用 git diff --cached 看已暂存的改动确认你提交的就是你想提交的别把调试输出、临时代码、本地配置混进去。查看历史也有技巧。git log 默认输出很长我更喜欢用一整行带分支图的命令git log --oneline --graph --decorate -10这样能看到最近 10 条提交每条一行还能看清分支从哪里分出来的、当前 HEAD 指向哪里。排查“这个改动是怎么进来的”这种问题这命令比 UI 工具高效太多了。2.2 提交与修正add、commit、commit --amend新人的常见操作是 git add . 一把梭把所有文件全加进去再 commit。我的建议是放弃这个习惯至少做到看一眼 git status 再决定加哪些文件。比如只提交核心代码就把相关文件一个个加git add src/order/OrderService.java。如果把 IDE 的 .idea 目录、target 目录、编译产物也一起 add 了后面再想补个 .gitignore 都会多出很多事。提交信息同样重要。别写“update”“修改了点东西”至少要让人能从信息里知道这次改动做了什么。我一般按团队规范写比如 feat: 新增订单导出功能、fix: 修复订单超时未回滚的问题。这种写法在 MR 列表里扫一眼就能定位到对应提交效率完全不同。提交完之后如果发现漏了个文件或者 message 写错了可以用 git commit --amend 来补。举个例子你刚提交了“feat: 新增登录接口”突然发现还有个常量文件忘了加直接git add 忘加的文件 git commit --amend --no-edit这样不会多一条“补文件”的提交而是把文件并进上一条提交里提交信息保持不变。如果连 message 都想改就把 --no-edit 换成 -m 新的提交信息。这里必须要提醒amend 本质是“用一条新提交替换旧提交”会改写提交哈希。如果你的提交还没 push 到远端随便用但如果已经 push 了并且可能有同事基于这条提交拉了分支那千万别随便 amend。真遇到已经 push 又需要 amend 的情况只能考虑强推但强推之前必须和团队成员确认清楚后面我会在排障章节专门讲。2.3 撤销操作restore、reset 的正确姿势新人最怕的是“改坏了怎么回退”。Git 给的能力很多但每个操作的危险程度不一样。git restore 文件可以把工作区某个文件的未暂存修改直接还原相当于按了撤销键git restore --staged 文件则相反是把已经 git add 的文件从暂存区拿出去但保留在工作区的改动这个很常用比如发现某个文件不该提交你只要取消暂存就行。如果错误地提交了本地代码想撤销最近一次 commit 但保留所有改动用 git reset --soft HEAD~1。撤销 commit 并把工作区、暂存区都回退到之前的状态用 git reset --mixed HEAD~1这也是默认参数。至于 git reset --hard HEAD~1会连工作区改动一起丢掉非常危险属于“不可找回”的操作。我在实习期间给自己定了一条铁律只能对自己正在开发的个人功能分支用 reset --hard绝对不对主线分支用。如果你发现改动丢了又没备份先别急着重写看看终端还留着多少历史记录实在不行找同事看他们的本地版本很多时候还能捞回来。2.4 做了一半要先走stash 帮你保存现场写代码时经常遇到这种情况feature 分支写到一半线上突然报了个 bug需要马上切换到另一个分支处理。直接切分支是不行的因为工作区有未提交的改动Git 会拒绝切换除非你硬切带过去那更乱。正确做法是先把现场暂存起来git stash push -m 订单导出功能开发中然后工作区会变得干干净净可以随便切分支。处理完 bug 回到原分支用 git stash list 查看暂存的记录再用 git stash pop 把改动恢复出来。如果恢复之后还想保留 stash 记录那就用 git stash apply。多条 stash 需要指定用哪一条比如 git stash pop stash{1}。这里有两个小坑。第一git stash 默认不会把未跟踪的新文件藏起来如果你的功能里新增了几个文件记得用 git stash push -u 连同未跟踪文件一起暂存。第二stash pop 恢复时如果当前分支的代码和你暂存前改动过的地方产生冲突Git 会报冲突让你手动解决解决之后原来的 stash 条目还在需要 git stash drop 手动清理不然 Stash 列表会越堆越多。3. 分支管理与团队协作合并、冲突、代码评审3.1 分支是隔离房间名字要能看懂实习之后我才真正理解分支的意义。它像是仓库里的隔离房间你在 feature/ 房间里随便折腾不会影响正在运行的 main 房间。查看本地分支用 git branch创建并切换分支常用 git checkout -b feature/xxxGit 2.23 以后也可以 git switch -c feature/xxx。公司里普遍的做法是主干分支受保护任何人都不能直接往 main/master 上 push只能通过 MR/PR 审核合并。所以实习生要养成的第一个分支习惯就是开一个语义明确的功能分支。命名建议见名知意feature/user-login、fix/order-timeout、hotfix/20230603-security。看到分支名你就知道这段代码对应哪个需求或者哪个线上问题不需要去翻提交记录。如果同事告诉你“去把远端某个分支拉下来看看”先用 git fetch origin 把远端引用更新到本地再用 git branch -r 查看远端都有哪些分支。实际开发中很少需要自己去 git init 建空仓库更多是 git clone 远端的项目下来改。3.2 日常同步pull --rebase 还是 merge多人协作最重要的其实是“及时同步”。你写代码的这段时间仓库可能已经多了好几条别人的提交。最简单的同步方式是 git pull它等价于 git fetch git merge。但很多团队为了保持提交历史是一条干净的直线会约定用 git pull --rebase。rebase 的意思是把本地尚未推送的提交先“摘下来”拉取远端最新提交再把这些本地提交往最新的代码上重新“放”一遍。好处在于历史没有多余的 merge commit看图特别清爽。风险在于重放时可能产生冲突你需要逐个解决然后 git add 冲突文件再 git rebase --continue。如果发现 rebase 过程中把自己绕晕了可以用 git rebase --abort 回到 rebase 之前的状态当作无事发生。实习生的建议是先问团队有没有统一约定。团队说用 rebase 就 rebase说用 merge 就 merge别自己在中间乱切换。重点不是哪个更好而是保持统一避免提交历史一团乱麻。3.3 合并冲突实战别怕逐行处理就行冲突大概是新人最怕的词但实际上只要你理解了规则它反而没那么可怕。冲突的本质是两个人改了同一处代码Git 不知道该听谁的于是把两边的代码都保留下来让你来当裁判。冲突出现时冲突文件里会看到一串标记 HEAD 你这一行代码 对方那行代码 feature/xxx处理步骤如下先用 git status 找到冲突文件然后打开文件搜索 。每一对标记之间就是一处冲突你需要和同事确认这处逻辑到底应该保留哪边还是要两边拼起来然后把冲突标记全部删掉。处理完所有冲突后执行 git add 文件再执行 git commit 完成合并或者如果是在 rebase 过程中就执行 git rebase --continue。我实习时踩过最典型的坑是为了图快直接 git checkout --ours 或者 --theirs 整个文件地取一边结果把同事的修改覆盖了。这种盲目操作非常危险一定不是遇到冲突的好解法。正确做法是逐行看实在不确定就找人一起过一遍。流程上想少冲突只能靠小步提交、及时同步、尽量只动自己负责的文件没有别的偷懒办法。3.4 从本地分支到 Merge Request标准交付流程一套标准的交付流程能够让你在正式入职后少挨很多骂。功能开发完成后先把代码提交到本地分支然后推送远端git push origin feature/user-login推上去之后去 GitLab、Gitee 或者 GitHub 的页面创建 Merge Request / Pull Request。标题和描述一定要写清楚最好关联任务单号比如“订单导出功能关联需求 #123”。如果是修复 bug描述里建议写清复现步骤和修复思路这对 reviewer 和后人查历史都很有帮助。MR 创建之后会有人给你做 code review也可能有 CI 自动跑测试。评审意见出来你就在同一个本地分支继续修改、提交、推送MR 会自动更新不需要重新创建。这里有个细节push 前一定要检查这次分支和主干之间到底改了什么可以执行 git diff main...HEAD只看自己这个分支的净改动。这个命令特别好用能帮你发现“我不小心把别人的文件也改了”这种尴尬问题。另外IDEA 这类 IDE 天然集成了 Git新建项目时可以直接从版本控制拉取菜单栏 VCS - Get from Version Control粘贴仓库地址就能 clone。VS Code 也类似左下角源代码管理面板能看到所有改动。IDE 解决的是可视化问题但底层命令还是我们这套所以两边都要会一点。4. 远程仓库与免密认证SSH Key、密码缓存、多平台配置4.1 用 SSH Key 代替每次输密码实习第一天连接公司的 GitLab 仓库最烦的就是每次 push/pull 都要输账号密码。与其和 HTTPS 密码纠缠不如一次性配好 SSH Key后面就能安静地写代码。生成密钥的命令很简单ssh-keygen -t ed25519 -C 你的企业邮箱执行后连续按三次回车就会在用户目录下生成一对密钥。Windows 默认位置是 C:\Users\你的用户名.ssh\id_ed25519.pubLinux/macOS 是 ~/.ssh/id_ed25519.pub。后缀 .pub 的公钥可以公开私钥绝对不要给别人。用文本编辑器打开 .pub 文件复制里面完整的一行然后到公司 GitLab 或 Gitee/GitHub 的 SSH Keys 设置页面粘贴保存。配置完成后用命令测试连通性ssh -T gitgitee.com如果返回类似 “Hi 用户名! Youve successfully authenticated” 就说明通了。走到这一步后续 git clone 时请选择 SSH 地址形如 gitgitee.com:user/repo.git而不是 https:// 开头的地址。如果你发现明明配好了密钥还是提示要密码大概率就是 clone 地址用成了 HTTPS可以 git remote -v 检查一下。4.2 HTTPS 场景下的账号密码缓存与清除也有人图省事继续用 HTTPS 方式那么第一次 clone 时输入的账号密码会被 Git 的凭据管理器记住以后不用重复输入看起来很爽。但问题来了当你换了账号或者密码改成 Token 之后会发现明明改了配置命令还是用旧账号旧密码去请求这是很多“Git 疑难杂症”的来源。Windows 上要彻底清掉缓存凭据可以打开“控制面板 - 凭据管理器 - Windows 凭据”找到 git 开头的条目删掉。macOS 用户在“钥匙串访问”里搜 git 相关关键字删除。命令行层面可以执行 git config --global --unset credential.helper 暂时清掉凭据助手配置但这不会删掉系统里已存的凭据所以最靠谱的还是去系统凭据管理器手动删。顺带说一句现在国内外的代码托管平台大多不再推荐直接用账号密码而是用个人访问令牌Personal Access Token。push 时让你输密码你输入这个 Token 就能过。令牌本身有权限范围别把它写在配置文件里或提交到仓库否则等于裸奔。4.3 多 Git 平台、多账号怎么区分密钥实习期间你很可能同时要面对公司 GitLab、个人 Gitee、个人 GitHub 三个平台。如果一直用同一个默认密钥往往 A 平台配好了B 平台又说密钥已存在或者认证失败。解决办法是给不同平台生成不同私钥然后用 SSH config 文件做好路由。生成第二个密钥时指定文件名比如ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_gitee -C 你的Gitee邮箱 ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C 你的企业邮箱然后在 ~/.ssh/ 目录下创建 config 文件内容大概这样Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519_gitee Host gitlab.company.com HostName gitlab.company.com User git IdentityFile ~/.ssh/id_ed25519_work保存后每次 SSH 连接到对应的 Host就会自动使用指定的密钥文件互不干扰。这套配置我自己实习第二周就配好了之后再也没为输密码烦心过。要注意的是不同系统下私钥文件权限可能会被严格检查Linux/macOS 上如果报权限过宽执行 chmod 600 ~/.ssh/id_* 通常就能解决。5. 实习期高频报错与排查疑难杂症速查表5.1 fatal: not a git repository当前目录根本不是仓库刚实习的时候最常见到的一条报错就是 fatal: not a git repository (or any of the parent directories): .git。看到这个第一反应别慌先 pwd 看看自己当前在哪个目录再 ls -a 找有没有 .git 目录。绝大多数情况是你根本没进到仓库目录里比如在用户主目录、桌面或者项目外层就敲了 git statusGit 找不到 .git 当然会报错。还有一种情况是自己手贱在已有项目的子目录里 git init结果创建了嵌套仓库。Git 虽然不会阻止你在子目录重新 init但后续操作很容易混乱。我建议在克隆下来的项目目录里直接开发不要自作聪明地初始化如果本地没有仓库用 git clone 拿到远端仓库而不是先 init 再加 remote这条能帮你避开很多问题。5.2 refusing to merge unrelated histories两端历史对不上另一个高频报错是 fatal: refusing to merge unrelated histories。常见的触发姿势是你先在本地 git init然后 git add git commit 做了几条记录再添加远端仓库地址执行 git pull于是本地仓库和远端仓库的历史完全不同Git 出于安全考虑拒绝自动合并。有些教程教你在 pull 后面加 --allow-unrelated-histories 强行合并但作为实习生我建议别这么干。最稳妥的方式是先备份本地文件直接 git clone 远端仓库然后再把本地要保留的改动复制进来放到新分支上提交。历史对不上这个问题本质上是“本地初始化”这个动作造成的从源头避免比事后缝合舒服得多。5.3 SSH 认证失败Permission denied (publickey)SSH 认证失败是新人绕不开的坎。常见原因按出现概率排公钥没粘贴完整、用了 HTTPS 地址却对着 SSH 排查、ssh-agent 没加载私钥、远端地址写错。可以先执行 ssh -T gitgitee.com 看具体提示。如果返回 Permission denied (publickey)先确认你的公钥有没有复制全粘贴时不要把邮箱漏掉再确认本地私钥是否被 ssh-agent 识别手动加载一下eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519同时检查 git remote -v 里的地址是不是 SSH 格式。有一个容易被忽略的细节生成密钥后如果 Git Bash 是在生成之前打开的可能还没加载新密钥关掉重开一个终端就好了。这条排查顺序基本覆盖了实习期间遇得到的 SSH 问题。5.4 commit --amend 之后 push 被拒怎么办前面讲过 amend 会改写提交历史这里专门说已经 push 之后的情况。如果你 amend 后直接 push远端会拒绝更新因为本地分支历史跟远端不一致。这时候要是这个分支是你自己的功能分支没有任何同事基于它开发可以安全地强推git push --force-with-lease origin feature/xxx注意我用的是 --force-with-lease 而不是 -f。区别在于force-with-lease 会检查远端分支在上次 fetch 之后有没有新增提交如果有它就拒绝强推防止你覆盖别人的工作。这个参数对新人非常友好可以把它当成默认强推方式。但如果你操作的是共享分支或者公司开启了分支保护强推往往会被服务端直接拒绝。这时候就别想着绕过了老老实实基于最新代码再补一条修复提交虽然历史多了一个提交但安全得多。实习生在这个问题上最忌讳“自己偷偷强推把同事代码覆盖了”相信我这种事故一次就够影响整个团队对你的信任。5.5 git worktree一个仓库同时开多个分支的进阶操作实习第三周我遇到过一个真实场景一个功能分支写到一半还没法提交但线上 hotfix 又急得不行。之前我会 stash 然后切分支但 stash 多了容易混乱。后来师兄教我 git worktree它能把同一个仓库的分支检出一份到另一个目录两边同时操作互不干扰。git worktree add ../project-hotfix hotfix这会在 ../project-hotfix 目录下新建一个和当前仓库关联的 worktree并且直接切到 hotfix 分支。你可以在原目录继续写 feature在新目录处理 hotfix最后 push、pull 各自正常执行。用 git worktree list 可以查看有哪些 worktree用完执行 git worktree remove ../project-hotfix 就能移除。要注意的是同一个分支不能同时被两个 worktree 检出Git 会直接拒绝。这个功能对实习生来说不是必须但知道它存在紧急时刻能救你一命。5.6 关于 .git 目录泄露的一点安全提醒Git 目录泄露是真实存在的安全隐患。如果一个线上 Web 目录里被误部署了 .git 文件夹攻击者可能通过工具从 .git 里的对象数据还原出源代码甚至找回包含敏感信息的旧提交。作为实习生如果在公司项目里看到这种环境正确的做法不是自己去下载那些数据而是第一时间告知运维或安全同事让他们删除泄露目录并在构建或部署流程里把 .git 排除掉。很多部署工具的默认配置里其实已经会忽略 .git但总有一些“手动打包”的项目会翻车。你有这个意识以后写部署脚本的时候就会主动在忽略清单里加上 .git这是很值得培养的工程习惯。5.7 Git 和 SVN 的区别几句话讲明白有些公司还保留着 SVN 的老项目实习可能也要接触。Git 是分布式的每个克隆下来的仓库都包含了完整的提交历史没网也能查历史、切分支SVN 是集中式的历史都放在服务器上必须联网才能看。Git 的本地分支切换成本极低SVN 的分支操作则笨重很多。会 Git 的人转 SVN 很轻松基本命令对照一下就行svn update 对应 git pullsvn commit 对应 git commit pushsvn add 对应 git add。所以哪怕你实习的公司在用 SVN学 Git 的时间也完全不会白费。5.8 用 alias 把常用命令缩短写命令写多了自然会嫌 git status、git checkout 太长。Git 自带别名功能可以一次性配置好git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.cm commit git config --global alias.lg log --oneline --graph --all --decorate配置之后git st 就是 git statusgit lg 就是格式化历史图。我个人用下来最爽的是 git lg一眼扫清分支结构排查“这条提交在哪”特别快。如果你习惯图形界面Windows 小乌龟这类工具可以辅助使用但别把命令行彻底丢了毕竟服务器、CI 环境里可没有 GUI。6. 实习这几周我把 Git 用成了肌肉记忆如果说实习第一个月我有什么成长那一定是 Git 操作从“背命令”变成了“条件反射”。以前我要想一下 git pull 会不会有冲突、git rebase 能不能用现在基本是肌肉记忆早上到工位先 git status看看有没有人动了我的分支写代码前 git pull --rebase 同步主干提交前 git diff 自检推完代码顺手看一眼 MR 状态。我给自己定过一组日常检查清单不要在 main 上提交提交信息写清楚干了什么push 之前先检查有没有敏感信息、调试输出、本机绝对路径解决完冲突一定删干净冲突标记不清楚的命令先 git help 或者问同事绝不拿强推冒险。这几点看起来简单但每一个都是踩过坑之后才写下来的。最后再分享一个小技巧当你只想往上次提交里追加一个文件、又不想改提交信息时用 git commit --amend --no-edit 会很顺手。而如果你想看得更远习惯用 git log --all --graph 而不是只看当前分支很多“张冠李戴”的提交错位问题一眼就能看明白。Git 就是这样只要把日常那十几条命令磨顺手了它就能从绊脚石变成你最趁手的工具。