6.4:git

本地

bash 复制代码
11400@▒▒ MINGW64 ~
$ git config --global user.name "xiaocao"

11400@ MINGW64 ~
$ git config --global user.email 1140075663@qq.com

11400@ MINGW64 ~
$ cd /D/vsprogram/WpfApp6

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git init
Reinitialized existing Git repository in D:/vsprogram/WpfApp6/.git/

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git add .

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git commit -m "feat:X光检测上位机-完整"
[remove-legacy-mainvm 16e9f15] feat:X光检测上位机-完整
 2 files changed, 599 deletions(-)
 delete mode 100644 WpfApp6/MainViewModel.cs

11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git branch
  master
* remove-legacy-mainvm

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git branch -r

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git branch -a
  master
* remove-legacy-mainvm

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git branch
  master
* remove-legacy-mainvm

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git status
On branch remove-legacy-mainvm
nothing to commit, working tree clean

11400@ MINGW64 /D/vsprogram/WpfApp6 (remove-legacy-mainvm)
$ git checkout -b archive-axiscontrolviewmodel
Switched to a new branch 'archive-axiscontrolviewmodel'

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ mkdir -p Archive/Legecy

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git mv ViewModel/AxisControlViewModel.cs Archove/Legacy/
fatal: bad source, source=ViewModel/AxisControlViewModel.cs, destination=Archove/Legacy/

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git mv ViewModel/AxisControlViewModel.cs Archive/Legacy/
fatal: bad source, source=ViewModel/AxisControlViewModel.cs, destination=Archive/Legacy/

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git mv ViewModel/AxisControlViewModel.cs Archive/Legecy/
fatal: bad source, source=ViewModel/AxisControlViewModel.cs, destination=Archive/Legecy/AxisControlViewModel.cs

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git mv /ViewModel/AxisControlViewModel.cs  Archive/Legec
y
fatal: Invalid path 'C:/Program Files/Git/ViewModel': No such file or directory

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git mv ViewModel/AxisControlViewModel.cs  Archive/Legecy
fatal: bad source, source=ViewModel/AxisControlViewModel.cs, destination=Archive/Legecy/AxisControlViewModel.cs

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ mv Archive/Legecy Archive/Legacy

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ mv ViewModel/AxisControlViewModel.cs Archive/Legacy/
mv: cannot stat 'ViewModel/AxisControlViewModel.cs': No such file or directory

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ ls ViewModel/
ls: cannot access 'ViewModel/': No such file or directory

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ ls ./ViewModel
ls: cannot access './ViewModel': No such file or directory

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git ls-files
.gitattributes
.gitignore
WpfApp6.sln
WpfApp6/AXISafeIO.cs
WpfApp6/App.config
WpfApp6/App.xaml
WpfApp6/App.xaml.cs
WpfApp6/Base/ViewModelBase.cs
WpfApp6/Converters/EnumDescriptionConverter.cs
WpfApp6/Enums/DeviceStatus.cs
WpfApp6/EtherCATConfig.cs
WpfApp6/EtherCATMaster.cs
WpfApp6/Interfaces/IEtherCATMaster.cs
WpfApp6/Interfaces/ILogService.cs
WpfApp6/Interfaces/IXYScanAxis.cs
WpfApp6/MainWindow.xaml
WpfApp6/MainWindow.xaml.cs
WpfApp6/Messages/AppMessages.cs
WpfApp6/Properties/AssemblyInfo.cs
WpfApp6/Properties/Resources.Designer.cs
WpfApp6/Properties/Resources.resx
WpfApp6/Properties/Settings.Designer.cs
WpfApp6/Properties/Settings.settings
WpfApp6/Services/LogService.cs
WpfApp6/ViewModel/AxisControlViewModel.cs
WpfApp6/ViewModel/AxisEcatVM.cs
WpfApp6/ViewModel/MainShellVM.cs
WpfApp6/ViewModel/MainViewModel.cs
WpfApp6/ViewModel/XrayImageVM.cs
WpfApp6/WpfApp6.csproj
WpfApp6/XYScanAxis.cs
WpfApp6/packages.config

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git mv WpfApp6/ViewModel/AxisControlViewModel.cs Archive
/Legacy/

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git commit -m "Archive:移动AxisControlViewModel至Legacy 目录,消除冲突"
[archive-axiscontrolviewmodel f89f4aa] Archive:移动AxisControlViewModel至Legacy目录,消除冲突
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename {WpfApp6/ViewModel => Archive/Legacy}/AxisControlViewModel.cs (100%)

