news 2026/9/26 3:11:55

Clone-Git Add-Git Commit

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Clone-Git Add-Git Commit

找了一个使用 Python 编写的车辆动力学仿真项目,可以根据油门、制动、转向等输入,计算车辆动力系统、轮胎以及车身状态。用它来:

找到一个现有项目中的问题,分析原因,修改代码,验证结果,然后使用 Git 保存这次修改。

这是我第一次完整走通这样的 Bug 修复流程。


1. Clone 项目并运行

首先从 GitHub 将仓库 Clone 到本地。

这里我第一次真正理解了Clone和Download ZIP的区别。

Download ZIP基本只是:

GitHub 当前代码 ↓ 下载一份文件 ↓ 本地普通文件夹

而 Clone 得到的是:

远程 GitHub 仓库 ↕ 本地 Git 仓库

除了代码,还保留了 Git 历史以及远程仓库关系。

项目 Clone 完成后,我用 VS Code 打开项目。

目录大致为:

vehicle-dynamics/ │ ├─ example_data/ ├─ vehicle_dynamics/ │ ├─ modules/ │ ├─ structures/ │ └─ utils/ │ ├─ bmw_m8.yaml ├─ main.py ├─ pyproject.toml ├─ README.md └─ setup.py

第一次运行:

python main.py

出现:

ModuleNotFoundError: No module named 'yaml'

原因是代码虽然已经下载下来了,但 Python 环境中还没有安装这个项目需要的依赖。

于是执行:

python -m pip install -e .

这里:

pip install

负责安装 Python 包。

-e

表示 Editable Install,可编辑安装。

.

表示安装当前目录中的 Python 项目。

执行后,项目所需要的:

numpy scipy matplotlib pandas PyYAML tqdm ...

都被安装完成。

再次:

python main.py

项目成功运行。


2. 项目成功运行,但发现了一个奇怪现象

正常运行以后,项目根目录突然多出了一个:

Braking.pickle

但项目本身已经有:

example_data/ └─ Braking.pickle

也就是说,运行程序之后出现了两份:

vehicle-dynamics/ │ ├─ example_data/ │ └─ Braking.pickle │ └─ Braking.pickle

这显然值得检查。

于是打开根目录的main.py。

发现这里:

file_path = "example_data/Braking.pickle" url = "https://github.com/roadview-project/vehicle-dynamics/raw/refs/heads/main/example_data/Braking.pickle" urllib.request.urlretrieve(url, "Braking.pickle") os.makedirs(os.path.dirname(file_path), exist_ok=True) if not os.path.exists(file_path): print(f"{file_path} not found. Downloading from {url}...") urllib.request.urlretrieve(url, file_path) print("Download complete!") else: print(f"{file_path} already exists. Skipping download.")

问题就出在:

urllib.request.urlretrieve(url, "Braking.pickle")

这一行。

它位于文件存在判断之前。

因此每次运行程序时,不管:

example_data/Braking.pickle

是否已经存在,Python 都会先执行:

urllib.request.urlretrieve(url, "Braking.pickle")

于是根目录就会被额外下载一份:

Braking.pickle

下面的判断:

if not os.path.exists(file_path):

只负责判断:

example_data/Braking.pickle

是否存在。

所以正确逻辑其实应该是:

检查 example_data/Braking.pickle ↓ 是否存在? / \ 是 否 ↓ ↓ 跳过 下载

而原来的逻辑实际上是:

先下载一份到根目录 ↓ 再检查 example_data 中有没有

这就造成了重复文件。


3. 不直接修改 main,而是创建 Bug 修复分支

这次我没有直接在main分支修改。

首先创建一个新的分支:

git switch -c fix/duplicate-braking-download

这条命令可以拆开理解:

git switch

切换分支。

-c

Create,新建分支。

fix/duplicate-braking-download

是分支名称。

执行成功:

Switched to a new branch 'fix/duplicate-braking-download'

此时可以理解为:

原来的 main │ ● \ └─ fix/duplicate-braking-download

目前两个分支代码还是一样的。

后面我们的 Bug 修复只发生在:

fix/duplicate-braking-download

分支。

这样即使修改失败,main仍然保持原样。


4. 修改代码

修复非常简单。

删除这一行:

urllib.request.urlretrieve(url, "Braking.pickle")

修改后:

file_path = "example_data/Braking.pickle" url = "https://github.com/roadview-project/vehicle-dynamics/raw/refs/heads/main/example_data/Braking.pickle" os.makedirs(os.path.dirname(file_path), exist_ok=True) if not os.path.exists(file_path): print(f"{file_path} not found. Downloading from {url}...") urllib.request.urlretrieve(url, file_path) print("Download complete!") else: print(f"{file_path} already exists. Skipping download.")

现在下载动作只会发生在:

if not os.path.exists(file_path):

成立的时候。

也就是说,只有文件真的不存在才下载。


5. 一个很容易忽略的问题:修改后必须保存

这次过程中我还遇到了一个很典型的问题。

我明明在 VS Code 中删除了代码,但是运行:

git status

Git 却没有提示:

modified: main.py

执行:

git diff

也什么都没有。

后来才发现:

我修改了 VS Code 编辑器中的内容,但是没有按Ctrl + S。

这时候:

VS Code 编辑器中的内容

和:

硬盘上的 main.py

其实不是同一个状态。

Python 和 Git 读取的都是硬盘上的文件。

所以:

修改代码 ↓ Ctrl + S ↓ 保存到硬盘 ↓ Python / Git 才能看到变化

保存后,VS Code 左侧main.py出现:

M

这里:

M = Modified

说明 Git 已经发现这个文件发生了修改。


6. 使用 Git 确认到底修改了什么

保存之后运行:

git status

得到:

On branch fix/duplicate-braking-download Changes not staged for commit: modified: main.py

这说明:

当前分支: fix/duplicate-braking-download 被修改的文件: main.py

然后执行:

git diff

Git 显示:

- urllib.request.urlretrieve(url, "Braking.pickle")

这里的:

-

表示这行代码被删除。

这一步非常有用。

因为在真正提交之前,可以先检查:

我究竟改了什么?

这次git diff只有一行删除,说明没有误改其他代码。


7. 重新运行程序验证 Bug

先删除之前旧代码生成的根目录文件:

Braking.pickle

但是保留:

example_data/ └─ Braking.pickle

然后再次:

python main.py

程序输出:

example_data/Braking.pickle already exists. Skipping download.

车辆动力学仿真继续正常运行:

100%|████████████████████| 9001/9001

运行完成后检查目录:

vehicle-dynamics/ │ ├─ example_data/ │ └─ Braking.pickle │ ├─ main.py ├─ bmw_m8.yaml └─ ...

根目录没有再次生成:

Braking.pickle

这说明:

Bug 修复成功,同时没有破坏项目原本的运行逻辑。


8. Git Add:准备提交修改

确认修复没有问题后执行:

git add main.py

git add并不等于保存版本。

它更像是在告诉 Git:

下一次 Commit,我准备把main.py的这些修改包含进去。

再次:

git status

可以看到:

Changes to be committed: modified: main.py

也就是说:

工作区修改 ↓ git add ↓ 暂存区

9. 第一次 Commit

最后执行:

git commit -m "Fix duplicate Braking.pickle download"

Git 返回:

[fix/duplicate-braking-download e7aca10] Fix duplicate Braking.pickle download 1 file changed, 1 deletion(-)

这里包含很多重要信息。

fix/duplicate-braking-download

是当前分支。

e7aca10

是这个 Commit 的短 ID。

Fix duplicate Braking.pickle download

是 Commit Message。

1 file changed

说明修改了一个文件。

1 deletion(-)

说明删除了一行代码。

此时 Git 历史大致变成:

原作者代码 │ ● main \ ● e7aca10 Fix duplicate Braking.pickle download ↑ fix/duplicate-braking-download

至此,一次完整的 Bug 修复完成。


10. 这次真正学到的,不只是删除一行代码

这次 Bug 本身其实非常简单,只删除了一行:

urllib.request.urlretrieve(url, "Braking.pickle")

但完整流程比这行代码本身更重要。

我第一次真正走通了:

Clone 开源项目 ↓ 安装项目依赖 ↓ 运行项目 ↓ 发现异常现象 ↓ 阅读源码定位原因 ↓ 创建 Git Branch ↓ 修改代码 ↓ Ctrl + S 保存 ↓ git status ↓ git diff ↓ 运行程序验证 ↓ git add ↓ git commit

以前学习 Git 时:

branch commit diff status

这些词很容易变成需要背诵的概念。

真正修一次 Bug 以后,它们的用途就清楚很多:

  • branch:给修改建立一条独立的开发路线。

  • git status:现在仓库是什么状态,哪些文件发生了变化。

  • git diff:具体改了哪几行。

  • git add:选择哪些修改进入下一次提交。

  • git commit:把这一次完整修改保存成一个版本。


后续

这次运行项目时,还发现了另一个问题:

RuntimeWarning: invalid value encountered in scalar divide

位置在:

vehicle_dynamics/utils/plot_function.py

与轮胎滑移率计算有关。

初步检查发现,在车辆速度和轮速同时为 0 时,部分绘图代码可能产生:

0 / 0

不过这属于另外一个独立问题。

所以我没有在这次 Commit 中一起修改。

下一步准备继续按照:

一个问题 → 一个修复 → 一次测试 → 一个 Commit

的方式处理这个 Warning。

这样 Git 历史也会更加清楚。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 3:10:44

生产级智能体平台实战:任务编排、工具管理与运行监控

1. 从单机脚本到生产级智能体平台:为什么“能跑”和“敢用”之间隔着一整个工程体系很多人第一次接触 Agent,都是从一段几十行的脚本开始的:调一个模型接口,塞几个工具函数,跑通一个“查天气发邮件”的流程&#xff0c…

作者头像 李华
网站建设 2026/9/26 3:09:20

Linux系统:IPC进程间的通信--共享内存

一 共享内存本质上是内存预留的一块空间,就是一块物理空间,进程间的复制是虚拟的空间。内核物理内存,映射到多个不同进程的虚拟地址空间。多个进程可以直接读写这块内存,实现进程间的通信。两个进程通过唯一的key对应一个IPC对象/…

作者头像 李华
网站建设 2026/9/26 3:07:58

Git合并冲突深度解析:从<<<<<<< HEAD到日常规避

“<<<<<<< HEAD”——看到这一串符号的那一刻&#xff0c;别说新人&#xff0c;就是干了几年的人偶尔也会头皮发紧。这七个左箭头加上HEAD&#xff0c;翻译成人话就是&#xff1a;你的代码和别人的代码在同一行怼上了&#xff0c;Git不知道听谁的&#xf…

作者头像 李华
网站建设 2026/9/26 3:06:58

Claude Code Templates:用CLI和MCP模板一键配置AI编程助手

1. 项目缘起与核心价值拆解第一次看到claude-code-templates这个项目名&#xff0c;我的直觉是&#xff1a;这大概率是一个围绕 Claude Code 做“脚手架”和“模板库”的工程化项目。事实也确实如此。Claude Code 是 Anthropic 推出的命令行 AI 编程助手&#xff0c;它能在终端…

作者头像 李华
网站建设 2026/9/26 3:06:19

FLIM系统硬件架构设计:从光学分类到电路选型与调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华