L6 Git 协作
本课目标
建立“检查状态 -> 暂存 -> 提交 -> 推送”的日常循环,能在独立分支完成修改并发起 Pull Request,同时理解同步和冲突处理的边界。
为什么我们需要 Git?
在正式敲命令之前,我想先问大家两个非常现实的问题。
痛点一:毕业论文式的文档命名 大家在写实验报告或课程设计文档的时候,是不是经常经历这样的心路历程:
设计方案_v1.docx(初稿完成)设计方案_v2_修改.docx(加了文献,改了格式)设计方案_final.docx(一定是最终版)设计方案_final_打死不改.docx(真的最终版)设计方案_final_打死不改_老师又让改.docx(导师反馈,再改一遍)
最绝望的是什么?当你改得乱七八糟,甚至删掉了某个重要章节,Ctrl+Z 的撤销历史也已经没了,你突然想找回上周五那个“文献还没加但逻辑清楚”的版本,却翻出来 5 个 final 都不知道哪个是想要的。
痛点二:U盘传代码的恐惧
打比赛是团队合作。学长在调底盘的底盘解算,你在写云台的视觉通信。你们俩要把代码合并到一辆车上测试。 “喂,学长,我把你昨天的代码用微信发给你,你把我的 main.c 复制进去,千万别覆盖了你改的第 150 行啊!” 结果一跑,车炸了。谁也不知道到底是谁改错了哪行代码。
结论:你需要 Git。 Git 提供可追溯的版本历史,也能让多人在独立分支上协作并审查合并。
终端常用命令
我们要学 Git,就不可避免地要和黑框框(终端 Terminal)打交道。忘掉鼠标双击,让我们像程序员一样和计算机对话。 大家打开电脑上的终端:

pwd(Print Working Directory):显示当前目录。ls(List):列出当前目录中的文件。cd <文件夹名>(Change Directory):切换目录,例如cd Desktop;cd ..返回上一级。mkdir <文件夹名>(Make Directory):创建目录。
互动小练习: 用终端在桌面文件夹里新建一个叫 RoboMaster_Git_Lab 的文件夹,并走进去。
前置任务:自报家门 (git config)
在第一次使用 Git 之前,你必须完成极其重要的一步:告诉 Git 你是谁。 为什么?因为以后出了 Bug,Git 的历史记录里要清清楚楚地写明这行炸车的代码是谁写的(俗称“精准追溯”)。
在终端敲入这两行(替换成你自己的英文拼音和邮箱):
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"这一步在你的电脑上只需要做一次,终身有效。
⚠️ 重要提醒 上面的两行命令千万不要直接全选粘贴! 请一行一行地来:第一步,敲写(或粘贴)第一行:注意把
你的名字拼音改成自己的英文名字拼音(比如Zhang San或zhangsan),保留引号,然后按回车。第二步,敲写(或粘贴)第二行:把你的邮箱@example.com改成自己的真实邮箱(比如zhangsan@qq.com),然后按回车。
核心循环:雷达、取景框与快门
现在,我们站在了刚才新建的 RoboMaster_Git_Lab 文件夹里。这里目前只是个普通的文件夹,还没有任何版本控制。
第一步:初始化仓库 git init
git init敲下回车,你会看到提示 Initialized empty Git repository。 此时,Git 已经在你文件夹里建了一个隐藏的 .git 文件夹。从现在起,这个文件夹里发生的任何改动,都逃不过 Git 的眼睛。
第二步:Git 界的雷达 git status (极其重要!)
只要你感到迷茫,不知道刚才敲的命令生效没,直接敲:
git status现在我们新建一个 main.c 文件随便写两行字。再敲 git status,你会看到红色的字写着 Untracked files: main.c 红字的意思是:Git 看到这里有个新文件,但还没把它纳入版本控制。
不是什么都要提交
在 .gitignore 中加入 cmake-build-debug/、构建输出和本地 IDE 配置。它们可以重新生成,提交后反而容易制造无关差异。已经被 Git 跟踪的文件仅写入 .gitignore 不会自动取消跟踪。
第三步:放入取景框 git add
准备好你要存档的文件后,我们要把它们放进“准备提交的取景框”(暂存区)。
git add main.c # 只加这一个文件
git add . # (最常用)把当前目录下所有红字文件全部加入暂存区再次敲 git status,你会发现原本的红字变成了绿字。绿字代表:这些文件已经准备好,可以提交了!
第四步:按下快门 git commit
git commit -m "完成底盘PID基础框架"-m 后面跟着的,是这次提交的“留言”。千万不要写“111”或者“改代码”这种无意义的描述! 一定要写清楚你做了什么改动。 按下回车,一个完整的版本快照就永久地保存在了本地仓库里。即使你明天把代码删得一干二净,也能瞬间找回来。
时光机:后悔药怎么吃?
刚刚我们提交了快照,那怎么看我们提交过的历史呢?
查看历史:git log
git log你会看到一串长长的、像乱码一样的黄字(比如 commit a1b2c3d4...),这就是这次提交的唯一标识符 (Commit Hash),下面还写着谁在什么时间,提交了什么留言。
时光倒流:git reset / git restore
如果你刚刚把代码写乱了,还没提交:
这会丢弃未提交修改
先运行 git status 和 git diff,确认这些改动确实不再需要。无法从 Git 恢复从未提交过的内容。
# 把工作区所有未保存的改动全部撤销,恢复到上一次提交后的状态
git restore .如果更惨,你已经连续提交了 3 次垃圾代码,想回到昨天那个 a1b2c3d4 的版本:
这会同时移动分支并覆盖工作区
先确认目标提交,必要时先创建临时分支或提交当前工作。不要在不理解影响时执行 --hard。
# 警告:这是一剂猛药,会将代码完全回退到那个时刻
git reset --hard a1b2c3d4平行宇宙:分支 (Branch) 的艺术
Git 最强大的功能,叫做分支 (Branch)。
想象一下 RoboMaster 战车代码:main(或旧仓库中的 master)分支代表随时可以集成测试的稳定版本。开发尚未验证的新功能时,应先创建独立分支,避免阻塞队友的底盘和云台测试。
怎么办?拉出一个平行分支!
# 创建并切换到一个叫 "feature/aim-bot" 的新分支
git checkout -b feature/aim-bot分支上的提交不会直接改变主分支。功能经过构建、测试和审查后,再通过合并(Merge)进入 main。
尽早开分支,主干保平安。哪怕只是改一个按键映射,也请养成开新分支的习惯!
图形界面集成:CLion 中的 Git 操作
好,听完上面那些命令行的介绍,现在告诉大家一个好消息: 在实际开发中,你几乎不需要在终端里敲这些命令!
现代 IDE 早已把 Git 深度集成到了图形界面中。刚才我们学的底层逻辑,在 CLion 里都变成了直观的按钮:
git add+git commit:打开 CLion 的 Commit 窗口,勾选本次相关文件、检查差异、填写提交信息并提交。
git log:在 CLion 的 Git 工具窗口查看提交时间线、分支和文件差异。
git switch -c(分支管理):点击当前分支名并选择New Branch,或在终端执行git switch -c feature/name。