11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git log
commit f89f4aa25d8b2ac32a3487383c47039290c755e0 (HEAD -> acommit f89f4aa25d8b2ac32a3487383c47039290c755e0 (HEAD -> archive-axiscontrolviewmodel)
Author: 
Date:   Thu Jun 4 20:49:33 2026 +0800

    Archive:移动AxisControlViewModel至Legacy目录,消除冲突

commit 16e9f15fe276ee49d3e6afdfa4d62b6379f72b43 (remove-legacy-mainvm)
Author: 
Date:   Thu Jun 4 19:07:31 2026 +0800

    feat:X光检测上位机-完整

commit 5ef4fe5d50ed9b883330864c3df7de772e9ecc2c (master)
Author: 
Date:   Wed Jun 3 23:01:14 2026 +0800

    改

commit 31f222391ee405e5efa18d28410766d76c438e09
Author: 11400 <11400@常念>


11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrol
viewmodel)
$

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git push origin archive-archive-axiscontrolviewmodel
error: src refspec archive-archive-axiscontrolviewmodel do
es not match any
error: failed to push some refs to 'https://github.com/zhixincao1123/WpfApp6.git'

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git push origin archive-axiscontrolviewmodel
fatal: unable to access 'https://github.com/zhixincao1123/WpfApp6.git/': Recv failure: Connection was reset

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolvi
ewmodel)
$ git push origin archive-axiscontrolviewmodel
fatal: unable to access 'https://github.com/zhixincao1123/
WpfApp6.git/': Failed to connect to github.com port 443 after 21066 ms: Could not connect to server

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolvi
ewmodel)
$ git push origin archive-axiscontrolviewmodel
fatal: unable to access 'https://github.com/zhixincao1123/WpfApp6.git/': Failed to connect to github.com port 443 after 21065 ms: Could not connect to server

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git reflog
f89f4aa (HEAD -> archive-axiscontrolviewmodel) HEAD@{0}: commit: Archive:移动AxisControlViewModel至Legacy目录,消除
冲突
16e9f15 (remove-legacy-mainvm) HEAD@{1}: checkout: moving from remove-legacy-mainvm to archive-axiscontrolviewmodel
16e9f15 (remove-legacy-mainvm) HEAD@{2}: commit: feat:X光
检测上位机-完整
5ef4fe5 (master) HEAD@{3}: checkout: moving from master to remove-legacy-mainvm
5ef4fe5 (master) HEAD@{4}: commit: 改
31f2223 HEAD@{5}: commit: 添加项目文件。
2ae7d24 HEAD@{6}: commit (initial): 添加 .gitattributes 和 .gitignore。

11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git branch
* archive-axiscontrolviewmodel
  master
  remove-legacy-mainvm

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolvi
ewmodel)
$ git add .

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git commit -m "修改内容:AppMessage AxisEcatVM 增加消息
内容 不可变Dto 改"
[archive-axiscontrolviewmodel cfa853a] 修改内容:AppMessag
e AxisEcatVM 增加消息内容 不可变Dto 改
 3 files changed, 60 insertions(+), 33 deletions(-)

11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git status
On branch archive-axiscontrolviewmodel
nothing to commit, working tree clean

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git push
fatal: The current branch archive-axiscontrolviewmodel has
 no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin archive-axiscontrolviewmodel

To have this happen automatically for branches without a t
racking
upstream, see 'push.autoSetupRemote' in 'git help config'.


