PS:如今已经可以通过 ai agent 用自然语言的方式操作 git,以下内容学习熟知即可


Git 核心体系

基础概念

基础操作

分支管理

远程协作

进阶工具

工作流

对象模型
blob / tree / commit

四大区域
工作区 → 暂存区
→ 本地仓库 → 远程

初始化配置
init / config

git add
暂存修改

git commit
提交快照

status / diff
查看状态与差异

restore / reset
撤销与恢复

branch / switch
创建与切换

merge
快进 / 三方合并

冲突解决
手动处理标记

SSH Key
身份认证

clone / fetch / pull
获取与同步

git push
推送更新

rebase
变基(慎用)

stash
临时保存

cherry-pick / tag
worktree / blame

日常循环
pull → branch → PR

分支策略
Git Flow / 简化版


序:Git的安装与配置

Windows 用户:

  1. 访问 Git - Install for Windows
  2. 下载 64-bit 版本的安装包
  3. 双击安装,安装过程中保持所有默认选项即可(会有很多页配置,不用改,一直点 Next)
  4. 安装完成

macOS 用户:

macOS 通常自带 Git

打开终端输入 git --version,如果有输出就不需要安装

如果没有,执行:

# macOS 安装 Git(通过 Xcode 命令行工具)
$ xcode-select --install

弹出的对话框中点击"安装"即可

验证安装:

$ git --version

预期输出:

git version 2.43.0

首次配置(必须):

安装完成后,需要告诉 Git 你是谁(这些信息会记录在每次代码提交中):

# 设置你的名字(用英文,可以是昵称)
$ git config --global user.name "Your Name"

# 设置你的邮箱
$ git config --global user.email "your.email@example.com"

提示:这里的名字和邮箱不需要是真实的,但建议和将来注册 GitHub 的邮箱保持一致


一. Git 简介

1. 什么是Git

Git 是一个分布式版本控制系统

简单理解,Git 就像一颗后悔药,可以帮你记录文件的每一次修改,随时回退到任意历史版本

注意:Git 并非每次都存储完整文件,它会引用没有变化的文件,储存有变化的文件


2. Git 对象模型

Git 的底层是三种对象(blob、tree、commit),存在 .git/objects/ 目录下:

blob(文件内容)

存储文件的具体内容

每个blob只存储文件数据,不包含文件名

tree(目录结构)

存储目录的信息:

  • 哪些文件名对应哪些 blob
  • 哪些子目录对应哪些 tree

tree 就是一张「文件名 → blob」的映射表

commit(提交)

存储一次提交的全部信息:

  • 指向一个 tree(这次提交的项目快照)
  • 指向父 commit(上一次提交)
  • 作者、时间、提交信息
commit -> tree -> blob
  |
parent commit -> tree -> blob