为什么有了图形界面还要教命令? 因为只有理解了工作区、暂存区、本地仓库这些概念,你在使用图形界面时遇到问题才不会手足无措。图形界面是命令的快捷方式,而原理才是内功。
远程仓库:为什么需要云端?
上半场我们学会了在自己的电脑上保存版本和创建分支。但问题来了:如果你的电脑突然坏了怎么办?如果你要和另外三个队友一起写同一辆车的代码怎么办?
我们需要一个 “云端的中央仓库”。常见代码托管平台包括 GitHub 和 Gitee(码云);它们负责保存 Git 仓库,并提供代码审查、议题和自动化工作流等协作功能。
配置身份验证:告别重复输入密码
在我们把代码推送到云端之前,需要先解决身份验证的问题。 为了防止别人篡改你的代码,代码托管平台在你每次上传时都会要求验证身份。如果每次都要输入账号密码,会非常麻烦。
为了让 Git 记住我们的凭证,请执行以下命令:
# Windows 版 Git 通常已安装并启用 Git Credential Manager
git config --global credential.helper manager不要把账号密码或访问令牌直接写进仓库、脚本或 credential.helper store 的明文文件中。首次推送时按系统提示登录即可。
注册并登录Gitee账号
访问gitee官网:https://gitee.com/,点击右上角注册,填写相关信息

酌情进行初始化配置,可以全部点击右下角按钮跳过

进入工作台,点击右上角的绑定邮箱(“添加绑定”这四个字)

点击新增,输入密码验证,输入邮箱


在邮箱中查询已经收到的验证邮件,点击确认绑定


创建一个云端仓库
点击右上角的加号->新建仓库

输入仓库相关信息,点击创建

创建完成,进入空仓库页面

将本地仓库推送到云端 (git push)
在本地新建一个叫 hello-world 的 C++ 项目。这个项目会检测项目文件夹下的“greetings”文件夹里的txt文件,并将其内容输出出来。
现在我们完成了第一次提交。我们把它推送到我在 Gitee 上刚刚建好的空仓库里。
仓库链接:https://gitee.com/dlmu-cone/hello-world
按照gitee的指示,在命令行里执行了下面的操作:
git remote add origin https://gitee.com/dlmu-cone/hello-world.git
git push -u origin "master"现在,大家刷新一下上面的 Gitee 仓库链接,是不是看到我刚才写的 main.c 已经出现在网页上了? 这就是 Push 的作用:把本地的提交历史,完整地复制到云端。
互动挑战:在开源世界留下你的名字
现在,我要邀请在座的所有人,参与到这个 HelloWorld 项目的开发中来。你们的任务是:在greetings文件夹里加入一个自己的txt文件,并把它合并到我的主分支里。
但这引出了一个权限问题:你们不是这个仓库的拥有者,Gitee 不会允许你们直接把代码 Push 到我的仓库。那开源社区成千上万的程序员是怎么给 Linux 这样的项目贡献代码的?
答案就是:Fork + PR 工作流。
Step 1: Fork (复刻)
请大家打开我的 Gitee 仓库页面,点击右上角的 “Fork” 按钮。

