多人协同git提交工程化思路
Git 多人协同分支开发教学(mes_dev 协作版)
场景设定:团队共享的远程开发分支是
mes_dev,每个人的本地开发分支是mes_dev_自己名字(下文以mes_dev_zhangsan为例)。本文覆盖:推送自己的代码、拉取远程代码、解决冲突、避免冲突,以及每一步在 IDEA 中对应的操作和所有常见场景的处理方案。
目录
一、分支模型总览

关键认知:
| 分支 | 位置 | 谁在动 | 用途 |
|---|---|---|---|
origin/mes_dev |
远程仓库 | 全组人 | 团队共享的开发主线,所有人的代码最终汇合到这里 |
mes_dev(本地) |
你的电脑 | 只有 git pull 会动它 |
只是 origin/mes_dev 的本地缓存副本,不要在上面开发 |
mes_dev_zhangsan |
你的电脑 | 只有你 | 你的专属开发分支,日常写代码都在这里 |
口诀:在
mes_dev_name上开发;push 前先把origin/mes_dev的新代码合并进来,再推上去。
创建你自己的开发分支(首次入职做一次)
# 基于远程最新开发分支创建自己的分支
git fetch origin
git checkout -b mes_dev_zhangsan origin/mes_dev
git push -u origin mes_dev_zhangsan # -u 建立跟踪关系,以后 push/pull 不用再写参数
IDEA 操作:右下角分支图标 → New Branch 输入 mes_dev_zhangsan(基于 origin/mes_dev 创建)→ 勾选 Check out branch。
二、日常开发标准循环

每天重复这套动作:拉新代码 → 开发 → 提交 → 推送前再拉一次 → 解决冲突(如有)→ 推送 → 发 Merge Request。
三、如何把自己的代码推送到远程
命令行标准三步
# 1. 提交你的改动(在 mes_dev_zhangsan 上)
git add .
git commit -m "feat: 完成排程校验逻辑"
# 2. 推送前先同步远程(防止 push 被拒,见第四节)
git pull --rebase origin mes_dev
# 3. 推送
git push origin mes_dev_zhangsan
IDEA 操作
- 提交:
Ctrl+K(Git → Commit),勾选要提交的文件,写 commit message,点 Commit。- 勾选
--amend可以把改动并进上一次提交(还没 push 时用)。
- 勾选
- 推送:
Ctrl+Shift+K(Git → Push),确认无误后点 Push。- 推荐做法:在 Commit 窗口直接勾选 "Commit and Push...",一步完成。
- IDEA 右上角有黄色横幅提示 "The branch has new remote changes" 时,点
Rebase(推荐)或Merge。
场景 1:本地有提交,远程没有新提交
git push origin mes_dev_zhangsan # 直接成功,fast-forward
场景 2:本地有提交,远程也有新提交(最常见!)
先看第四节"把远程合并到本地"里的 rebase 方案,合并完再 push。
强行推送的报错长这样:
! [rejected] ... (fetch first)或(non-fast-forward)。看到报错不要 force push! 按第四节处理。
场景 3:本地改了一半还没 commit,想推送
两个选择:
# 选择 A:先提交再走标准流程(推荐)
git add . && git commit -m "wip: xxx"
# 选择 B:暂存起来
git stash push -m "改到一半的排程页面"
git pull --rebase origin mes_dev
git stash pop
IDEA:右键项目 → Git → Uncommitted Changes → Stash Changes / Unstash Changes。
场景 4:误把代码提交到了本地 mes_dev
# 还没 push:把提交"搬家"到自己的分支
git checkout mes_dev_zhangsan
git cherry-pick mes_dev # 把 mes_dev 上最新的提交摘过来(可多次或用区间)
git checkout mes_dev
git reset --hard origin/mes_dev # 把本地 mes_dev 恢复成远程的样子
# 已经 push 且被 MR 合入了:不要再动历史,revert(见第九节)
四、如何把远程代码合并到本地
远程 mes_dev 不断有同事的提交汇入,你必须定期同步,拖得越久冲突越多。
命令行:拉取 + 合并的完整方案
# 第一步:只下载,不动工作区(安全,随时可执行)
git fetch origin
# 第二步:合并远程代码,二选一 ——
| 方案 | 命令 | 历史形态 | 适合 |
|---|---|---|---|
| Rebase(推荐) | git rebase origin/mes_dev |
一条直线,干净 | 你自己的开发分支没推送过 / 推送过但只有你一个人用 |
| Merge(保守) | git merge origin/mes_dev |
有分叉合并节点 | 团队习惯如此 / 分支已共享多人使用 |
为什么推荐 rebase:rebase 把你的提交"搬"到远程最新提交后面,历史是一条直线(见下图);merge 会产生一堆"Merge branch 'mes_dev'..."的合并节点,日志很难看。