11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git reflog
cfa853a (HEAD -> archive-axiscontrolviewmodel) HEAD@{0}: commit: 修改内容:AppMessage AxisEcatVM 增加消息内容 不可变Dto 改
f89f4aa HEAD@{1}: commit: Archive:移动AxisControlViewModel
至Legacy目录,消除冲突
16e9f15 (remove-legacy-mainvm) HEAD@{2}: checkout: moving from remove-legacy-mainvm to archive-axiscontrolviewmodel
16e9f15 (remove-legacy-mainvm) HEAD@{3}: commit: feat:X光
检测上位机-完整
5ef4fe5 (master) HEAD@{4}: checkout: moving from master to remove-legacy-mainvm
5ef4fe5 (master) HEAD@{5}: commit: 改
31f2223 HEAD@{6}: commit: 添加项目文件。
2ae7d24 HEAD@{7}: commit (initial): 添加 .gitattributes 和 .gitignore。

11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git add .

11400@ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git commit -m "修改MainShellVm.StartScan方法 本质继续增 加消息内容 不可变DTO"
[archive-axiscontrolviewmodel 6b4dfcc] 修改MainShellVm.StartScan方法 本质继续增加消息内容 不可变DTO
 2 files changed, 35 insertions(+), 21 deletions(-)

11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (archive-axiscontrolviewmodel)
$ git checkout -b xaml
Switched to a new branch 'xaml'

11400@ MINGW64 /D/vsprogram/WpfApp6 (xaml)
$ git add .

11400@ MINGW64 /D/vsprogram/WpfApp6 (xaml)
$ git commit -m "XAML绑定改变 .cs改变"
[xaml 02c1689] XAML绑定改变 .cs改变
 3 files changed, 59 insertions(+), 56 deletions(-)

11400@▒▒ MINGW64 /D/vsprogram/WpfApp6 (xaml)
$

Git分支的核心作用

Git分支是隔离开发任务、并行推进工作、保护主代码稳定的核心工具,


一、核心作用总览

作用 通俗解释 上位机开发场景价值
隔离开发 一个任务一个分支,互不干扰 双扫描模式开发不影响主分支稳定,急停功能调试不打断点位扫描代码
并行工作 多人/多任务同时推进 你做运控逻辑,同事做Halcon视觉算法,各自分支独立开发
风险控制 不稳定代码不进主分支 限位报警逻辑测试失败时,直接放弃分支即可,不影响已发布版本
版本管理 清晰记录功能迭代历史 remove-legacy-mainvm分支可追溯X光检测系统的演进轨迹
协作规范 强制代码评审与合并流程 新功能必须通过PR合并,避免个人错误代码污染生产环境

二、详细作用拆解

1. 隔离开发:保护主分支"永远可运行"
  • 核心价值 :开发中的半成品代码不会污染稳定的主分支(main/master),确保随时可发布、可回滚
  • 项目实例
    • feature/double-scan-mode分支开发双扫描模式(点位+连续),即使代码没写完、有bug,也不会影响主分支的基础功能
    • 主分支始终保持"初始化→就绪→运行→停止"的完整可用流程,随时可用于演示或测试
2. 并行开发:多人协作不"打架"
  • 核心价值:不同开发者/不同任务可同时推进,无需等待他人完成
  • 项目实例
    • 自己开发运控逻辑(轴移动、限位报警)
    • 同事A开发Halcon缺陷检测算法
    • 同事B优化UI显示(AxisStatusText、进度条)
    • 三个分支并行开发,最后通过合并集成,效率提升3倍
3. 风险控制:安全试错与快速回滚
  • 核心价值
    • 实验性功能(如连续扫描新算法)可在独立分支测试,失败直接删除分支,零成本试错
    • 紧急问题(如客户现场发现的轴定位偏差)可在hotfix/axis-position-error分支修复,不影响正常开发
  • 项目实例
    若连续扫描模式开发中出现轴失控风险,可直接放弃该分支,回退到稳定版本,避免整机故障
4. 功能管理:清晰的迭代轨迹
  • 核心价值:每个分支对应明确任务,提交历史清晰,便于追溯与协作

  • 分支命名规范(上位机推荐)

    复制代码
    feature/双扫描模式-20260604  # 新功能开发
    hotfix/急停逻辑修复-20260604 # 紧急bug修复
    release/v1.0.0-20260610      # 版本发布准备
    refactor/轴控制代码重构      # 代码重构优化
  • 项目实例
    remove-legacy-mainvm分支名可快速知道这是"移除老旧MainViewModel冗余代码"的优化任务,便于后续维护

