一、git概述

Git 是一种 分布式版本控制系统,最初由 Linus Torvalds 开发,用于管理 Linux 内核代码。如今,它被广泛用于各种软件开发项目,以帮助开发者跟踪代码的变更、协作开发,并管理不同版本的代码。

二、git 的特点

  • 分布式:每个开发者的本地仓库都包含整个项目的完整历史,不依赖于中央服务器。
  • 高效:采用快照存储(Snapshot)方式,存储文件的差异,而不是完整的文件副本。
  • 分支管理:支持轻量级的分支(Branch),便于团队并行开发和代码合并。
  • 数据安全:采用 SHA-1 哈希算法,确保代码的完整性和安全性。
  • 适应性强:适用于各种规模的项目,尤其适合开源和团队协作开发。

三、git 基本概念

概念 说明
仓库(Repository) 存储项目文件和历史 版本的地方,可以是本地仓库,也可以是远程仓库(如 GitHub、Gitee)。
提交(Commit) 记录项目的一个历史版本,每次提交都会生成一个唯一的哈希值。
分支(Branch) 用于并行开发的独立代码线,默认主分支为 mainmaster
合并(Merge) 将不同分支的代码合并到一起。
暂存区(Staging Area) 用于存放即将提交的文件,是 Git 的缓冲区域。
远程仓库(Remote Repository) 托管在远程服务器上的仓库,如 GitHub、GitLab、Gitee。
克隆(Clone) 复制远程仓库到本地。
拉取(Pull) 从远程仓库获取最新代码并合并到本地分支。
推送(Push) 将本地的提交更新到远程仓库。

四、git的三种使用

Git 主要有 三种使用方式命令行(CLI)、图形化界面(GUI)和 IDE 插件。不同方式适用于不同用户需求,下面分别介绍它们的特点和使用方法。


1. 命令行(Command Line Interface,CLI)

适用于: 熟悉 Git 的开发者、高级用户、服务器环境。
特点:

  • 功能最全,所有 Git 操作都可以执行。
  • 高效,适合习惯使用终端的开发者。
  • 跨平台,Windows(Git Bash)、Linux 和 macOS 终端都可以使用。

推荐工具:Git Bash(Windows)、Linux/macOS 终端、PowerShell(Windows)

2. 图形化界面(GUI)

适用于: 初学者、习惯可视化操作的用户。
特点:

  • 更直观,通过界面查看代码变更、分支管理等。
  • 适合初学者,避免记忆大量命令。
  • 易于管理分支和冲突,可视化展示合并状态。

常见的 Git GUI 客户端

工具 适用平台 特点
GitHub Desktop Windows/macOS 官方出品,适用于 GitHub 用户
Sourcetree Windows/macOS 适合团队开发,支持 Git 和 Mercurial
GitKraken Windows/macOS/Linux 界面友好,支持团队协作
TortoiseGit Windows 集成到资源管理器,适合 Windows 用户

示例: 在 GitHub Desktop 中:

  1. Clone Repository:克隆远程仓库到本地。
  2. Commit & Push:修改代码后,提交并推送到远程仓库。
  3. Manage Branches:创建、切换、合并分支。

3. IDE 插件

适用于: 开发者,习惯在 IDE 中完成所有工作的人。
特点:

  • 集成度高,不需要单独打开终端或 GUI 工具。
  • 适合日常开发,可以在编码时直接使用 Git。
  • 自动完成 & 代码管理,减少手动输入命令。

常见的 IDE Git 插件

IDE Git 插件
VS Code 内置 Git 支持(Source Control),可安装 GitLens 增强
IntelliJ IDEA / PyCharm / WebStorm 自带 Git 插件,支持可视化操作
Eclipse EGit(插件)
Visual Studio 内置 Git 支持,适用于 C# 开发者

示例:在 VS Code 中使用 Git

  1. 打开 Source Control(Ctrl + Shift + G)
  2. 点击 “+” 添加修改的文件
  3. 输入 Commit Message,点击 “✔” 提交
  4. 点击 “Push” 推送代码

五、git的初始化

Git 初始化是指在一个目录中创建 Git 仓库,以便对文件进行版本控制。Git 提供了 git init 命令来完成初始化操作。

1. 初始化 Git 仓库

在项目目录下运行以下命令:

1
git init

作用:在当前目录创建一个 .git 文件夹,表示该目录已成为 Git 仓库。