出现下面的窗口,选中个人,然后点击确认

Fork 的意思是“复刻”。点击之后,Gitee 会在服务器上把我的整个仓库复制一份,放到你自己的账号下。 现在,你拥有了一个完全属于你的云端仓库,你可以对它进行任意修改!
Step 2: Clone (克隆到本地)
现在,打开你自己的 Gitee 页面,找到你刚刚 Fork 下来的 HelloWorld 仓库。点击“克隆/下载”按钮,复制 HTTPS 链接。


回到 CLion,点击顶部的 Git -> 克隆(或者在欢迎界面点击 克隆项目),粘贴这个链接。



注意,这里的链接一定是Fork的,你自己用户下的仓库链接!
克隆完成后,会提示打开新克隆好的工程。

或者,你也可以直接在命令行里输入:
# 对应的底层命令:把云端仓库下载到本地
git clone https://gitee.com/你的账号/hello-world.git(如果提示输入账号密码,先输入你在 Gitee 的手机号并回车,然后输入密码并回车即可,Git 会帮你记住!)
Step 3: 创建自己的开发分支 (Branch)
好习惯从现在养成:不要在 master 上直接修改。 在 CLion 左上角点击 master,选择 新建分支,起名叫 feature/你的拼音(比如 feature/zhangsan)。


点击创建,即可在Git选项卡里看到你创建的分支

Step 4: 提交修改 (Commit)
右键greetings目录,点击新建文件;

写入自己想要的名称,按下回车

在文件里输入你的问候或者任意一句话!

点击 CLion 左侧的蓝色勾 (Commit),填写提交信息:“Add Zhang San greeting”,点击 提交!

Step 5: 推送到自己的云端仓库 (git push)
点击 CLion 左上角的分支,选中当前我们所在的feature/zhangsan分支,点击推送:


第一次推送的时候,CLion会提示我们输入用户名和密码。我们点击选中下面的使用凭证帮助程序,点击登录,然后在接下来出现的窗口中输入Gitee手机号和密码,点击Continue

你会发现,代码被推到了你自己的 Gitee 仓库的 feature/zhangsan 分支上。


Step 6: 发起 Pull Request (PR)
怎么把你的代码提交给我?这就是开源界著名的 PR (拉取请求)。 回到你自己的 Gitee 仓库网页,点击上方的Pull Request。原分支选择我们创建的新分支,目标分支选择原仓库的master分支。我们可以填写PR描述,然后点击左下角的创建 Pull Request

:“你好,我在我的分支上完成了一个修改,请你审核一下,并把它拉取 (Pull) 合并到你的主分支中吧!”
仓库负责人在收到这个PR之后,就可以开始决定是否要通过并合并这个PR。

同步更新:拉取队友的最新代码 (git pull)
大家刚才提交的代码已经被我合并到了主仓库中。 但是大家看看自己电脑上的 CLion 代码,是不是还只有你自己的名字?因为你的本地仓库还没有更新。
首先我们要更新一下云端的Fork仓库。在你自己的Fork仓库中点击拉取:

接下来,我们需要把云端最新的 master 分支拉取下来。 在 CLion 里,点击分支中的master,点击更新:

更新完成后再点击签出:

或者使用命令:
git pull origin master瞬间,所有队友刚才写的 printf 就出现在了你的电脑上!这就是团队协作的体验。
解决冲突:当两个人改了同一行代码
但是,实际协作中难免会遇到一种情况:代码冲突 (Conflict)。
假设,学长在 main.c 的第 20 行写了 speed = 100; 并推送到了云端。 而你,在自己电脑的 main.c 第 20 行写了 speed = 200;。 当你执行 git pull 准备合并学长的代码时,Git 会提示冲突: CONFLICT (content): Merge conflict in main.c
Git 说:“同一行代码有两个不同的修改,我不知道该保留哪个,需要你来决定。”
如果是在命令行里解决冲突,你可能会看到满屏的 <<<<<<< HEAD 和 ======= 标记。 但是,CLion 提供了可视化的冲突解决工具!
当冲突发生时,CLion 会弹出 Conflicts 窗口。点击 Merge (合并): 你会看到屏幕分成三块:
左边 (Your version): 你自己写的
speed = 200;右边 (Server version): 学长写的
speed = 100;中间 (Result): 最终合成的代码(冲突行目前是空的)
怎么解决? 点击中间面板两侧的箭头:点左边的 >> 接受你的修改,点右边的 << 接受学长的修改。如果你想同时保留两行,可以手动编辑中间框。 当中间框里没有红色冲突标记时,点击右下角的 Apply (应用)。 冲突就解决了!Git 会自动生成一个合并提交。