5. 协作规范:强制质量门禁
  • 核心价值:通过Pull Request(PR)机制,合并前必须通过代码评审、自动化测试,确保代码质量
  • 项目实例
    双扫描模式开发完成后,发起PR请求合并到主分支,领导/同事可检查:
    • 限位报警是否触发整机停机
    • 急停是否同步记录日志
    • 操作互斥是否生效(运行中禁用启动按钮)
      问题修复后再合并,避免低级错误进入生产环境

三、实战应用

  1. 基础流程

    bash 复制代码
    # 1. 从主分支创建新功能分支
    git checkout main
    git pull
    git checkout -b feature/double-scan-mode
    
    # 2. 开发双扫描模式+急停+限位功能
    git add .
    git commit -m "feat:完成双扫描模式开发,添加急停和限位报警"
    
    # 3. 功能完成,合并到主分支
    git checkout main
    git merge feature/double-scan-mode
    
    # 4. 删除已完成分支
    git branch -d feature/double-scan-mode
  2. 紧急情况处理(如现场发现轴移动异常):

    bash 复制代码
    # 从主分支创建紧急修复分支
    git checkout main
    git checkout -b hotfix/axis-move-error
    
    # 修复问题并提交
    git commit -m "fix:解决轴移动时坐标跳变问题"
    
    # 快速合并到主分支并发布
    git checkout main
    git merge hotfix/axis-move-error

四、分支使用的关键原则

  1. 主分支神圣不可侵犯main分支永远保持可编译、可运行、可测试状态,仅用于发布版本
  2. 一个分支一个任务:避免在一个分支中同时开发多个不相关功能,便于管理和回滚
  3. 定期合并更新:功能分支开发期间,定期从主分支合并最新代码,减少冲突
  4. 及时清理分支:功能合并后删除分支,避免分支泛滥,保持仓库整洁

核心结论速览

  1. Git本地提交≠没用 :=本地安全网+进度存档,不联网也能随时回滚、实验和整理代码
  2. 团队协作必须提交到远程 :远程是团队的共享中枢,但建议先在本地分支完成开发+测试+冲突解决,再推送到远程
  3. 分支是Git的灵魂 :核心作用是隔离风险,让你在不影响主代码的前提下安全做事(如归档旧VM、修复bug、开发新功能)

一、不提交到远程,为什么还要用Git?(3个核心价值)

1. 本地版本"时光机"------随时回滚的安全网

Git本地提交会创建完整的代码快照 ,保存在你电脑的.git文件夹里,相当于给代码拍了"不可修改的照片"

  • 归档AxisControlViewModel时,如果改坏了项目文件,随时能回退到提交前的状态git reset --hard HEAD^
  • 开发时写坏代码、误删文件,都能通过git log找到历史版本恢复,不用怕"删了找不回"
  • 比手动备份更高效:一次git commit就能保存所有修改,还附带完整的修改记录和注释

2. 无网开发自由------飞机/地铁/断网时照写不误

Git本地操作完全不依赖网络,提交、分支切换、回滚都能离线完成

  • 在整理轴VM代码时,就算办公室断网,也能安全提交归档改动,等网络恢复再推送远程
  • 这是Git作为分布式版本控制系统的核心优势,每个开发者都有完整的本地仓库

3. 本地"草稿箱"------先整理再发布,避免远程污染

可以在本地多次提交、重构代码,直到功能稳定、测试通过后,再推送到远程共享

  • 比如你先在本地归档VM、修复消息契约、重构异步代码,分3次提交,等全部搞定再一次性推到远程
  • 避免把"半成品""有bug"的代码直接推到远程,影响团队其他成员

二、团队合作

"共享硬盘"

远程仓库(GitHub/GitLab/Gitee)是团队协作的唯一真相源,用于:

  • 同步所有人的代码,避免"各写各的,最后合并灾难"
  • 备份代码,防止本地电脑损坏导致代码丢失
  • 进行代码审查(PR/MR)、持续集成(CI)等团队协作流程