2. 配置 Git 用户信息(全局/本地)

在提交代码前,需要配置 Git 用户信息:

1
2
git config --global user.name "你的名字"
git config --global user.email "你的邮箱"

通过git config命令进行配置用户名和邮箱,这样在提交的时候才能够识别出是谁提交的内容。

参数:

  1. 省略(local):本地配置,只对本地仓库有效
  2. --global:全局配置,所有仓库生效
  3. --system:系统配置,对所有用户生效

“你的名字”:这部分如果用户名中间存在空格,则需要用双引号(英文)括起来;如果没有则可以省略双引号。

git config --global user.namegit config --global user.email 只需要在同一台电脑上 执行一次,以后就不需要重复执行,除非你想更改用户名或邮箱。

🔹 --global 配置:只需执行一次,在同一台电脑的所有 Git 仓库都生效。
🔹 --local 配置:只影响当前 Git 仓库,需要单独配置。
🔹 换电脑或要修改用户名/邮箱时,需要重新执行命令。

3. 注意事项!

1. 用户名 (user.name)

  • 可以是 任意字符串,不一定要和 GitHub、Gitee 账户名一致。
  • 这个名字不会影响 Git 账户的登录,只是用于提交记录的显示。

2. 邮箱 (user.email)

  • 建议填写和 GitHub/Gitee 绑定的邮箱,否则可能影响远程仓库的提交关联。
  • 在 Git 提交记录中,邮箱用于识别提交者,并在 GitHub/Gitee 上显示贡献(Contributions)。

3. 是否可以随意填写?

本地使用:

  • 可以随意填写,因为 Git 只会在提交记录中保存这些信息,并不会验证邮箱的有效性。

🚨 推送到 GitHub/Gitee 时:

  • 推荐使用 GitHub/Gitee 绑定的邮箱,否则提交可能不会显示在 GitHub 个人主页的 Contributions 统计中。
  1. 保存用户名和密码(这样就不用每次都输入了)
1
git config --global credential.helper store

查看git的配置信息

1
git config --global --list

4. 实操

1
2
3
4
5
6
7
8
9
git config --global user.name Ryan-Joee
git config --global user.email 3497882088@qq.com
git config --global credential.helper store

34978@Ryan MINGW64 ~
$ git config --global --list
user.name=Ryan-Joee
user.email=3497882088@qq.com
credential.helper=store

六、新建版本库

版本库又叫仓库(Repository,简称Repo),我们可以将仓库理解为一个目录,这个目录里所有的文件都可以被git管理起来,每个文件的修改、删除、添加等操作,git都能够跟踪到,以便任何时候都可以跟踪历史或者还原到之前的某一个版本。

1.创建仓库的两种方式

方式一:在本地新建 Git 仓库,适用于 从零开始 创建一个新的 Git 项目。

1
git init 目录名(可选)

执行 git init 后,Git 会在该目录下创建一个 .git 目录,用于存储版本控制信息。

方式二:从远程仓库克隆已有的 Git 仓库

1
git clone <远程仓库地址>

远程仓库:GitHub、Gitee、GitLab等

2. 实操

在本地创建一个仓库

  1. 找到合适的位置(文件夹)创建一个新的git仓库(之后的所有操作都是在该文件夹中执行)。
  • Windows系统操作:打开文件管理器,进入到所想要创建为仓库的文件夹中,点击鼠标右键,点击”显示更多选项”,点击”Open Git Bash here”,随后就可以在打开的终端中进行操作了(例如我进入d盘下的Repository文件夹中进行操作)。
1
2
3
4
5
6
34978@Ryan MINGW64 /d/Repository
$ git init
Initialized empty Git repository in D:/Repository/.git/

34978@Ryan MINGW64 /d/Repository (main)
$

随后可以在文件管理器中的该文件夹下查看到有一个新的隐藏文件夹.git(如果没有,需要打开显示隐藏文件选项)。或者直接在刚才打开的终端中输入ls -al命令即可显示该隐藏文件。

在命令提示符$前有main或者master则表示已经在仓库。

如果删除掉该隐藏的文件夹,则相当于删除该仓库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git init my-repo(目录名)
34978@Ryan MINGW64 /d/Repository
$ git init my-repo
Initialized empty Git repository in D:/Repository/my-repo/.git/

