惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
T
The Exploit Database - CXSecurity.com
The GitHub Blog
The GitHub Blog
量子位
S
SegmentFault 最新的问题
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Proofpoint News Feed
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Threat Research - Cisco Blogs
I
Intezer
Hugging Face - Blog
Hugging Face - Blog
Spread Privacy
Spread Privacy
Microsoft Security Blog
Microsoft Security Blog
P
Proofpoint News Feed
Know Your Adversary
Know Your Adversary
人人都是产品经理
人人都是产品经理
G
Google Developers Blog
Cyberwarzone
Cyberwarzone
L
LINUX DO - 热门话题
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tenable Blog
Jina AI
Jina AI
A
About on SuperTechFans
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MyScale Blog
MyScale Blog
AWS News Blog
AWS News Blog
宝玉的分享
宝玉的分享
WordPress大学
WordPress大学
T
Threatpost
大猫的无限游戏
大猫的无限游戏
I
InfoQ
T
Tor Project blog
Project Zero
Project Zero
F
Full Disclosure
L
Lohrmann on Cybersecurity
P
Palo Alto Networks Blog
G
GRAHAM CLULEY
B
Blog
Apple Machine Learning Research
Apple Machine Learning Research
The Hacker News
The Hacker News
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
V2EX
The Cloudflare Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security

qlAD 的技术笔记

2026 年 6 月 7 日 -- 我有社交恐惧症,恐惧外面到处雷电风雨声(大学生活记录) 手把手带你实现哈希表(C/C++ 数据结构) 手把手带你实现图结构(C/C++ 数据结构) 手把手带你实现二叉树(C/C++ 数据结构) 手把手带你实现栈和队列(C/C++ 数据结构) 手把手带你实现单/双链表(C/C++ 数据结构) 手把手带你实现动态数组(C/C++ 数据结构) 2026 年 1 月 2 日 -- 我不怕冷,因为我内心炽热 【2025 年度总结】(大学生活记录) 2025 年 12 月 2 日 -- 省电模式:大一 100 天耗电日志(大学生活记录) 蓝桥杯备赛第一期 —— 枚举与模拟 2025 年 11 月 3 日 -- 用爱发电、大爱无私(大学生活记录) 使用循环嵌套输出规则图形找规律讲解(嵌套循环-图形输出) 2025 年 10 月 1 日 -- 二字开头第一年的生日记录及感悟随笔(大学生活记录) Python 初级 04 -- 目前为止 Python 中你们做题可能会遇到的问题以及七七八八 2025 年 9 月 24 日 -- 开学后的第一课及军训汇演(大学生活记录) Python 初级 03 -- 程序设计的三种结构之选择结构和循环结构 Python 初级 02 -- 基础的数据类型和输入输出 2025 年 9 月 17 日 -- 大连 2025 国际大体联足球世界杯(大学生活记录) Python 初级 01 -- 初识编程、理解计算机语言及程序运行方式 适合大一新生学习编程的前一课 -- 编程先导(编程的本质) 2025 年 9 月 12 日 -- 三天军训感受以及一些七七八八(大学生活记录) 2025 年 9 月 9 日 -- 体检、军训前的准备(大学生活记录) 适合大一新生的计算机基础知识 -- 个人认为足够版 2025 年 9 月 7 日 -- 既来之、则安之(大学生活记录) C++ 程序的内存布局 —— 代码区、全局/静态区、栈区和堆区 联想小新 pro 16 2025 开箱记录:跳过联网、office 激活、更换 win 11 专业版 R 语言中的数学函数 计算机软件著作权申请过程记录 从聚类到回归:用 Python 解析鸢尾花数据集的完整数据科学流程 条件概率、全概率与贝叶斯公式 —— 一篇文章带你死磕概率公式 高中化学物质反应规则表 —— 方程式之间也有规律可循 集合元素性质、关系、子集公式、基本运算 —— 一篇文章带你全方面死磕集合 如何为你的项目选择合适的许可证 -- 全方位指南 解释 3:1 和 9:3:3:1 的详细来源 —— 建立减数分裂与孟德尔遗传学定律之间的联系 重新设置磁盘分区以及 Btrfs 子卷(subvolume)布局的无损方案 零基础实战:用 Docker 启动 dockermailserver 绕过 25 端口封锁搭建个人邮箱服务器 基于 GitHub Actions + OSS 的自托管 APT 仓库全面指南 如何在安装 Debian 时配置 Btrfs 子卷 | 详细分步指南 一个合格的个人网站站长应该知道哪些事? CSS 基础入门教程 —— 选择器、样式声明 HTML 基础入门 —— 基本结构和语法 给博客添加一个文章数据统计的页面 Anki 牌组选项详细解释与设置 手动编译带有 KernelSU 的 OnePlus 6 内核 安卓类原生系统补全计划 —— PixelExperience(一加 OnePlus) 如何使用 use-sound 为 React 应用添加声音效果 标准化项目的 GitHub Flow 工作流 如何搭建设计自己的博客网站? 使用安知鱼主题同款的 Twikoo 评论组件 配置 GitHub Actions 实现自动化提交百度收录 第00期 | 环境搭建 & 递归 (一) | 基本数列递归 逐字符讲解 C 语言 HelloWorld 程序 2023 年回顾 🤟 Anki:记忆神器,助你高效学习 Gentoo 学习笔记 美化你的 PixelExperience OS Markdown 语法指南 搭建 OneDrive 目录索引 为什么用 65 表示大写字母 A
Git 学习笔记(命令备忘表)
qlAD · 2025-03-30 · via qlAD 的技术笔记