2. 推荐的团队协作流程

复制代码
本地开发 → 本地多次commit(存档) → 本地测试/修复 → git push到远程分支 → 团队评审 → 合并到主分支

先在本地分支archive-axiscontrolviewmodel完成文件移动+测试,确认无编译错误后再推到远程,让团队看到你的改动

  • 这样做的好处:本地先解决所有问题,再共享成果,避免把未完成的改动或错误代码直接推到主分支影响他人

三、分支有啥用?

1. 隔离风险------你的归档操作安全区

archive-axiscontrolviewmodel分支,就是专门用来隔离归档风险的"安全沙箱"

  • 即使在归档过程中不小心改坏了AxisEcatVM代码,也不会影响主分支的稳定版本
  • 测试通过后再合并到主分支,确保主线代码永远可运行、无冲突
  • 类比:办公室的"草稿区"整理文件,整理好再放到"正式文件柜"(主分支)
2. 并行开发------多人协作不打架

团队中不同人可以在不同分支做不同事,互不干扰

  • 你归档旧VM的同时,同事可以在feature-scan-optimize分支优化扫描算法,我在bugfix-async-error分支修复异步问题
  • 没有分支的话,所有人都在主分支改代码,很容易出现"你改了EtherCAT初始化,我又改了一遍,导致总线冲突"的问题
3. 版本管理------轻松管理不同状态的代码

分支可以用来区分开发/测试/生产环境,或保存不同版本的代码

  • main/master分支:稳定的生产版本
  • develop分支:日常开发的集成分支
  • feature-xxx分支:新功能开发分支
  • bugfix-xxx分支:紧急bug修复分支
  • 你的归档分支:专门保存"移除旧VM"这个历史状态,后续想恢复时随时可以找到
4. 实验自由------大胆尝试不怕失败

可以在分支上做任何实验性修改,失败了直接删除分支就行,不会影响主线

  • 比如你想尝试把AxisEcatVM的初始化逻辑移到MainShellVM,可以创建experiment-axis-init分支
  • 改坏了?直接git branch -D experiment-axis-init删除分支,回到主分支继续开发

1. 查看历史版本(两种核心命令)

命令 作用 上位机开发常用场景
git log 查看提交历史(完整版本链) 确认EtherCAT总线配置、Halcon算法的提交节点
git reflog 查看HEAD指针移动记录(含重置/删除操作) 恢复误操作git reset --hard丢失的代码

实战示例

bash 复制代码
# 简洁查看提交历史(带分支图)
git log --oneline --graph --decorate

# 查看所有操作记录(救命命令)
git reflog

2. 恢复历史版本(3种安全方案)

方案A:恢复整个项目到指定版本(谨慎使用)
bash 复制代码
# 先查看版本号(如a1b2c3d)
git reflog
# 硬重置(会丢弃本地修改)
git reset --hard a1b2c3d
方案B:恢复单个文件(上位机开发首选,不影响其他代码)
bash 复制代码
# 恢复EtherCAT配置文件到上一版本
git checkout HEAD^ -- ViewModel/EtherCATConfigViewModel.cs
# 恢复到指定版本的Halcon算法文件
git checkout 9f7d6e5 -- Services/HalconVisionService.cs
方案C:恢复丢失的提交(误操作后必用)
bash 复制代码
# 找到丢失的提交ID
git reflog
# 创建临时分支保存恢复内容
git branch recover-axis-control 7g8h9i0
# 合并到当前分支
git checkout main
git merge recover-axis-control

分支是Git中指向提交节点的指针,不是一个版本,而是一条独立的开发时间线。

1. 并行开发,互不干扰(核心价值)
  • 场景:同时开发「运动轴控制模块」和「机器视觉检测功能」

  • 操作

    bash 复制代码
    git checkout -b feature-axis-control  # 轴控制开发分支
    git checkout -b feature-vision-detect # 视觉检测分支
  • 好处:修改Halcon算法时不会影响EtherCAT总线代码,反之亦然