34978@Ryan MINGW64 /d/Repository
$ ls -al
total 12
drwxr-xr-x 1 34978 197609 0 2月 1 15:07 ./
drwxr-xr-x 1 34978 197609 0 2月 1 14:49 ../
drwxr-xr-x 1 34978 197609 0 2月 1 15:07 my-repo/

34978@Ryan MINGW64 /d/Repository
$

执行这条命令相当于在刚才打开的文件夹下再创建一个叫my-repo的文件夹,并将该文件夹初始化为一个仓库。所以my-repo才是实际的仓库,而不是我们上次进入的文件夹Repository。

从远程仓库克隆一个仓库到本地

1
2
3
4
5
6
7
8
9
10
11
12
34978@Ryan MINGW64 /d/Repository
$ git clone https://github.com/git/git.git
34978@Ryan MINGW64 /d/Repository
$ ls -al
total 204
drwxr-xr-x 1 34978 197609 0 2月 1 15:48 ./
drwxr-xr-x 1 34978 197609 0 2月 1 14:49 ../
drwxr-xr-x 1 34978 197609 0 2月 1 15:49 git/
drwxr-xr-x 1 34978 197609 0 2月 1 15:07 my-repo/

34978@Ryan MINGW64 /d/Repository
$

七、Git的工作区域和文件状态

1. Git 的三个工作区域

Git 版本控制涉及 三个不同的区域

  1. 工作区(Working Directory)
    • 你的本地目录/工作目录,存放所有文件。我们能在文件资源管理器中看到的目录就是工作目录,工作区就是我们实际操作的目录。
    • 修改文件后,文件仍然在工作区。
  2. 暂存区(Stage/Index)
    • 是一种临时存储区域,用于保存即将提交到Git仓库的修改内容。通过 git add 命令把修改的文件添加到 暂存区
    • Git 记录哪些文件将进入下次提交。
  3. 本地仓库(Local Repository)
    • 实际上就是通过git init命令来创建的仓库。它包含了完整的项目历史和元数据,是Git存储代码和版本信息的主要位置。通过 git commit 提交文件后,文件被存入 本地仓库.git 目录)。
    • 本地仓库存储所有历史版本,并形成版本快照。
  4. (可选)远程仓库(Remote Repository)
    • 通过 git push,可以将本地提交的内容推送到 远程仓库(如 GitHub、Gitee)。
    • 远程仓库一般用于团队协作或备份。

示意图:

1
2
编辑工作区  →  暂存区  →  本地仓库  →  远程仓库
(修改) (git add) (git commit) (git push)

我们可以先将需要提交的文件暂存到暂存区中,最后一次性将所有文件提交到本地仓库。

2. Git 的四种文件状态

Git 中的文件通常处于以下 四种状态

文件状态 描述 命令
未跟踪(Untracked) 文件新建但未添加到 Git 版本控制 git add
已暂存(Staged) 通过 git add 添加到暂存区,等待提交 git commit
已提交(Committed) 通过 git commit 提交到本地仓库 git push
已修改(Modified) 文件被修改但未 git add git addgit checkout -- <file>

文件状态流转示意图:

1
2
3
4
未跟踪(Untracked) → 已暂存(Staged) → 已提交(Committed)
↑(git add) ↑(git commit)
↓(修改文件) ↓(修改文件)
已修改(Modified) (再次进入 Modified 状态)

八、添加和提交文件

1. git status查看仓库的状态

git status 命令用于查看 当前 Git 仓库的状态,包括:

  • 文件的跟踪状态(已提交、已修改、已暂存、未跟踪等)。
  • 当前分支信息(是否有未提交的更改、是否与远程分支同步)。
  • 是否有需要提交的变更

2. git add(添加到暂存区)

git add 命令用于 将修改的文件添加到暂存区(Staging Area),准备提交。它不会立即创建提交记录,而是让 Git 记录哪些更改需要被提交。

常见用法:

1
2
3
4
git add <文件名>   # 添加单个文件到暂存区
git add . # 添加当前目录下的所有文件到暂存区
git add -A # 添加所有修改(包括删除、新增、修改)
git add "*.txt" # 添加所有 .txt 文件

git add使用通配符来添加文件到暂存区

1. 常见通配符用法