cover

版本控制系统(VCS)

版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统

  1. 本地版本控制系统(Local VCS)

本地版本控制系统

  • 通过在本地计算机上创建一个数据库来保存文件的所有版本
  • 需要手动备份和恢复
  1. 集中式版本控制系统(Centralized VCS)

集中式版本控制系统

  • 通过在服务器上创建一个数据库来保存文件的所有版本
  • 需要手动备份和恢复
  • 需要网络连接才能访问版本库
  • 需要服务器维护和管理
  1. 分布式版本控制系统(Distributed VCS)

分布式版本控制系统

  • 每个开发者的计算机上都有一个完整的版本库
  • 可以在本地进行版本控制

Git 是一个分布式版本控制系统,最初由 Linus Torvalds 开发,用于管理 Linux 内核的开发Git 的设计目标是速度快、数据完整性高和支持分布式非线性工作流程

Git 更像是把数据看作是对小型文件系统的一系列快照,而不是像其他版本控制系统那样记录文件的差异,这使得 Git 在处理大文件时更加高效

在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引

你执行的 Git 操作,几乎只往 Git 数据库中 添加 数据 你很难使用 Git 从数据库中删除数据,也就是说 Git 几乎不会执行任何可能导致文件不可恢复的操作 因此可以尽情做各种尝试,而没有把事情弄糟的危险

主要特点:

  • 几乎所有操作都是本地执行
  • 保证完整性(SHA-1 哈希算法)
  • 操作可追溯且可恢复
  • 文件的三种状态:已修改、已暂存、已提交

初始化设置(git config)

在使用 Git 之前,需要先进行一些基本的设置:

# 配置用户信息
git config --global user.name "Your Name"
git config --global user.email "email@example.com"

# 查看配置
git config --list

# 获取帮助
git help <命令>
git <命令> --help

可选参数 --global 表示全局配置,省略参数表示只对当前仓库生效

配置姓名和邮箱是为了方便识别是谁的提交而备注的信息,不起到登录注册的作用

配置文件位置:

  • /etc/gitconfig:系统配置
  • ~/.gitconfig:用户配置
  • .git/config:仓库配置

优先级:仓库配置 > 用户配置 > 系统配置

获取 Git 仓库(Repository)

获取 Git 仓库有两种方式:

  1. 克隆一个现有的 Git 仓库

可在 <url> 后跟上新的文件名,表示重命名

  1. 在本地创建一个新的 Git 仓库

该命令将创建一个名为 .git 的隐藏目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干

核心概念

工作区域

Git 的工作区域分为三个部分:

  1. 工作目录(Working Directory)

    • 项目的实际文件所在的目录

    • 可以直接修改的区域

  2. 暂存区(Staging Area)

    • 位于 .git 目录中的 index 文件
    • 临时保存你的改动
  3. Git 仓库(Repository)

    • .git 目录中的数据库
    • 保存项目元数据和对象数据库

暂存区也叫缓冲区,存在意义是实现更灵活的提交

文件状态

你工作目录下的每一个文件都不外乎这两种状态:已跟踪 或 未跟踪

已跟踪的文件又可以分为三种状态:已修改、已暂存、已提交

未跟踪 ───────► 已暂存 ───────► 已提交
(Untracked)    (Staged)       (Committed)
     ▲             ▲
     │             │
     └──── 已修改 ──┘
       (Modified)
  • 未跟踪(Untracked):新创建但还没被 git 管理的文件
  • 已修改(Modified):修改了但是没有保存到暂存区的文件
  • 已暂存(Staged):修改后已经保存到暂存区的问件
  • 已提交(Committed):把暂存区的文件提交到本地仓库后的状态

可以通过 status 命令查看文件的状态

status 可跟上 -s--short 参数,你将得到一种格式更为紧凑的输出

基本的 Git 流程如下:

  1. 在工作区中修改文件
  2. 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区
  3. 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录

常用操作

跟踪 / 暂存文件(add)

运行之后可通过 git status 查看状态

git add