2. 隔离风险,保护稳定版本
  • 场景:调试新的DC同步逻辑可能引入bug
  • 操作 :在dev分支开发,稳定后再合并到main
  • 好处:上位机设备的生产环境代码始终稳定,避免调试中的bug导致设备停机
3. 版本管理,清晰迭代
  • 场景:设备需要V1.0、V2.0版本维护

  • 操作

    bash 复制代码
    git checkout -b release-v1.0  # 版本分支
    git tag v1.0  # 标记正式发布
  • 好处:不同版本的bug修复、功能扩展清晰分离,便于追溯

4. 团队协作,分工明确
  • 场景:我负责运动控制,同事负责UI界面
  • 操作:各自在专属分支开发,定期合并
  • 好处:避免代码冲突,提高开发效率

有多种安全方式,无需切换分支即可复用其他分支代码:

方法1:直接复制其他分支的文件(最常用)
bash 复制代码
# 当前在main分支,恢复来自feature-axis分支的轴控制文件
git checkout feature-axis -- ViewModel/AxisControlViewModel.cs
方法2:合并其他分支到当前分支(完整集成功能)
bash 复制代码
# 当前在main分支,合并feature-vision分支的视觉检测功能
git merge feature-vision
方法3:选择性合并单个提交(修复bug专用)
bash 复制代码
# 从bugfix分支提取修复EtherCAT连接问题的提交
git cherry-pick 4a5b6c7