通配符 作用 示例 说明
* 匹配任意数量的字符(包括空字符) git add *.txt 添加当前目录下所有 .txt 文件
? 匹配任意单个字符 git add file?.txt 添加 file1.txtfileA.txt
[abc] 匹配括号内的任意一个字符 git add file[12].txt 添加 file1.txtfile2.txt,但不包括 file3.txt
[a-z] 匹配指定范围内的字符 git add file[a-z].txt 添加 filea.txtfilez.txt
** 递归匹配所有子目录(Git 2.0+) git add **/*.txt 添加所有子目录中的 .txt 文件

3. git commit(提交到本地仓库)

git commit 命令用于 将暂存区的内容提交到本地仓库,并生成新的提交记录。提交时,通常需要添加一条描述本次提交的 提交信息(commit message),以便回溯。

常见用法:

1
2
3
4
git commit # 通过这个命令提交文件,则会默认进入一个交互界面,通常默认是vim。然后通过vim操作在交互界面第一行写下描述信息。
git commit -m "提交信息" # 提交暂存区的文件,并添加描述信息
git commit -a -m "提交信息" # 跳过 add,直接提交已修改的文件(但不包括新建文件)
git commit --amend -m "修改提交信息" # 修改最近一次提交的信息

4. git log查看提交记录

git log 是 Git 中用于查看提交历史记录的命令。它可以显示每次提交的 提交哈希值(commit ID)作者信息提交时间提交信息,帮助开发者追踪代码的变更历史。

1. 退出 git log

git log 显示内容太多时,会进入 分页模式(类似 less 命令),你可以:

  • q 退出 查看历史模式
  • 翻页
  • space 向下翻页

2. 常见选项

选项 作用
--oneline 单行显示每个提交记录(简洁模式)
--graph 图形化方式展示分支合并情况
--all 显示所有分支的提交记录
--author="用户名" 仅显示某个作者的提交记录
--since="3 days ago" 仅显示最近 3 天的提交
--until="2025-01-01" 仅显示 2025 年 1 月 1 日前的提交
--grep="关键字" 仅显示提交信息包含指定关键字的提交
-p 显示每次提交的详细修改内容
-n <数量> 仅显示最近的 n 条提交记录

5. 实操

(1)在没创建任何文件时使用git status命令。

1
2
3
4
5
6
7
8
9
10
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git status
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

(2)按照你喜欢的方式在该仓库下创建一个新的文件,随后查看git仓库状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ vim file1.txt
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git status
On branch main

No commits yet

Untracked files:
(use "git add <file>..." to include in what will be committed)
file1.txt

nothing added to commit but untracked files present (use "git add" to track)

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

可以在显示信息中发现多了一个Untracked files未被跟踪的文件file1.txt。

(3)使用git add命令将未被跟踪的文件添加到暂存区,随后查看git仓库状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git add file1.txt

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git status
On branch main

No commits yet

Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: file1.txt


34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

仓库状态显示Changes to be committed:表示暂存区有文件已经修改了,但是没有提交,等待被提交。

同时提示:use "git rm --cached <file>..." to unstage,表示可以使用这个命令来将把添加到暂存区的文件再取消暂存。

(4)使用git commit -m "提交文件描述信息"命令来将暂存区的文件提交到仓库中,随后查看git仓库状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git commit -m "第一次提交"
[main (root-commit) 67c8758] 第一次提交
1 file changed, 1 insertion(+)
create mode 100644 file1.txt

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git status
On branch main
nothing to commit, working tree clean

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

git commit命令只会将暂存区中的文件提交到仓库中。

(5)在仓库下多创建几个文件,然后通过使用通配符的方式来添加文件到暂存区。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git status
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
file2.txt
file3.txt
file4.txt
file5.java

nothing added to commit but untracked files present (use "git add" to track)

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git add *.txt

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: file2.txt
new file: file3.txt
new file: file4.txt

Untracked files:
(use "git add <file>..." to include in what will be committed)
file5.java


34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

可以看到通过执行git add *.txt指令,所有以.txt结尾的文件都有添加到暂存区,而以.java结尾的文件则没有。

(5)通过git add .指令将当前目录下的所有文件添加到暂存区。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git add .

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: file2.txt
new file: file3.txt
new file: file4.txt
new file: file5.java


34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

(6)通过git commit指令提交暂存区的文件。

1
2
3
4
5
6
7
8
9
10
11
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git commit
[main 060e8d1] 第二次提交
4 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file2.txt
create mode 100644 file3.txt
create mode 100644 file4.txt
create mode 100644 file5.java

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

(7)使用git log查看提交记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git log
commit 060e8d127592127f32c759acc7f7b178503d486a (HEAD -> main)
Author: Ryan-Joee <3497882088@qq.com>
Date: Sat Feb 1 16:56:55 2025 +0800

第二次提交

commit 67c8758d088254c83884364450879f27812b9e36
Author: Ryan-Joee <3497882088@qq.com>
Date: Sat Feb 1 16:41:46 2025 +0800

第一次提交

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$ git log -1
commit 060e8d127592127f32c759acc7f7b178503d486a (HEAD -> main)
Author: Ryan-Joee <3497882088@qq.com>
Date: Sat Feb 1 16:56:55 2025 +0800

第二次提交

34978@Ryan MINGW64 /d/Repository/my-repo (main)
$

九、git reset回退版本

git reset 是 Git 中用于 回退提交或撤销修改 的命令,常用于:

  • 取消已经提交的更改
  • 将提交回退到某个历史版本
  • 取消 git add 但不影响工作区文件

1. git reset 的三种模式

git reset 主要有 soft(软重置)、mixed(默认)、hard(硬重置) 三种模式,影响的范围不同:

模式 作用 影响 HEAD 指针 影响 暂存区(index) 影响 工作区(working directory)
--soft 回退提交,但保留暂存区和工作区的修改 ✅ 移动 ❌ 不变 ❌ 不变
--mixed(默认) 回退提交,清空暂存区,但保留工作区的修改 ✅ 移动 ✅ 清空 ❌ 不变
--hard 彻底回退提交,并丢弃所有修改 ✅ 移动 ✅ 清空 ✅ 丢弃

2. 常见用法

(1)撤销最近一次提交(保留代码)

1
git reset --soft HEAD~1

作用:

  • 仅撤销最近的一次提交(HEAD~1 指的是上一个提交)
  • 代码仍然保留在暂存区,可以重新提交

适用于

  • 提交信息写错了,想重新提交
  • 误提交但代码还需要

(2)撤销最近一次提交(保留代码,但取消 git add

1
git reset --mixed HEAD~1

作用:

  • 撤销最近的一次提交
  • 暂存区清空git add 过的文件回到未追踪状态)
  • 工作区保留代码,可以重新 git add 后再提交

适用于

  • 误提交,但想重新组织代码再提交

(3)彻底回退(删除提交 & 代码)

1
git reset --hard HEAD~1

作用:

  • 撤销最近的一次提交
  • 暂存区清空
  • 工作区代码也恢复到上次提交的状态(所有未提交的更改都会丢失!)

谨慎使用,尤其是团队协作时,--hard 可能导致代码丢失。

适用于

  • 彻底撤销提交,并恢复原始代码状态
  • 想回到之前的某个稳定版本

(4)回退到指定提交

如果想回退到某个特定提交(不是最近的提交),需要使用提交哈希值

1
2
3
git reset --soft <commit-id>
git reset --mixed <commit-id>
git reset --hard <commit-id>

查看提交哈希值git log --oneline

示例:

1
git reset --hard e6f9b7b

这将回退到 e6f9b7b 这个提交,并丢弃之后的所有提交和修改。

(5)取消 git add

如果你使用 git add 添加了文件,但还未 git commit,可以用 git reset 取消:

1
git reset <文件名>

示例:

1
2
git add hello.txt  # 先添加文件
git reset hello.txt # 取消暂存,但文件内容不变

适用于误 git add 某个文件,不想让它进入暂存区。

HEAD~1 这种表示法在 Git 中是有特定含义的,它是 Git 的提交历史引用语法(commit reference syntax)的一部分,不能随意取名。

3. HEAD~1 的含义

HEAD~1 表示 当前提交(HEAD)之前的第 1 个提交,即上一个提交。

  • HEAD 指向当前分支的最新提交(当前的 commit)。
  • ~1 表示向上回退 1 个提交(等价于 HEAD^)。

示例:

1
git reset --soft HEAD~1

相当于回到上一次提交,但保留工作区和暂存区的修改

(1) HEAD~N 的用法

语法 含义
HEAD 当前分支的最新提交
HEAD~1 上一个提交
HEAD~2 上上个提交
HEAD~3 上上上个提交
HEAD~N 向上回退 N 个提交

示例:

1
git reset --hard HEAD~3  # 回退到 3 个提交前的状态

HEAD~N 只沿着当前分支向后回退,适用于线性提交的情况。

(2)HEAD^HEAD~ 的区别

除了 HEAD~N,Git 还有 HEAD^N 这样的语法:

语法 含义
HEAD^ 上一个提交(等价于 HEAD~1
HEAD^2 如果是合并提交,表示第二个父提交
HEAD^N 合并提交的第 N 个父提交
HEAD~N 沿着当前分支的主线向上回退 N

示例:

1
2
git reset --hard HEAD^  # 回退到上一个提交(等价于 HEAD~1)
git reset --hard HEAD^2 # 回退到合并提交的第二个父提交

HEAD^N 主要用于合并提交的情况下,而 HEAD~N 适用于普通提交。

(3)结论

  • HEAD~N 表示回退 N 次提交,适用于线性提交
  • HEAD^N 适用于合并提交,可以指定第 N 个父提交。

十、git reflog 概述

git reflog(Reference Log,引用日志)是 Git 提供的一个记录 HEAD 变更历史的命令,它可以用于恢复误操作(如 git reset --hardgit checkout 等),帮助找回丢失的提交。


1. git reflog 作用

HEAD(当前提交指针)发生变更时(如 commitresetcheckout 等操作),Git 会自动记录这些变更历史。
使用 git reflog,可以查看 HEAD 过去指向过哪些提交,甚至恢复被 git reset --hard 删除的提交。


2. git reflog 基本用法

(1)查看 HEAD 变更历史

1
git reflog

示例输出:

1
2
3
4
5
e6f9b7b (HEAD -> main) HEAD@{0}: commit: 修复了登录 Bug
5c3e2a0 HEAD@{1}: reset: moving to HEAD~1
a1b2c3d HEAD@{2}: checkout: moving from dev to main
9a8b7c6 HEAD@{3}: commit: 添加了新功能
f4e5d6a HEAD@{4}: commit: 修改了 API

解释:

  • HEAD@{0} 代表当前 HEAD 位置
  • HEAD@{1} 是上一次 HEAD 变更的位置
  • HEAD@{2} 是更早的 HEAD 位置
  • 每条记录后面是 commit ID 和对应的操作

3. git reflog 结合 git reset

如果误用了 git reset --hard,想找回丢失的提交:

1
2
3
git reflog
git reset --hard HEAD@{1} # 恢复到上一个 HEAD 位置
git reset --hard 提交哈希值 # 恢复到指定的提交哈希值的版本

示例:

1
git reset --hard HEAD@{4}

这样就可以恢复到 HEAD@{4} 记录的提交。


4. git reflog 结合 git checkout

如果切换了分支导致某个提交找不到:

1
2
git reflog
git checkout <commit-id>

可以使用 commit-id 切回该提交,并创建新分支:

1
2
git branch recover-branch <commit-id>
git checkout recover-branch

5. git log vs git reflog

命令 作用 记录对象 适用于恢复误删提交
git log 查看提交历史 仅记录提交 ❌ 不能恢复 git reset --hard
git reflog 记录 HEAD 变更 记录所有 HEAD 变更 ✅ 可以恢复 git reset --hard

6. 结论

  • git reflog 记录 HEAD 变更历史,适用于找回丢失的提交
  • 结合 git reset --hard HEAD@{N},可以恢复误删的提交。
  • git reflog 不会被推送到远程,仅在本地有效。

十一、git diff查看差异

git diff 是 Git 中用于比较不同版本之间代码变更的命令,适用于查看未提交的修改、暂存区与最新提交的差异,以及不同分支或提交之间的差异

  1. 查看工作区、暂存区、本地仓库之间的差异
  2. 查看不同版本之间的差异
  3. 查看不同分支之间的差异

1. git diff 基本用法

(1)查看工作区未暂存的修改

1
git diff
  • 比较 工作区暂存区 的差异(即还未 git add 的修改)。
  • 适用于 查看哪些文件修改了但还未添加到暂存区。

(2)查看暂存区和最近一次提交的差异

1
git diff --cached

1
git diff --staged
  • 比较暂存区最近一次提交(HEAD) 的差异。
  • 适用于检查 git add 之后但还未 git commit 的修改。

(3)查看工作区和最近一次提交的所有差异

1
git diff HEAD
  • 显示 工作区最近一次提交(HEAD) 之间的修改(包括已 git add 和未 git add 的文件)。
  • 适用于全面检查所有未提交的更改。

(4)查看两个分支的差异

1
git diff main dev
  • 比较 main 分支和 dev 分支的代码差异。
  • 适用于检查不同分支之间有哪些修改。

(5)查看两个提交的差异

1
git diff <commit1> <commit2>

示例:

1
git diff a1b2c3d e6f9b7b
  • 比较 a1b2c3de6f9b7b 这两个提交之间的代码变更。

(6)查看指定文件的差异

1
git diff <文件名>

示例:

1
git diff index.html
  • 仅查看 index.html 文件的修改情况。

(7)查看某个提交的具体改动

1
git diff <commit-id>^ <commit-id>

1
git show <commit-id>
  • commit-id^ 代表 commit-id 的前一个提交。
  • 适用于查看某个 commit 做了哪些修改。

示例:

1
git diff e6f9b7b^ e6f9b7b

1
git show e6f9b7b

十二、从版本库中删除文件

在 Git 版本库中删除文件时,可以选择**仅删除 Git 追踪(保留本地文件)**或**彻底删除文件(工作区和版本库都删除)**。


1. 删除文件但保留本地文件

如果你只想让 Git 停止追踪某个文件,但仍保留该文件在本地(不删除实际文件),可以使用:

1
git rm --cached <文件名>

示例:

1
2
git rm --cached config.json
git commit -m "从 Git 版本库中删除 config.json,但保留本地文件"

📌 适用于:

  • 误提交了不应纳入 Git 版本控制的文件,例如 *.lognode_modules/、配置文件等。
  • 之后可以通过 .gitignore 忽略该文件,防止它再次被提交。

2. 彻底删除文件

如果你希望文件从本地和 Git 版本库中都删除,使用:

1
2
git rm <文件名>
git commit -m "删除 <文件名>"

示例:

1
2
git rm old_script.py
git commit -m "删除 old_script.py"

📌 适用于:

  • 确定不再需要该文件。
  • 该文件已经纳入 Git 版本管理,现在想要彻底删除。

3. 删除整个文件夹

如果要删除整个文件夹及其内容,使用:

1
2
git rm -r <目录名>
git commit -m "删除 <目录名> 目录"

示例:

1
2
git rm -r logs/
git commit -m "删除 logs 目录"

4. 强制删除未暂存的修改

如果文件有未提交的更改,Git 默认不会允许删除。如果要强制删除:

1
git rm -f <文件名>

示例:

1
2
git rm -f debug.log
git commit -m "强制删除 debug.log"

📌 警告:

  • -f--force)会直接删除文件,无法恢复,请谨慎使用。

5. 撤销 git rm 操作

如果不小心删除了文件,还没有 commit,可以用 git checkout 恢复:

1
git checkout -- <文件名>

或者,如果已经提交了删除操作,可以使用 git reset 找回:

1
2
git reset HEAD~1  # 撤销上一次提交
git checkout -- <文件名> # 恢复删除的文件

6. 提交更改并推送

删除文件后,记得提交并推送更改:

1
2
git commit -m "删除了不需要的文件"
git push origin main

7. 结论

命令 作用 适用场景
git rm --cached <文件> 仅从 Git 删除,保留本地文件 误提交了配置文件等,需要 Git 忽略
git rm <文件> 删除文件,并提交更改 不再需要该文件
git rm -r <目录> 删除整个目录 删除文件夹及其内容
git rm -f <文件> 强制删除文件 文件有未提交的修改,但仍需删除

📌 删除文件后,一定要 git commit,否则不会真正影响版本库! 🚀

十三、git ls-files列出 Git 版本库中已追踪的文件

git ls-files 用于列出 Git 版本库中已追踪的文件,可以帮助你快速查看哪些文件被 Git 管理,以及排除 .gitignore 影响的文件。


1. git ls-files 的基本用法

1
git ls-files
  • 列出当前 Git 仓库中所有被追踪的文件(即 Git 版本库中的文件)。
  • 不会显示 未被 Git 追踪的文件(如 .gitignore 忽略的文件或新创建但未 git add 的文件)。

2. git ls-files 常用选项

(1)查看被忽略的文件

1
git ls-files --ignored --others --exclude-standard

📌 解析:

  • --ignored:显示 .gitignore 中被忽略的文件。
  • --others:显示 Git 未追踪 的文件(未 git add)。
  • --exclude-standard:遵循 .gitignore 规则。

(2)查看已暂存但未提交的文件

1
git ls-files --stage

📌 作用:

  • 显示暂存区的文件,并附带文件的哈希值、权限信息、文件路径等。

(3)查看已修改但未暂存的文件

1
git ls-files --modified

📌 作用:

  • 仅显示已被 Git 追踪但发生了修改,且git add 的文件。

(4)查看已删除但未提交的文件

1
git ls-files --deleted

📌 作用:

  • 列出被 Git 追踪但已在工作区中删除的文件(尚未 git commit)。

(5)查看未被 Git 追踪的文件

1
git ls-files --others

📌 作用:

  • 显示 Git 未追踪的文件(未 git add)。

(6)仅显示已暂存的文件

1
git ls-files --cached

📌 作用:

  • 显示已添加到暂存区但未提交的文件。

(7)查看已忽略的文件

1
2
git ls-files --others --ignored --exclude-standard
git ls-files --ignored --others --exclude-standard

📌 作用:

  • 仅列出 .gitignore 规则下被忽略的文件

3. git ls-files 结合其他命令

(1)结合 grep 过滤文件

1
git ls-files | grep "config"

📌 作用:

  • 仅显示文件名包含 "config" 的文件。

(2)结合 xargs 进行批量操作

1
git ls-files '*.log' | xargs rm

📌 作用:

  • 删除 Git 版本库中所有 .log 文件。

十四、.gitignore文件

.gitignore 文件用于告诉 Git 忽略特定文件或文件夹,这些被忽略的文件不会被 Git 追踪、提交或推送。

.gitignore文件生效的前提:该文件不能是已经添加到版本库中的文件

1. .gitignore 作用

  • 避免将敏感文件(如密码配置、API 密钥)提交到 Git。
  • 忽略自动生成的文件(如编译文件、日志、临时文件)。
  • 保持代码仓库整洁,避免不必要的文件污染版本库。

2. 应该忽略的文件

(1)系统或者软件自动生成的文件

(2)编译产生的中间文件和结果文件

(3)运行时生成的日志文件、缓存文件、临时文件

(4)涉及身份、密码、口令、密钥等敏感信息文件

3. 创建 .gitignore 文件

在 Git 仓库的根目录创建 .gitignore 文件:

1
touch .gitignore

然后在 .gitignore 文件中写入要忽略的文件或目录。


4. .gitignore 语法规则

  • 忽略指定文件

    1
    debug.log

    忽略 debug.log 文件。

  • 忽略整个文件夹

    1
    /logs/

    忽略 logs 目录及其所有内容。

  • 忽略特定类型的文件

    1
    *.log

    忽略所有 .log 结尾的文件。

  • 忽略某个文件,但保留特定文件

    1
    2
    *.txt
    !README.txt

    忽略所有 .txt 文件,但**保留 README.txt**。

  • 忽略某个目录下的所有内容,但保留特定文件

    1
    2
    /config/*
    !/config/settings.json

    忽略 config 目录下的所有文件,但**保留 settings.json**。

  • 使用 # 添加注释

    1
    2
    # 忽略所有的 .log 文件
    *.log
  • 忽略某个目录下的所有子目录

1
2
# 忽略 doc/ 目录及其所有子目录下的 .pdf文件
doc/**/*.pdf

总结上面的,最终在.gitignore文件中包括以下内容:

1
2
3
4
5
6
7
8
9
debug.log
/logs/
*.log
*.txt
!README.txt
/config/*
!/config/settings.json
# 忽略所有的.log文件
*.log

5. .gitignore文件匹配规则

(1).gitignore文件是从上到下逐行匹配的,每一行表示一个忽略模式。

(2)空行或者以#开头的行会被git忽略。一般空行用于可读性的分隔,#一般用作注释

(3)使用标准的Blob模式匹配,例如

​ (1 星号*通配任意个字母

​ (2 问号?匹配单个字符

​ (3 中括号[] 表示匹配列表中的单个字符,比如:[abc] 表示a/b/c

(4)两个星号**表示匹配任意的中间目录

(5)中括号可以使用短中线连接,比如:

​ [0-9]:表示任意一位数字,[a-z]:表示任意一位小写字母

(6)感叹号!表示取反