Git笔记

⚪日常最常用的就这些:

初始化(只做一次)

复制代码
git clone git@github.com:xieqihang666-prog/SLE-UNet.git
cd SLE-UNet

每天开发

复制代码
git switch -c 功能名     # 创建分支
# 写代码...
git add .               # 加入暂存区
git commit -m "做了什么"  # 提交到本地
git push -u origin 功能名 # 推到远程(第一次加 -u,之后直接 git push)

合并到主线

复制代码
git switch dev                          # 切到 dev
git pull                                # 拉取最新
git merge --no-ff -m "说明" 功能名        # 合并
git push                                # 推到远程

常用辅助

复制代码
git status          # 看当前状态
git log --oneline   # 看提交历史
git stash           # 临时保存修改
git stash pop       # 恢复保存的修改
git branch -a       # 看所有分支

记住核心循环:改代码 → add → commit → push,反复执行就行。

特性 集中式(SVN) 分布式(Git)
仓库位置 仅在服务器上 每个开发者本地都有完整仓库
离线工作 不行 完全可以
历史记录 只在服务器 每个人本地都有全部历史
单点故障风险 高,服务器挂了就停工 低,任一副本都可恢复
分支操作 重量级,依赖网络 轻量级,本地瞬间完成
⚪2、Git 把内容按元数据方式存储,而 SVN 是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里。这句话什么意思

Git 的存储方式:基于内容快照(Snapshot)

Git 关注的是"整个项目在这一刻长什么样"。每次提交时,Git 会对所有文件内容做 SHA-1 哈希,生成一棵对象树。Git 内部有三种核心对象:

  • blob:存储文件内容(注意,只存内容,不存文件名)
  • tree:记录目录结构,把文件名和 blob 对应起来
  • commit:记录某次提交指向哪棵 tree,以及作者、时间、父提交等信息

所以原文说"按元数据方式存储",意思是 Git 不是简单地按文件路径管理版本,而是把所有内容拆解成这些哈希索引的对象来管理。文件名、目录结构这些"元信息"和文件内容是分开存储的。

一个直观的例子:

假设你有两个不同路径的文件,内容完全一样:

复制代码
src/model.py    →  内容哈希: a1b2c3
backup/model.py →  内容哈希: a1b2c3
⚪这四个概念是 Git 工作流中的四个区域,数据就是在这四个区域之间流转的。

Workspace(工作区)

就是你电脑上实际看到的项目文件夹。比如你打开 PyCharm 看到的那些 .py 文件、README.md 等,都在工作区里。你直接编辑代码、新增文件、删除文件,这些操作都发生在工作区。此时的修改 Git 知道有变化(git status 能看到),但还没纳入版本管理。

Staging Area(暂存区)

这是工作区和本地仓库之间的一个"中转站"。当你执行 git add model.py 时,就是把 model.py 的当前修改放入暂存区。暂存区的意义在于让你可以选择性提交------比如你改了 5 个文件,但只想提交其中 2 个,就只 add 那 2 个。暂存区实际存储在 .git/index 文件中。

Local Repository(本地仓库)

执行 git commit 后,暂存区的内容就被正式记录到本地仓库中,生成一个 commit 对象(带有 SHA-1 哈希、作者信息、时间戳等)。本地仓库存储在 .git 文件夹里,包含了项目的全部提交历史。前面说的"分布式"就体现在这里------你本地就有完整的版本历史,不需要联网。

Remote Repository(远程仓库)

就是 GitHub、GitLab 这类服务器上的仓库。执行 git push 把本地仓库的提交推上去,执行 git pull 把远程的更新拉下来。它的作用是团队协作的同步点。

用你的实际开发场景串一遍流程:

假设你在改 SLE-UNet 的代码:

  1. 你在编辑器里修改了 sle_unet.py工作区发生变化)
  2. git add sle_unet.py(修改进入暂存区
  3. git commit -m "优化LPD模块结构"(暂存区的内容写入本地仓库,生成一条提交记录)
  4. git push origin main(本地仓库的提交同步到远程仓库,同学也能看到了)

数据流向就是:工作区 → 暂存区 → 本地仓库 → 远程仓库 ,反过来拉取时则是 远程仓库 → 本地仓库 → 工作区

每一列就是一次 git commit,相当于给整个项目拍了一张"照片",记录了那个时刻所有文件的状态。

为什么能记住每次修改?

核心原因是每次 git commit 时,Git 都会做两件事:

第一,对当前所有文件的内容生成快照,存储为 blob 对象,并用 SHA-1 哈希作为唯一标识。没有改变的文件不会重复存储,Git 只是让新的快照指向之前已有的 blob。比如 V2 到 V3 中文件 A 没变,Git 不会再存一份 A1,而是直接复用之前的引用。

第二,生成一个 commit 对象,里面包含指向当前快照的指针、作者信息、时间戳,以及指向上一次 commit 的指针(父提交)。这样所有 commit 就形成了一条链:

复制代码
V1 ← V2 ← V3

通过这条链,Git 可以从任意一个版本往回追溯到项目的最初状态。你执行 git log 看到的提交历史就是这条链。想回到任何一个版本,只需要 git checkout 到对应的 commit 哈希,Git 就把那个时刻的完整快照恢复出来。

所以 Git 记住每次修改的本质就是:每次提交都保存一份完整的项目快照,所有快照通过链式结构串联起来,永久保存在 .git 目录中,不会丢失。

⚪这里git为什么可以本地提交,但是不用push,push代表什么意思,本地代表什么意思?git commit是不是本地提交一次

这张图很好地展示了 Git 分布式的核心优势。

本地提交(git commit)是什么意思?

git commit 是把你的修改记录到本地仓库(就是你电脑上 .git 文件夹里的数据库)。每执行一次 git commit,就在本地生成一条提交记录。这个过程完全在你自己的机器上完成,不需要网络。

图中三个开发者的状态很能说明问题:

  • 开发者 A:本地提交了 2 次,已经 push 到 GitHub------一切正常同步
  • 开发者 B:本地提交了 8 次,断网了,还没 push------但这 8 次提交完好地保存在本地仓库里,代码一点没丢
  • 开发者 C:本地提交了 1 次,还没 push------同样没问题,提交已经在本地记录了

push 代表什么意思?

git push 是把本地仓库中的提交上传到远程仓库(图中的 GitHub)。你可以理解为"同步上传"。push 的目的是让团队其他人能看到你的修改。

为什么可以本地提交但不 push?

因为 Git 是分布式的,你本地就有一个完整的版本库。commitpush 是两个独立的操作:

复制代码
# 这一步只在本地完成,不需要网络
git commit -m "修改了LPD模块"

# 这一步才需要网络,把本地的提交推到远程
git push origin main

就像开发者 B 的情况------断网了照样工作,本地提交了 8 次,等网络恢复后一个 git push 就能把 8 次提交全部同步到 GitHub。

第一个问题:.git 文件夹是不是存了所有本地修改记录?

是的。.git 文件夹就是你的本地仓库,所有提交历史都在里面。你可以看看它的结构

复制代码
.git/
├── objects/     # 所有的 blob、tree、commit 对象都存在这里
├── refs/        # 分支指针,记录每个分支指向哪个 commit
├── HEAD         # 当前在哪个分支上
├── index        # 暂存区的内容
└── logs/        # 操作日志

如果你把 .git 文件夹删了,整个版本历史就全没了,项目就变成一个普通文件夹。

第二个问题:多次提交会覆盖吗?

不会。每次 git commit 都是新增一条记录,而不是覆盖之前的。所有提交是以链表的方式串起来的:

复制代码
commit1 ← commit2 ← commit3 ← commit4(当前最新)

每个 commit 都保存了完整的项目快照,并且通过"父指针"指向前一个 commit。所以 commit1 到 commit4 全部完好保存着,任何一个都可以随时回退查看。

举个实际例子:

复制代码
# 第一次提交
git commit -m "完成LPD模块初版"      # 生成 commit1,哈希 a1b2c3

# 第二次提交(修改了同一个文件)
git commit -m "优化LPD模块性能"      # 生成 commit2,哈希 d4e5f6

# 两个提交都在,互不影响
git log
# d4e5f6 优化LPD模块性能      ← 最新
# a1b2c3 完成LPD模块初版      ← 依然存在

# 随时可以回到第一次提交的状态
git checkout a1b2c3
⚪使用 Git 和 GitHub 之前的三步配置。

这张图展示的是首次使用 Git 和 GitHub 之前的三步配置。

第一行:设置用户名

复制代码
git config --global user.name songyuanyaun

告诉 Git "我是谁"。以后每次 git commit 时,这个名字会被记录在提交信息里,其他人就知道这次提交是谁做的。--global 表示全局生效,对这台电脑上所有 Git 仓库都适用。

第二行:设置邮箱

复制代码
git config --global user.email 1667846898@qq.com

和用户名一样,邮箱也会写入每次提交记录中。这个邮箱最好和你 GitHub 账号注册的邮箱一致,这样 GitHub 才能把提交记录和你的账号关联起来,在贡献者列表里显示你的头像。

第三行:生成 SSH 密钥

复制代码
ssh-keygen -t rsa -C 1667846898@qq.com

这是最关键的一步,用来建立你本地电脑和 GitHub 之间的安全通信通道。执行后会在 ~/.ssh/ 目录下生成两个文件:

  • id_rsa:私钥,留在本地,绝对不能给别人
  • id_rsa.pub:公钥,需要复制粘贴到 GitHub 的 SSH Keys 设置里

配置好之后,你 git pushgit pull 时就不用每次输密码了,Git 会通过 SSH 密钥自动验证你的身份。

这三步做完之后,你的本地 Git 就和 GitHub 建立了信任关系,可以自由地 push 和 pull 了。这是每台新电脑上只需要配置一次的操作。

第一行:查看公钥内容

复制代码
cat id_rsa.pub

cat 是打印文件内容的命令。这里把你的 SSH 公钥文件打印出来。

第二行:测试与 GitHub 的 SSH 连接

复制代码
ssh -T git@github.com
为什么要这么多分支?

四条分支各自的角色:

master(蓝色):主分支,存放的是稳定的、可以发布的代码。你看它上面的节点(圆圈)很少,因为不是随便什么代码都能直接进 master,只有经过测试验证的代码才会被合并进来。

dev(红色) :开发主线。日常开发都汇总到这里。当 dev 上的功能积累到一个稳定版本时,才会合并到 master。图中可以看到 dev 和 master 之间有连线,那就是合并的时刻。

michael(青色)和 bob(黄色):这是两个开发者的个人分支。michael 和 bob 各自在自己的分支上写代码,互不干扰。写完一个功能后,再合并到 dev。图中那些斜线就是他们把自己的代码合并到 dev 的过程。

为什么要这么多分支?

核心目的是隔离风险。用你的实际场景举例:假设你和同学一起开发项目,你负责 LPD 模块,同学负责 TBED 模块。如果两个人都在同一条线上改代码,很容易互相冲突,改坏对方的东西。

⚪解释为什么git merge 为什么带参数--no--ff 和-m

这两个参数各有各的作用。

--no-ff 是什么意思?

ff 是 fast-forward(快进合并)的缩写。--no-ff 就是"不要快进合并"。

区别在于:

默认的 fast-forward 合并,如果 dev 没有新提交,Git 会直接把 dev 指针移到 xiaoming 的最新提交上,不会产生新的合并节点。历史记录是一条直线,看不出曾经有过分支:

复制代码
dev: A → B → C(xiaoming的提交)

加了 --no-ff 之后,Git 会强制创建一个新的合并提交(merge commit),即使可以快进也不快进。历史记录能清楚看到分支的存在:

复制代码
dev: A → B ------------→ M(合并提交)
          \     /
xiaoming:  → C →

这样做的好处是,以后看 git log 能明确知道"这些提交是从 xiaoming 分支合并过来的",项目历史更清晰。

-m 是什么意思?

git commit -m 一样,给这次合并提交写一条说明信息。图中写的是:

复制代码
-m "小明完成开发V1"

如果不加 -m,Git 会自动打开编辑器让你写合并信息。加了 -m 就直接在命令行里指定了,省去手动编辑的步骤。

图中完整命令的含义:

复制代码
git merge --no-ff -m "小明完成开发V1" xiaoming
git merge xqh git merge --no-ff
能否看出分支历史 不能,变成直线 能,保留分支痕迹
合并提交 不产生 产生一个
适合场景 个人小改动 团队协作、功能分支
⚪第一次推送时执行 git push -u origin dev,Git 会做两件事:
  1. 把本地 dev 分支推送到远程 origin/dev
  2. 建立本地 dev 和远程 origin/dev 之间的绑定关系
相关推荐
练习时长一年6 小时前
我的开发笔记
笔记
生瓜硬劈..6 小时前
SQL 调优全解:从 20 s 到 200 ms 的 6 步实战笔记
java·笔记·sql
不早睡不改名@6 小时前
Netty源码分析---Reactor线程模型深度解析(一)
java·笔记·学习·netty
祁白_7 小时前
Bugku:备份是一个好习惯
笔记·学习·web安全·ctf
野指针YZZ7 小时前
XV6操作系统:内存学习笔记
笔记·学习
sanshanjianke8 小时前
《DeepSeek 的 50 次初恋》
笔记
chase。8 小时前
【学习笔记】迈向通用神经运动规划器——深度学习如何重塑机器人操作手的“思考”方式
笔记·深度学习·学习
csdn_aspnet8 小时前
Git二分法精准定位Bug,分享用git bisect快速锁定引入缺陷的提交,提升调试效率
git·bug·二分查找
freexyn8 小时前
Matlab自学笔记七十五:(求解+绘图)函数的图像和零点,以二次函数为例,使用最简单的代码完成作业
开发语言·笔记·matlab