历史版本解决"回退到过去"的问题,分支解决"同时走多条路"的问题。在上位机开发中:

  • 调试新的运动轴扫描逻辑 → 用分支(feature-scan-mode
  • 发现上周的EtherCAT配置更稳定 → 用历史版本恢复(git checkout 9f7d6e5 -- EtherCATConfig.cs
  • 既要保留当前功能,又要尝试新算法 → 分支+历史版本结合使用

  1. 主分支保护main分支只存稳定版本,禁止直接提交
  2. 功能分支 :新功能(如Halcon视觉优化)从main创建feature-xxx分支
  3. 修复分支 :bug修复(如运动轴定位偏差)从main创建bugfix-xxx分支
  4. 版本分支 :发布时创建release-vx.x分支,便于后续维护
  5. 定期合并 :功能稳定后,通过Pull Request合并到main

提交到团队远程仓库后,依然可以回退!**


情况1:你只在本地提交了 → 还没推送到远程(git push 没执行)

随便回退!无任何风险

bash 复制代码
git reset --hard HEAD^

直接撤销本地最后一次提交,别人完全不知道,也不受影响。


情况2:你已经 git push 推送到团队远程仓库(重点!)

禁止使用 git reset --hard

必须使用:git revert

为什么不能用 reset?

  • reset删除历史提交
  • 团队其他人已经拉了你的代码
  • 你一 reset 再强制推送 → 所有人的代码历史冲突、文件丢失
  • 工控/上位机代码绝对禁止这么干!

git revert 是什么?

不删除历史 ,而是新建一个"反向提交" ,把错误代码撤销掉,历史记录完整保留。

团队安全、合规、唯一标准做法!


消息

消息 = 一张「带文字/带数据的纸条」

场景:

你在办公室(主VM),

工人在车间(轴VM),

摄影师在暗房(图像VM),

三个人互相不说话、不串门、不认识

你想让工人移动机器 → 写一张纸条扔过去;

工人到位了 → 写一张纸条扔给摄影师拍照;

你想紧急停机 → 写一张纸条扔给所有人。

这张纸条,就是「消息」。


二、消息是什么?

项目有3个核心模块:

  1. 主界面VM(发指令)
  2. 轴控制VM(动XY轴)
  3. X光图像VM(拍照片)

这三个模块不能直接互相调用 (工业软件规范,解耦),

所以它们靠 消息 传递指令和数据。


三、消息的两种形式

1. 空消息 = 只喊口令,不带数据

就像喊:开始!停止!

csharp 复制代码
// 空消息:只告诉轴VM「开始扫描」,不说扫哪里
public class StartScanMessage { }

2. 带载荷的消息 = 口令 + 数据

就像喊:移动到 X=10,Y=20,曝光50ms!

csharp 复制代码
// 带数据的消息:指令+参数一起发
public class StartScanMessage
{
    public double TargetX { get; } // 坐标
    public double TargetY { get; }
    public int ExposureTime { get; } // 曝光时间
}

消息 = 模块之间的「通信工具」

主VM、轴VM、图像VM 互不依赖、互不引用,

却能完美配合工作:

  1. 主VM发消息 → 轴VM动
  2. 轴VM发消息 → 图像VM拍照
  3. 任意VM发消息 → 全局写日志

流程:

  1. 点「开始扫描」按钮

    → 主VM 发送一条消息

    我要扫X=10,Y=20,曝光50ms

  2. 轴控制VM 收到消息

    → 读取消息里的坐标,控制电机移动

  3. 轴到位了

    → 轴VM 发送一条消息

    我到位置了,可以拍照了

  4. X光图像VM 收到消息

    → 启动探测器采集图像

全程三个模块谁也不认识谁 ,全靠消息传话!


消息 = 模块之间传递的「指令 + 数据」,
是工业软件里,让不同功能互不干扰、协同工作的核心工具。

不可变 DTO


不可变 DTO = 只读数据传输对象

对象创建之后,永远不能被修改 ,所有数据只能在初始化时赋值,没有任何地方可以改写它。

DTO (Data Transfer Object):数据传输对象,专门用来存数据、传数据,不写业务逻辑(比如你的轴坐标、扫描结果、检测数据)。


核心特征

  1. 只有 get,没有 set(外部不能改)
  2. 只能通过构造函数初始化赋值
  3. 线程安全(多线程随便传,不会被篡改)
  4. 纯数据,无逻辑、无状态变化

为什么必须用不可变 DTO**?

异步多线程Task.Run/async/await)、运动控制状态实时刷新,普通可变对象会出大问题:

  1. 多线程篡改数据:UI线程、扫描线程、Halcon线程同时改同一个对象 → 轴坐标错乱、状态异常
  2. 工控安全风险:扫描参数、限位值被意外修改 → 设备撞机、误动作
  3. Bug 难排查:数据不知道被谁改了,溯源极难
  4. MVVM 规范:纯数据和业务逻辑分离,代码更整洁

不可变 DTO 直接根治这些问题


代码对比:可变 vs 不可变

1. ❌ 普通可变DTO

csharp 复制代码
// 危险!任何地方都能改,多线程会乱
public class ScanResultDTO
{
    // 公有set,随时能被篡改
    public int DefectCount { get; set; } 
    public double PosX { get; set; }
    public bool IsOk { get; set; }
}

2. ✅ 不可变DTO

C# 推荐写法:init 仅初始化赋值(创建后不能改)

csharp 复制代码
/// <summary>
/// X光检测结果 不可变DTO
/// </summary>
public class ImmutableScanResult
{
    // 只有get,无set → 绝对不能修改
    public int DefectCount { get; init; }
    public double AxisPosX { get; init; }
    public bool IsQualified { get; init; }
    public string ScanMode { get; init; }

    // 必须通过构造函数一次性赋值
    public ImmutableScanResult(int defectCount, double posX, bool isQualified, string scanMode)
    {
        DefectCount = defectCount;
        AxisPosX = posX;
        IsQualified = isQualified;
        ScanMode = scanMode;
    }
}

不可变 DTO 不是消息,但它是「消息的标准载体」

消息 = 快递包裹(用来传递通知)

不可变 DTO = 包裹里的货物(只读、不能改的核心数据)


消息 = 模块/线程之间发的通知

比如:

  • 轴到位了
  • 检测完成了
  • 触发急停了
  • 限位报警了
  • 扫描进度更新

消息的作用:发通知,告诉别的代码发生了什么事

「不可变 DTO」?

只读数据容器,创建后不能修改,专门存数据。


不可变 DTO = 消息体(消息里携带的数据)

消息 = 发送通知 + 携带不可变 DTO

工业上位机标准规范:

跨线程、跨模块发消息,必须用不可变DTO装数据

因为消息会在 运控线程 / UI线程 / Halcon线程 之间传递,可变对象会被篡改,导致设备撞机、数据错乱


partial

把一个类/方法,拆成多份写在不同地方,编译时自动合并成一个完整的整体


原因

CommunityToolkit.Mvvm[ObservableProperty]/[RelayCommand]):

  • 手写代码(逻辑、命令、属性)
  • 编译器自动生成代码(命令、通知属性、回调方法)