rebase 黄金法则:只 rebase 自己的、未与他人共享的提交。绝不对已经合入 mes_dev 的公共提交做 rebase。 如果你们组习惯全员直接往共享分支 push,那就统一用 merge。
IDEA 操作
- 菜单:Git → Update Project(或状态栏右下角分支图标 → Update),快捷键
Ctrl+T。 - 弹出选择框时选 Rebase(推荐)或 Merge —— 这个选择对应 IDE 设置
Settings → Version Control → Git → Update method,可以设成默认 Rebase。 - 只 fetch 不合并:Git → Fetch(相当于
git fetch),然后右下角分支面板里可以看到origin/mes_dev领先了几个提交。
场景 5:本地没有未提交改动,直接同步
git pull --rebase origin mes_dev
场景 6:本地有未提交的改动,又要同步
git stash push -m "同步前的临时保存"
git pull --rebase origin mes_dev
git stash pop # 恢复改动;若 pop 时报冲突,按第五节解决
IDEA 会自动帮你处理:Update Project 时若检测到未提交改动,会提示你 Stash → Update → Unstash,直接按它的引导走即可。
场景 7:pull 时自动合并成功(无冲突)
Git 会直接把远程改动合进来,你什么都不用做,直接继续开发或 push。
场景 8:pull 时提示冲突
进入第五节,按冲突流程解决。
场景 9:想看看远程到底更新了什么(不合并)
git fetch origin
git log mes_dev_zhangsan..origin/mes_dev --oneline # 远程比本地多的提交
git diff mes_dev_zhangsan...origin/mes_dev # 具体差异
IDEA:右下角分支面板 → 展开 origin/mes_dev → 选中某个提交右键 → Show Diff with Working Tree。
五、冲突:原理、解决与所有场景
5.1 冲突是怎么产生的

- 只有一方改了某行 → Git 自动合并,不会冲突
- 两方改了同一文件的不同区域 → 自动合并,不会冲突
- 两方改了同一区域的同一处且改得不一样 → Git 不知道该听谁的 → 冲突
5.2 解决冲突标准流程
第一步:找到冲突文件
git pull --rebase origin mes_dev
# 输出出现 CONFLICT (content): Merge conflict in xxx.java
git status # both modified: 的文件就是冲突文件
第二步:打开冲突文件,看懂冲突标记
<<<<<<< HEAD ← 当前分支这边(rebase 时=远程,merge 时=你自己)
orderService.checkStockV2(order);
======= ← 分隔线
orderService.checkStockAndLock(order);
>>>>>>> origin/mes_dev ← 另一边
易混警告:rebase 和 merge 时 HEAD 的含义相反!
git merge:HEAD = 你自己,origin/mes_dev= 远程git rebase:HEAD = 远程,origin/mes_dev(或 theirs)= 你自己的提交所以解决冲突不要背口诀,要看代码内容判断哪边是什么。
第三步:手动编辑融合两边逻辑(不是简单二选一!),删掉 <<<<<<<、=======、>>>>>>> 标记。
第四步:标记已解决并继续
git add 冲突文件名 # 或 git add .
git rebase --continue # rebase 流程用这个;会跳到下一个待重放的提交
# 如果想放弃整个 rebase:git rebase --abort(回到 rebase 前的状态,安全)
# merge 流程对应:git commit(Git 会生成合并提交)
# 如果想放弃 merge:git merge --abort
5.3 IDEA 冲突解决(强烈推荐,比命令行舒服太多)