git add 命令可以跟上文件名、目录名、通配符等参数

git add . #添加当前目录下的所有文件
git add <file> #添加单个文件
git add *.png #添加当前目录下所有 png 文件
git add -u #添加已跟踪的文件
git add -A #添加所有文件,包括未跟踪的文件

一些特殊文件(.gitignore)

如果你不希望某些文件被 Git 跟踪,可以在项目根目录下创建一个名为 .gitignore 的文件,并在其中列出要忽略的文件或目录

常见的特殊文件还有:

文件名作用
.gitgit 仓库的元数据和对象数据库
.gitignore忽略文件,里面的列举的文件不需要提交到仓库中
.gitattributes指向当前分支的指针
.gitkeep使空目录被提交到仓库
.gitmodules记录子模块的信息
.gitconfig记录仓库的配置信息

Github 官方给的常见参考模板 https://github.com/github/gitignore

查看提交差异(diff)

git diff #不加参数默认比较工作区和暂存区内容

比较差异更常用的是图形化界面:

或者 VScode 等 GUI 软件

git difftool

提交更新(commit)

每次准备提交前,先用 git status 看下,你所需要的修改的文件是不是都已暂存起来了, 然后再运行提交命令

修改不仅仅表示文件中内容的改动,而是包括增加、删除、改动等一系列操作

如果不加 -m 参数,Git 会打开一个文本编辑器让你输入提交信息

可选参数 -a 会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤

删除文件(rm)

本地删除、暂存、提交一条龙

rm xxx
git add .
git commit

或者

git rm #将 xxx 从工作区和暂存区同时删除
git commit

--cached 参数可以仅删除暂存区

重命名文件(mv)

要在 Git 中对文件改名,可以这么做:

其实,运行 git mv 就相当于运行了下面三条命令:

mv README.md README
git rm README.md
git add README

但是一般也是在 vscode 中直接对文件重命名就行

查看历史(log)

Git 记录了每次提交的历史信息,无论是添加、修改还是删除或者是提交的时间、作者、提交信息等都可以通过 git log 命令查看

git log

git log                     # 查看提交历史
git log --oneline          # 单行显示历史
git reflog                 # 查看引用日志

版本回退 / 撤销(reset/amend)

有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了 此时,可以运行带有 --amend 选项的提交命令来重新提交:

git commit --amend -m "新的提交信息" #修改上次提交信息

如果想重置为之前的某个提交,并且删除所有之后的提交 可以运行 reset

git reset <commit-id> #重置到某个提交
参数作用解释使用场景
--hard参数表示重置工作区和暂存区,并且清空两者改动完全放弃这次的改动
--soft参数表示重置暂存区,但不清空改动需要合并多个提交为一个版本
--mixed参数表示重置工作区(默认),且清除暂存区的改动和 --soft 异曲同工

如果不小心使用了 --hard 可以用 git refloggit reset --hard 来重置到之前的一次操作

除了 <commit-id> 还可以使用 HEAD 来表示当前版本

git reset --soft HEAD^ #软重置到上一个版本

HEAD(指针)表示指向的当前版本,HEAD^ 表示上一个,HEAD~4 表示上上上上一个版本

远程仓库(remote repo)

git remote add <remote-name> <remote-url> #添加远程仓库

远程仓库可以不止有一个,可以是多个人或者多台 git 服务器的仓库地址

git remote -v

git remote rm <remote-name> #删除远程仓库
git remote rename <old-name> <new-name> #重命名远程仓库
git remote set-url <remote-name> <new-url> #修改远程仓库地址
git push -u <remote-name> <branch-name> #将本地仓库推送至远程
git fetch <remote> #将远程同步至本地仓库

git fetchgit pull 的区别:

  • git fetch 只是将远程仓库的更新下载到本地,但不会自动合并到当前分支
  • git pull 会自动下载远程仓库的更新,并将其合并到当前分支

打标签(tag)

Git 可以给仓库历史中的某一个提交打上标签,以示重要

可能有的项目标签数量很多,如果只对 1.8.5 系列感兴趣,可以运行

git tag -l "v1.8.5*" #列出所有以 v1.8.5 开头的标签

git tag -l

git tag -a v1.0.0 -m "这是v1.0.0" #给当前提交打上 v1.0.0 的标签
git tag -a v1.0.0 <commit-id> -m "这是v1.0.0" #给具体提交打上 v1.0.0 的标签

默认的 git push 不会将 tag 推送出去,需要使用

git push origin <tagname> #将某个标签共享出去

或者:

git push origin --tags #把所有不在远程仓库服务器上的标签全部传送到那里

如果需要删除标签:

但是上述命令不会删除远程仓库的标签,必须更新一次远程仓库

git push origin --delete <tagname>

切换至某个标签

但是如果你需要在 2.0.0 上进行更改然后提交,标签号不会发生变化。因此,如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新的分支:

git checkout -b version2 v2.0.0

别名(alias)

Git 允许你为常用的命令创建别名,以便更方便地使用

git config --global alias.<alias-name> <command>

例如:

git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status

这样你就可以使用 git co 来代替 git checkout,使用 git br 来代替 git branch,以此类推

分支

上文提到 Git 保存的不是文件的变化或者差异,而是一系列不同时刻的快照。

在提交操作时,Git 会保存一个提交对象,该提交对象会包含一个指向暂存内容快照的指针,还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针

比如我们假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件,然后我们进行首次提交:

git add README test.rb LICENSE
git commit -m 'The initial commit of my project'

现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象 (记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)

git commit

做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针

git commit

Git 的分支,其实本质上仅仅是指向提交对象的可变指针, Git 的默认分支名字是 master。

在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。master 分支会在每次提交时自动向前移动

git commit

分支存在的意义是为了让你可以在不同的分支上进行不同的工作,比如说你正在开发一个新功能,你可以在一个新的分支上进行开发,而不会影响到主分支上的代码

当你完成了新功能的开发,并且测试通过后,你可以将这个分支合并到主分支上,这样主分支就会包含这个新功能的代码

分支管理(branch)

git branch #查看所有本地分支,当前分支前有一个 *

参数 -a 查看所有分支,-r 查看远程分支

git branch

git branch testing #创建一个名叫 testing 的分支

这会在当前所在的提交对象上创建一个新的指针

git branch testing

HEAD 指向的是当前分支的特殊指针,可以将 HEAD 想象为当前分支的别名

git branch 这是创建分支的命令,但并不会自动切换到这个分支上,因此当前分支还是 master,而 HEAD 仍然指向 master 分支

git branch testing

可以使用 switchcheckout 命令来切换分支:

git switch testing #切换当前分支

git switch testing

这样 HEAD 就指向 testing 分支了

此时你进行提交操作时,HEAD 分支(testing)随着提交操作自动向前移动,而 main 分支却没有

git commit testing

那现在我们再切换回 main 分支

git switch main #切换回 main 分支

会发现之前在 testing 分支上所做的修改并没有出现在 main 分支上

这条命令做了两件事 一是使 HEAD 指回 main 分支,二是将工作目录恢复成 main 分支所指向的快照内容

分支作用一般的场景是

  1. 开发某个网站
  2. 为实现某个新的用户需求,创建一个分支
  3. 在这个分支上开展工作

正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补 你将按照如下方式来处理:

  1. 切换到你的线上分支 main(生产分支)
  2. 为这个紧急任务新建一个分支,并在其中修复它
  3. 在测试通过之后,切换回线上分支,然后合并这个修补分支,最后将改动推送到线上分支
  4. 切换回你最初工作的分支上,继续工作

分支整合(merge & rebase)

当在新的分支上完成了某个功能的开发后,就可以将这个分支合并到主分支上,让主分支也拥有这个功能

一般实现这个功能会有两种方式:mergerebase

git merge <branch-name> #将分支合并到当前分支中

git merge

git rebase <branch-name> #从分叉点开始直线型合并

git rebase

  • merge 不会破坏原分支的提交历史,但会产生分支线,并且多出一条提交记录
  • rebase 不会增加额外的提交记录,分支图为线性,但会改变提交历史,不应该在共享的主分支上使用

变基的风险:

如果这次提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。

如果你遵循这条金科玉律,就不会出差错。 否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你

既然你的修改已经合并进来了,就不再需要那个新的分支了。现在你可以在任务追踪系统(issue tracker)中关闭此项任务,并删除这个分支

git branch -d <branch-name> #删除已经合并的分支
git branch -D <branch-name> #强制删除分支

可见分支的好处是可以在不同的分支上进行不同的工作,而不会互相影响,但是当分支过多合并的时候可能会出现冲突(两个分支上都修改了同一行代码)

分支冲突(conflict)

当有人在不同分支同时更改了同一个代码 git 不知道保留哪一个的情况下被叫作冲突,此时需要手动介入处理

当运行

后 git 会等待手动修改冲突文件,修改之后直接暂存和提交后会自动 merge

如果需要中止等待合并可以运行

免费

https://learngitbranching.js.org/

https://www.w3schools.com/git/exercise.asp

付费

https://www.codecademy.com/learn/learn-git

工作流(Flow)

Git 工作流是指在使用 Git 进行版本控制时,团队成员之间如何协作、如何管理代码的流程和规范

常见的工作流有:

  • Git Flow
  • GitHub Flow

以下是 Github Flow 的工作流图(趋于稳定分支的流水线(“silo”)视图):

Github Flow

具体可以看我的这篇文章:标准化项目的 GitHub Flow 工作流标准化项目的 GitHub Flow 工作流