这两部分代码必须靠 partial 合并,否则无法一起工作!

手写的代码(AxisControlViewModel.cs)

csharp 复制代码
// 必须加 partial!
public partial class AxisControlViewModel : ObservableObject
{
    // 自动生成 DcSyncOk 属性
    [ObservableProperty]
    private bool _dcSyncOk;

    // 自动生成 StartScanCommand 命令
    [RelayCommand]
    private async Task StartScan() { }
}
2. 编译器自动生成的隐藏代码(AxisControlViewModel.g.cs)
csharp 复制代码
// 和上面是同一个类,靠 partial 合并
public partial class AxisControlViewModel
{
    // 自动生成的公开属性
    public bool DcSyncOk { ... }
    // 自动生成的命令
    public IRelayCommand StartScanCommand { ... }
}

最终结果

编译后,两个文件合并成一个完整的类,你手写的逻辑 + 自动生成的MVVM代码完美结合。


二、partial 另外两个常见用途

1. 拆分超大代码

一个类代码太多,拆成两个文件,方便维护:

MainViewModel.cs + MainViewModel.Axis.cs,都是 partial class,互不干扰。

2. 分部方法

比如:

csharp 复制代码
// 编译器自动生成
partial void OnDcSyncOkChanged(bool value);

// 你可以手动实现(不写也不会报错)
partial void OnDcSyncOkChanged(bool value)
{
    StartScanCommand.NotifyCanExecuteChanged();
}

这也是 partial 的用法。


sealed 密封类

sealed = 密封、上锁 → 加在类上,表示「这个类禁止被继承**,谁都不能派生子类」**


csharp 复制代码
// 密封 + 分部 = ViewModel标配
public sealed partial class AxisControlViewModel : ObservableObject
{
}

如果不加 sealed,别人可以随便继承ViewModel:

csharp 复制代码
// 错误用法:继承轴控制VM
public class BadViewModel : AxisControlViewModel 
{
   // 会覆盖、篡改原有轴控逻辑,导致硬件失控
}

加了 sealed ,上面的代码直接编译报错,从根源禁止乱继承。


3. 为什么 ViewModel 必须加 sealed?

  1. 安全第一
    轴控制、相机、EtherCAT 逻辑是核心硬件代码,绝对不允许被随意继承、重写,防止逻辑被篡改导致设备故障。
  2. 无继承需求
    WPF 每个页面对应一个独立 VM,从来不需要继承另一个 VM
  3. 性能微优化
    密封类让编译器运行更快(几乎感知不到,但属于规范)。
  4. MVVM 最佳实践
    用了 CommunityToolkit.Mvvm 的 VM,官方推荐一律写 sealed partial class

相关推荐
Rain5091 小时前
实战:搭建 AI Code Review 自动化流水线
前端·人工智能·git·ci/cd·自动化·ai编程·代码复审
zzzzzz3101 小时前
GitHub 今日爆火!headroom:一个帮你省 60-95% Token 的 AI Agent 上下文压缩神器
git·机器学习·github
张小凡vip3 小时前
gitlab的ci配置文件yaml参数说明
git·ci/cd·gitlab
搬砖的前端3 小时前
AI工具集:Git提交时使用AI进行CodeReview如何在前端应用构建NPM包
前端·人工智能·git·npm·codeview
ZXF_H4 小时前
Git clone 时遇到fatal: protocol ‘http‘ is not supported问题解决方法
git
傻啦嘿哟4 小时前
日志分析:利用OpenClaw日志排查“403”和“503”错误
java·git·github
摆烂菜鸡沧9964 小时前
【自用记录】修改GitHub提交历史作者
git·github
佳木逢钺14 小时前
Git分支强制覆盖与冲突解决实战记录
git·源代码管理
屋外雨大,惊蛰出没20 小时前
Git基本应用
git