pull/rebase/merge 触发冲突时 IDEA 会自动弹出 Merge Conflicts 对话框,每个文件三个选择:
| 按钮 | 效果 | 什么时候用 |
|---|---|---|
| Accept Yours | 整个文件采用"我的" | 确认对方的改动不该要(谨慎) |
| Accept Theirs | 整个文件采用"对方的" | 确认自己的改动不要了(谨慎) |
| Merge(推荐) | 打开三栏对比窗口,逐行决定 | 99% 的情况用这个 |
三栏窗口用法:
- 左栏(Local)/ 右栏(Remote):点击代码块旁边的
»/«箭头把一侧代码采纳进中间。 - 中栏(Result):合并结果,可以直接编辑——把两边逻辑融合后手写进去。
- 窗口顶部的冲突计数器会自动跳到下一个冲突点,全部解决后点 Apply。
- 底部预览区可以看最终效果;解决完 IDEA 自动
git add,rebase 的话再执行git rebase --continue(IDEA 有时会自动继续重放,注意看 Git 输出面板)。
重要提示:IDEA 在 rebase 时把"你的提交"显示为 Remote/Incoming、把"远程分支"显示为 Local——和直觉相反。不确定时看代码内容,别按位置猜。
5.4 所有冲突场景与合并方案
场景 10:两人改了同一个文件的不同方法/区域
Git 自动合并,无需干预。推送即可。
场景 11:两人改了同一行代码(经典冲突)
先问自己:这两处改动是不是要同时保留?
- 都要 → 在 IDEA 中栏手工融合,如"同事改了方法名 + 你加了参数"→ 写成融合后的最终形态;
- 只要一边 → 点对应箭头采纳。
- 拿不准就找同事对一下(微信/口头确认谁的业务逻辑是最新的),30 秒的事,比合错代码返工便宜得多。
场景 12:一人改代码,另一人删了整个文件(modify/delete 冲突)
命令行会提示 CONFLICT (modify/delete)。决策:文件该不该删?
- 该删 →
git rm 文件名 && git rebase --continue; - 不该删 →
git add 文件名 && git rebase --continue(保留你的修改版)。
IDEA 中在冲突列表选 Accept Yours(保留文件)或 Accept Theirs(删除文件),看清哪边是删除侧再点。
场景 13:两人都新增了同名文件 / 同名方法
- 同名文件:内容不同则手动融合成一个,删掉多余的那个;
git add保留的那个。 - 同名方法:编译期不会报错但逻辑可能冲突——融合后跑一遍编译和单测再继续。
场景 14:改动被包含在多个连续提交里,rebase 时同一个冲突反复弹
这是因为你的多个提交都碰了同一块代码。逐个 git rebase --continue 处理即可;也可以改用 git merge(冲突只弹一次)。长期方案见第六节"小步提交"。
场景 15:解决冲突解决到一半,想放弃重来
git rebase --abort # rebase 流程:完全回到 rebase 之前
git merge --abort # merge 流程:同上
IDEA:Git 面板中的通知栏有 Abort 按钮。
场景 16:stash pop 时冲突
同普通冲突流程解决,解决后 stash 记录要手动删:git stash drop。
场景 17:合并后代码丢了 / 合错了,想恢复
- 还没 push:
git reflog找到合并前的 HEAD 记录 →git reset --hard <id>; - 已 push:
git revert(见第九节)。
六、如何避免冲突
冲突的根源是 两个人改同一处代码 + 同步间隔太长。对策按有效性排序:
- 小步高频同步:每天上班第一件事
git pull --rebase origin mes_dev,下班前 push。拖一周再同步,冲突会滚雪球。 - 任务分工错开:领任务时和组长/同事确认"我改排程模块,你别动 SchedulingController"——改不同文件是根治手段。
- 拉自己的分支开发:
mes_dev_zhangsan只你一人提交,主分支永远干净;通过 MR 合入,冲突在 MR 阶段暴露而非污染主线。 - 大改动前先沟通:要改公共类(如
Result、BaseController)时,先在群里说一声,避免和别人撞车。 - 拆小提交、拆小 MR:一次提交几百行 vs 一天多个小提交——后者冲突概率和解决难度都低得多。
- 文件内部善用拆分:3000 行的巨型类是冲突温床;代码层面拆分方法/类,等于物理隔离了改动区域。
- 配置好
.gitignore:target/、*.iml、.idea/、本地配置文件(application-local.yml)不进版本库,消除一类无意义冲突。 - 统一格式化配置:全组用同一套 IDEA 代码格式化配置(Editor → Code Style → 导出/导入 scheme),否则"你自动格式化了他没格式化"就是隐形冲突制造机。
七、全场景速查表
| # | 场景 | 命令 | IDEA 操作 |
|---|---|---|---|
| 1 | 首次创建个人分支 | git checkout -b mes_dev_zhangsan origin/mes_dev |
分支面板 → New Branch |
| 2 | 同步远程(无本地改动) | git pull --rebase origin mes_dev |
Ctrl+T / Update Project → Rebase |
| 3 | 同步远程(有未提交改动) | git stash → pull → stash pop |
按弹窗引导 Stash→Update→Unstash |
| 4 | 提交代码 | git add . && git commit -m "..." |
Ctrl+K |
| 5 | 推送自己的分支 | git push origin mes_dev_zhangsan |
Ctrl+Shift+K |
| 6 | push 被拒(non-fast-forward) | git pull --rebase origin mes_dev → 再 push |
点黄色横幅的 Rebase |
| 7 | 拉取时冲突 | 解决 → git add . → git rebase --continue |
Merge Conflicts 弹窗 → Merge |
| 8 | 想放弃冲突处理 | git rebase --abort / git merge --abort |
弹窗 Abort 按钮 |
| 9 | 改了一半想临时切换分支 | git stash push -m "..." → git checkout ... |
Git → Stash Changes |
| 10 | 误提交到 mes_dev | cherry-pick 到自己分支 → reset | 分支面板右键提交 → Cherry-Pick |
| 11 | 撤销未 push 的提交 | git reset --soft HEAD~1(保留改动) |
Git Log 右键 → Undo Commit |
| 12 | 撤销已 push 的提交 | git revert <commit> |
Git Log 右键 → Revert Commit |
| 13 | 修改最后一次提交信息 | git commit --amend |
Commit 窗勾选 Amend |
| 14 | 查看远程更新了什么 | git fetch + git log ..origin/mes_dev |
分支面板看 origin/mes_dev |
| 15 | 查看某次改动谁写的 | git blame 文件名 / git log -p |
右键行号 → Annotate with Git Blame |
八、IDEA 操作与快捷键对照
| 操作 | 快捷键 / 入口 | 说明 |
|---|---|---|
| Update Project(拉取+合并) | Ctrl+T 或 Git 菜单 |
弹窗选 Rebase |
| Commit | Ctrl+K |
可勾选 Commit and Push 一步到位 |
| Push | Ctrl+Shift+K |
推送前看一眼 Diff |
| VCS 操作弹窗 | `Alt+`` (反引号) | 万能入口:commit/push/pull/stash 全在这 |
| 分支面板 | IDEA 窗口右下角 | 切换/新建/删除分支、看远程分支 |
| Stash Changes | Git 菜单 → Uncommitted Changes | 存放当前未提交改动 |
| 查看历史 | Alt+9(Git 工具窗口) |
Log 分支图、右键各种操作 |
| 冲突解决 | 自动弹窗;或 Git 菜单 → Resolve Conflicts | 三栏对比窗口 |
| Annotate(看谁写的) | 右键行号 → Annotate with Git Blame | 排查某行改动的责任人 |
| Undo Commit | Git Log 右键提交 | 仅限未 push 的本地提交 |
| Revert Commit | Git Log 右键提交 | 已 push 的安全撤销 |
建议的 IDEA 设置:Settings → Version Control → Git → Update method 设为 Rebase;Commit tool window 勾选常用检查项;开启 Before Commit → Reformat code 前先确认(若全组格式不统一则关闭 Reformat,避免无谓 diff)。
九、急救手册:出事了怎么办
原则:先停下来看
git status,再动手。别慌着删分支、别 force push。
| 事故 | 解法 |
|---|---|
| rebase / merge 到一半搞砸了 | git rebase --abort / git merge --abort,一切回到操作前 |
| commit 了不想要的文件(未 push) | git reset --soft HEAD~1 → 重新挑选文件提交 |
| reset --hard 把改动弄没了 | git reflog 找到之前的 HEAD id → git reset --hard <id> 找回 |
| push 错了分支 / push 错了内容 | git revert 生成反向提交再 push(已 push 的公共提交永远不要 reset/force push) |
| 提交信息写错了(未 push) | git commit --amend -m "新信息" |
| 把别人的提交 rebase 丢了 | git reflog 里 rebase 前的记录还在,git reset --hard <旧id> 恢复 |
| 完全乱了想要干净重来 | git fetch origin && git reset --hard origin/mes_dev(会丢弃本分支所有未推送内容,确认后再用) |
| 什么操作都不敢做了 | 停手,找组长。Git 几乎不会真正丢数据(reflog 在),慌乱操作才会 |
一图记住全部流程
上班: git checkout mes_dev_zhangsan
git pull --rebase origin mes_dev ← 拿最新代码
开发: 写代码 → git add . → git commit ← 小步提交
推送: git pull --rebase origin mes_dev ← 推之前再拉一次(关键!)
有冲突?→ IDEA 三栏窗口解决 → git add . → git rebase --continue
git push origin mes_dev_zhangsan
收尾: 发起 Merge Request:mes_dev_zhangsan → mes_dev,等 Review 合入
记住一句话:你的分支随便造,主线靠 MR 进;push 前先 rebase,冲突当天清。

浙公网安备 33010602011771号