每个对象用 SHA-1 哈希值作为唯一标识(如 a1b2c3d

这就是为什么 Git 能保证数据完整性——内容变了,哈希就变了


3. Git 的四个区域

3.1 Working Directory(工作区)

实际编辑文件的地方

用编辑器改代码,改的就是工作区的文件

3.2 Staging Area / Index(暂存区)

一个「准备区」

你选择哪些修改要放进下一次提交

git add 就是把文件放进暂存区

3.3 Local Repository(本地仓库)

存储在本地的仓库

提交历史存在这里

git commit 就是把暂存区的内容打包成一个快照,存进本地仓库

3.4 Remote Repository(远程仓库)

服务器上的仓库(如 GitHub)

git push 把本地提交推到远程,git pull 把远程更新拉到本地

git add

git commit

git push

git pull

🖥️ 工作区

📋 暂存区

📦 本地仓库

☁️ 远程仓库

暂存区的存在意义
可以精确控制每次提交包含哪些修改
不用每次都把所有改动一起提交


二. 初始化与配置

1. git init — 初始化仓库

执行git init命令会在当前目录创建一个 .git 隐藏文件夹( Git 仓库的全部内容都在这个文件夹里,之后所有的版本控制操作都在这个目录下进行)

.git 目录

objects/

refs/

HEAD

index

config

blob

tree

commit

分支指针

标签指针

指向当前分支

暂存区

仓库级配置


2. git config — 配置用户信息

设置用户名和邮箱:

git config user.name "your name"
git config user.email "your@email.com"

查看当前配置:

git config user.name
git config user.email

三个配置级别:

参数作用范围配置文件位置
--local(默认)仅当前仓库.git/config
--global当前用户的所有仓库~/.gitconfig
--system所有用户/etc/gitconfig
git config --global user.name "your name"
git config --global user.email "your@email.com"

建议:用 --global 设置名字和邮箱,这样每个新仓库都会自动使用


3. 创建文件

使用 Git 前,先创建一些文件

以下是常用的辅助命令:

注意:也可以在工作区右键鼠标点击,选择「创建文件」,双击文件也可以编辑,可通过红绿颜色区分已暂存和未暂存的修改

touch — 创建空文件

touch readme.md

echo + > — 写入内容

echo "hello world" > readme.md

>覆盖文件原有内容,如果文件不存在,会自动创建

echo + >> — 追加内容

echo "第二行" >> readme.md

>> 会在文件末尾追加,不影响已有内容

cat — 查看文件内容

cat readme.md

把文件内容打印到终端

注意:这些不是 git 命令,但它可以帮我们准备 git 要管理的文件


三. 基础指令

1. git add — 暂存修改

git add 把文件从工作区移到暂存区

用法:

  • git add file.txt — 暂存单个文件
  • git add . — 暂存所有修改
  • git add *.js — 暂存所有 .js 文件

暂存区(Index):
Git 特有的概念
是一个「预提交区」——可以选择性地把某些修改放进去,而不是把所有改动一次性提交

注意:
git add 不会创建提交,只是把文件放进「准备区」
可以多次 add 后一次性 commit


2. git status — 查看状态

git status 显示工作区和暂存区的当前状态

具体状态:

  • 哪些文件已暂存(准备提交)
  • 哪些文件已修改但未暂存
  • 哪些文件未跟踪(新文件,Git 还不知道它的存在)

3. git diff — 查看差异

git diff 显示文件的具体修改内容(逐行比较两个版本,告诉你改了什么

常用用法:

  • git diff --staged — 比较暂存区 vs 上一次 commit,看 add 了什么
  • git diff — 比较工作区 vs 暂存区,看改了但还没 add 的内容

输出格式:

- hello world     (旧行,被删除)
+ Hello Git       (新行,被添加)

4. git commit — 提交更改

git commit -m "提交信息" 把暂存区的内容打包成一个 commit,存入本地仓库

一次 commit 就是一份项目快照——记录了这一刻所有文件的状态

提交信息 应该简洁描述做了什么:

git commit -m "Add readme file"

每次 commit 都会记录:
改了什么文件、改了什么内容、上一次 commit 是谁
这样就形成了一条完整的历史链


4. git log — 查看提交历史

git log 显示从最新到最早的提交记录

输出格式:

commit a1b2c3d (HEAD -> main)
Author: Your Name <your@email.com>
Date:   Mon Jun 2 10:00:00 2025

    Add readme

HEAD -> main 表示 HEAD 当前指向 main 分支的最新 commit

HEAD 记录的是「当前在哪个 commit 上」——切换分支时,HEAD 会跟着移动

常用选项:

  • git log -n 3 — 只看最近 3 条
  • git log --oneline — 简洁模式(一行一条)

5. git restore — 恢复文件

git restore 用于恢复文件内容

数据通常在三个地方流动:工作区暂存区提交历史(HEAD)

场景 1:丢弃工作区的修改(最常用)

git restore readme.md

把工作区的文件恢复成暂存区里的样子
如果没暂存过,就恢复成最后一次提交的样子

场景 2:取消暂存(撤销 git add)

git restore --staged readme.md

把文件从暂存区撤出来,但不会改变工作区刚写的代码

场景 3:同时丢弃暂存区和工作区的修改

git restore --staged --worktree readme.md

彻底放弃这个文件的所有修改,让它直接回到最后一次提交的状态

场景 4:从历史提交中恢复文件

git restore --source=HEAD~1 readme.md

把上一次提交里的文件,直接拉到现在的工作区里

注:
HEAD 代表当前最新提交,HEAD~1 代表上一次提交,HEAD~2 是上两次,依此类推


6. git checkout Hash

切换到指定的commit

要注意使用该指令时处于分离HEAD状态,最好不要在此基础上修改文件
该指令常用于临时查看历史commit的内容


四. 分支操作

1. git branch — 分支操作

分支是 Git 最强大的功能之一

分支就是一个指向某个 commit 的标记
创建分支只是加个标记,瞬间完成

用法:

  • git branch — 列出所有分支
  • git branch dev — 创建名为 dev 的新分支
  • git branch -d dev — 删除分支

创建分支时,新分支指向当前 commit
两个分支共享之前的历史,之后各自独立发展

main:    A -- B -- C
                    \
dev:                 D -- E

2. git checkout — 切换分支

git checkout 切换到指定分支

切换分支时,Git 会:

  1. 让 HEAD 指向新分支

  2. 把工作区的文件更新为该分支最新 commit 的内容

创建并切换(一步到位):

git checkout -b dev — 创建 dev 分支并立即切换过去

切换后,工作区会变成 dev 分支的内容
两个分支可以各自独立开发,互不影响

git checkout -b dev Hash — 从指定的commit处创建 dev 分支并立即切换过去

切换后,工作区会变成 dev 分支的内容
两个分支可以各自独立开发,互不影响,且是从指定的commit开始延伸

[!Git 史话:checkout、switch 与 restore]

在早期,git checkout 承担了太多责任,核心逻辑是“把某个东西拿出来放到工作区”

这导致了极大的概念混乱:

  1. 操作分支git checkout dev(切换分支)

  2. 操作文件git checkout -- readme.md(丢弃修改,恢复文件)

分家(Git 2.23 引入)

为了让命令见名知意,Git 社区将 checkout 的功能一分为二,推出了两个专职的新命令:

  • git switch:专职负责切换分支
  • git restore:专职负责恢复文件(还顺便接管了以前用 reset HEAD 来取消暂存的工作)

虽然 checkout 依然可用,但现代 Git 教程强烈建议你拥抱 switchrestore


3. git switch — 切换分支

git switch 是 Git 2.23 引入的新命令,用来替代 git checkout 的分支切换功能

原因:git checkout 职责太多(切换分支、恢复文件、创建分支…),容易混淆

用法:

  • git switch main — 切换到 main 分支
  • git switch -c feature — 创建并切换到 feature 分支

git checkout 的对应关系:

  • git checkout devgit switch dev
  • git checkout -b devgit switch -c dev

4. git merge — 合并分支

git merge 把指定分支的修改合并到当前分支

用法:先切到目标分支(通常是 main),再 merge 其他分支:

git switch main
git merge dev

两种合并方式: 快速合并与三方合并

快进合并(Fast-forward)

前提:main 没有新 commit,dev 在 main 前面

Git 只需把 main 移到 dev 的位置:

之前:  main ── A
               \
        dev      B ── C

之后:  main ── A ── B ── C

三方合并(3-way merge)

前提:main 和 dev 都有新 commit

Git 找到分叉点,合并两边的修改,生成一个新的合并 commit:

        main ── A ── B ── M
                      /
        dev     C ── D

M 是合并 commit,它有两个父 commit(B 和 D)。

合并冲突

当两个分支修改了同一个文件的同一位置,Git 无法自动合并,就会产生冲突

冲突标记:

<<<<<<< HEAD
当前分支的内容
=======
要合并的分支的内容
>>>>>>> dev

解决步骤:

  1. 打开冲突文件,找到 <<<<<<< 标记

  2. 决定保留哪部分(或合并两者)

  3. 删除冲突标记

  4. git add 标记为已解决

  5. git commit 完成合并

冲突是正常现象
Git :“这两个修改我没法自动合并,你来决定”


五. 远程协作

1. SSH Key — 认证远程仓库

要和 GitHub 等远程仓库通信,需要证明你的信息,而SSH Key 是最常用的方式

原理:

  • 生成一对密钥:私钥(留在本地)和公钥(上传到 GitHub)
  • GitHub 用公钥验证你的身份,你用私钥签名

步骤 1:生成密钥

ssh-keygen -t rsa -C "your@email.com"

一路回车即可
默认生成在 ~/.ssh/id_rsa

步骤 2:复制公钥

cat ~/.ssh/id_rsa.pub

复制输出的整行内容

步骤 3:添加到 GitHub

GitHub → Settings → SSH and GPG keys → New SSH key → 粘贴公钥

步骤 4:测试连接

ssh -T git@github.com

看到 Hi username! 就说明配置成功了

配置好 SSH 后,clone/push/pull 都可以用 git@github.com:用户名/仓库.git 格式的 URL,无需每次输入密码


2. 远程仓库与 git push

远程仓库是托管在服务器上的 Git 仓库(如 GitHub)

本地仓库通过 push/pull 和远程仓库同步

添加远程仓库:

git remote add origin git@github.com:user/repo.git

origin 是远程仓库的默认名字,也可以自己取名字

查看已配置的远程仓库:

git remote -v

推送到远程:

git push origin main

把本地 main 分支的 commit 发送到远程

之后在 GitHub 上就能看到代码了


3. 克隆项目

场景:从远程克隆一个项目

3.1 git clone — 克隆仓库

git clone 从远程仓库复制一份完整的项目到本地:

git clone git@github.com:user/repo.git

它会:

  1. 下载远程仓库的全部内容

  2. 创建本地仓库和工作区

  3. 检出默认分支(通常是 main)

  4. 自动设置远程地址为 origin

克隆完成后,拥有完整的项目历史,和远程仓库一模一样

这就是「分布式」的含义——每个人的本地都是一个完整的仓库

两种 URL 格式:

  • HTTPS:https://github.com/user/repo.git
  • SSH:git@github.com:user/repo.git(需要配置 SSH Key)

3.2 git fetch — 获取远程更新

使用 fetch 前,需要先配置远程仓库地址:

git remote add origin git@github.com:user/repo.git
git fetch origin

fetch 从远程下载新的 commit,但不会合并到你的工作区
它只更新本地的远程记录(如 origin/main),让你知道远程有什么新内容,但不改动你的文件

fetch 前:  本地 main → C,  远程 main → E
fetch 后:  本地 main → C,  origin/main → E
            (你还是在 C,但知道远程有 E 了)

git pull = git fetch + git merge
想精确控制时,可以先 fetch 再决定是否 merge

3.3 git pull — 拉取并合并

使用 pull 前,需要先配置远程仓库地址(如果还没配置过):

git remote add origin git@github.com:user/repo.git
git pull origin main

origin 是远程仓库名,main 是分支名

默认情况下,git pull = git fetch + git merge

pull 先从远程下载 commit,然后在 local repo 里合并分支,最后更新工作区的文件

日常开发中,开始工作前先 git pull 是个好习惯

本地:  A -- B -- C
远程:  A -- B -- D -- E

pull 后: A -- B -- C -- M (merge commit)
                  \      /
                   D -- E

[!扩展:GitHub Pull Request (PR) 的合并方式]
把代码 push 到远程并提起 PR 后,在 GitHub 页面上通常有三种合并方式:

  1. Create a merge commit
    保留所有 commit 历史,并生成一个新的 Merge commit(类似上面的 M)
    适合保留完整开发过程

  2. Squash and merge
    把你的多个 commit 压缩成一个全新的 commit 加入主分支
    主分支历史最干净,适合小功能

  3. Rebase and merge
    把你的 commit 逐个复制并重新排列在主分支最前面,没有 merge commit,历史是一条直线

到这里,已经掌握了 Git 的核心工作流:

add → commit → push & pull

这四个命令覆盖了日常开发 90% 的场景
后面的章节是进阶内容


六. 撤销与修正

1. git reset — 重置

git reset 通过移动 HEAD 指针来撤销 commit

有三种模式,区别在于如何处理暂存区和工作区:

重置模式HEAD暂存区 (Index)工作区 (Working Directory)适用场景
--soft(软重置)移回旧 commit保留变更(放入暂存区)不变commit 拆分/合并、修正提交信息
--mixed(默认)移回旧 commit重置为旧 commit 状态不变撤销 commit 及 git add,重新整理修改
--hard(硬重置)移回旧 commit强制重置强制重置(未提交修改永久丢失)彻底丢弃当前所有改动,回到干净的旧状态

注意--hard 是危险操作,执行前请确认工作区和暂存区中没有需要保留的未提交内容

git reset --soft HEAD~1   # 仅撤销 commit
git reset --mixed HEAD~1  # 撤销 commit 和 add (默认)
git reset --hard HEAD~1   # 彻底回退,抛弃所有修改

误用 --hard 怎么办?

只要没有执行过 git gc,Git 的 reflog 记录了 HEAD 的所有移动历史

1git reflog          # 找到误操作前的 commit hash
2git reset --hard <hash>  # 恢复到那个状态

记住:Git 几乎不会真正丢失数据,reflog 是你的终极后悔药


2. git revert — 撤销提交

git revert 创建一个新的 commit,内容是「撤销指定 commit 的修改」

reset 的区别:

  • reset删除历史(改写已有的 commit)
  • revert新增历史(创建一个反向 commit)
原来:       A -- B -- C
revert B:   A -- B -- C -- B'
                       (B' 把 B 的改动反向做了一遍)

黄金法则
commit 已经 push 到远程并被其他人使用了,用 revert,不用 reset
reset 改写历史会导致其他人的代码出问题


七. 进阶工具

1. git rebase — 变基

git rebase main 把当前分支的 commit 逐个「移植」到 main 的最新 commit 之后

rebase vs merge:

假设在 dev 分支上有两个 commit(D、E),main 上也有新 commit(B、C):

用 merge 合并:

main:  A ── B ── C ── M   (M 是合并 commit,有两个父 commit)
              \      /
dev:           D ── E

历史保留了分叉结构,但多了一个 M

用 rebase 合并:

main:  A ── B ── C
                 \
dev:              D' ── E'   (D' 和 E' 是 D、E 的副本,哈希不同)

历史变成一条直线,没有合并 commit

rebase 的本质:把 commit 摘下来,接到目标分支的最新位置,像「嫁接」一样

黄金法则
不要 rebase 已经 push 到远程的 commit!
rebase 会改写 commit 的哈希值,导致其他人的代码出问题
只在 push 之前 rebase 本地 commit


2. git stash — 临时保存

git stash 把当前工作区和暂存区的修改「藏起来」,让工作区恢复干净

场景: feature 分支开发到一半,突然需要切到 main 修复 bug,但修改还没法 commit,这时候 stash 就派上用场了

用法:

  • git stash — 保存当前修改
  • git stash list — 查看所有 stash
  • git stash pop — 恢复最近一次 stash 并删除记录
  • git stash apply — 恢复但保留记录
git stash          # 藏起来
git switch main    # 切到 main 修 bug
git switch feature # 切回来
git stash pop      # 恢复之前的工作

3. git worktree — 多开工作区

正常情况下,一个 Git 仓库只能同时检出一个分支的代码在工作区里

git worktree 允许你为同一个本地仓库创建多个并行的工作目录

痛点场景:

feature 分支写了大量代码,本地环境正跑着
突然老板让你立刻切到 main 修紧急 Bug

  • 直接切?有大量未提交修改,Git 会阻止
  • 用 stash 藏起来切?切分支会导致项目依赖或编译产物被冲刷,切来切去很痛苦

Worktree 的完美解法:

保持当前目录一动不动,直接在旁边开辟一个新目录修 Bug!它们底层共享同一个 Git 数据库

# 在当前仓库外创建一个名为 hotfix 的新目录,并检出 main 分支
git worktree add ../hotfix main

# 修完 Bug 提交后,清理掉这个临时目录
git worktree remove ../hotfix

极速、省空间,而且彻底隔离了开发环境,保护了开发时的心流


4. git cherry-pick — 拣选提交

git cherry-pick 把某个 commit 的改动内容(diff) 提取出来,在当前分支重新应用一遍

场景:在 dev 分支修了一个 bug(commit D),但不想合并整个 dev,只想把这个修复拿到 main 上

dev:   A ── B ── C ── D    (D 改了 login.py 的第 10 行)
main:  A ── B

git switch main
git cherry-pick D
main:  A ── B ── D'         (D' 也改了 login.py 的第 10 行)

cherry-pick 不是复制文件快照,而是提取「改了什么」,在当前位置重新改一遍
所以 D’ 和 D 的哈希不同,但改动内容相同

注意:
这是「复制改动」不是「移动」
dev 上的 D 仍然存在


5. git tag — 标签

标签用于标记发布版本(v1.0, v2.0, …),方便以后快速找到这个版本

标签和分支类似,都是指向 commit 的标记。区别是:

  • 分支会随着新 commit 往前移动
  • 标签永远固定在创建时的 commit 上
git tag v1.0              # 给当前 commit 打标签
git tag                   # 列出所有标签
git show v1.0             # 查看标签对应的 commit
git tag -d v1.0           # 删除标签

轻量标签(上面用的)只是一个标记
还有一种附注标签git tag -a v1.0 -m "message"),包含作者信息和说明,适合正式发布


6. git rm — 删除文件

git rm 从工作区和暂存区同时删除文件,并记录这次删除
之后 commit 即可

git rm readme.md       # 删除文件 + 暂存删除操作
git commit -m "Remove readme"

和手动删除的区别:

  • 手动删除文件后,需要 git add 告诉 Git 删了什么
  • git rm 一步到位:删文件 + 暂存删除操作

如果只想从 Git 跟踪中移除(保留本地文件):

git rm --cached <file>

适用场景:不小心把 .env 之类的文件 add 进去了,想从跟踪中移除


7. git blame — 追溯修改

git blame 逐行显示文件的最后修改者和 commit

输出格式:

a1b2c3d (Alice 2025-01-15) def login():
b2c3d4e (Bob   2025-02-01)     check_token()

每行前面显示:commit 哈希、作者、日期、内容

用途:排查某行代码是谁改的、为什么改。配合 git loggit show 可以追溯完整上下文

git blame login.py         # 查看整个文件
git blame -L 10,20 login.py  # 只看第 10-20 行

八. 工作流

1. 日常开发流程

一个典型的 Git 工作日:

# 1. 拉取最新代码
git pull origin main

# 2. 创建功能分支
git switch -c feature/login

# 3. 开发、提交
git add .
git commit -m "Add login form"

# 4. 推送到远程
git push origin feature/login

# 5. 创建 Pull Request(在 GitHub 上)

# 6. 代码审查后合并到 main

# 7. 切回 main,拉取最新
git switch main
git pull origin main

# 8. 删除功能分支
git branch -d feature/login

核心循环就是:修改 → add → commit → push → PR → merge


2. Git Flow 工作流

Git Flow 是一种流行的分支管理策略:

  • main — 永远是生产环境的代码
  • develop — 开发主线
  • feature/* — 功能分支,从 develop 分出
  • release/* — 发布准备分支
  • hotfix/* — 紧急修复分支
main:     A --------- M --------- R
           \         ^           ^
dev:        D -- F -- D -- F --- D
               ^    ^
feature:      f1   f2

小团队可能不需要这么复杂
简单的策略:

  • main 保持可部署
  • 每个功能一个分支
  • 通过 PR 合并

选择适合你团队的工作流,不要为了流程而流程


结语:

学 Git 并不难 ,但它却是每一位开发者不可或缺的核心基石

尤其在 AI 时代,当自然语言操作逐渐普及,理解 Git 的底层原理与工作流反而愈发关键——它不仅是代码的“后悔药”,更是人机协作、版本追溯与团队协同的信任基础

工具会迭代,但对版本控制的深刻认知,永远是高效开发的底气

愿这份笔记成为你随时可查阅的地图,在每一次 commit 与 merge 中,走得更稳、更远

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