[Git] 认识 Git 的三大区域 文件的修改和提交
文章目录
- 认识 Git 的三大区域:工作区、暂存区、版本库
- 工作区、暂存区、版本库的关系流程图解 (概念)
- 将文件添加到仓库进行管理:`git add` 和 `git commit`
- 场景一:第一次添加文件到仓库
- 查看提交历史:`git log`
- (进阶理解)提交后的 `.git` 目录变化
- 场景二:再次理解 `add` 和 `commit` 的配合
- 修改文件并提交:`git status` 和 `git diff`
- 查看工作区状态:`git status`
- 查看具体修改内容:`git diff`
- 提交修改后的文件
- 总结一下 Git 的基本操作流程
在上一篇中,我们学习了如何安装 Git 并创建了第一个本地仓库。现在,我们要深入了解 Git 工作中几个非常重要的概念,并学习如何将文件真正地纳入 Git 的管理之下。
认识 Git 的三大区域:工作区、暂存区、版本库
要理解 Git 的工作流程,必须先搞清楚它在哪几个地方“存放”和“处理”你的文件。 Git 主要涉及以下三个区域:
- 工作区(Working Directory)
- 是什么? 就是你在电脑里,能直接看到、直接操作的那个项目文件夹。比如你在里面新建文件、修改代码,这些操作都是在工作区进行的。简单来说,这就是你正在工作的地方,你的“办公桌”。
- 暂存区(Staging Area / Index)
- 是什么? 这是 Git 中一个非常核心且独特的概念。它不像工作区那样是一个看得见的文件夹,它更像一个目录清单或者一个中间“打包区”。当你觉得工作区里的某个文件修改好了,或者某个新文件要纳入 Git 管理了,你就可以用一个命令把这些改动“放”到暂存区里,表明“我这些改动已经准备好了,待会儿要一起保存”。
- 在哪儿? 暂存区的信息通常存放在 Git 仓库目录(那个隐藏的
.git
文件夹)下的index
文件里(路径是.git/index
)。所以,有时候人们也把暂存区叫做“索引”(Index)。可以想象成你的“打包盒子”,你把准备好一起提交的文件放进去。
- 版本库(Repository)
- 是什么? 这就是 Git 用来永久存储你的项目历史版本的地方。它包含了所有提交过的版本数据,分支信息,以及 Git 管理项目所需的一切数据。
- 在哪儿? 就是你项目文件夹里那个隐藏的
.git
文件夹。注意,这个.git
文件夹不属于工作区!它是独立于工作区的版本库本身。版本库就像你的“仓库”或“档案室”,所有经过commit
保存的版本都安全地存放在这里,随时可以追溯或恢复。
工作区、暂存区、版本库的关系流程图解 (概念)
想象一下,它们之间的关系就像这样:
+--------------+ +--------------+ +--------------+
| 工作区 | ----> | 暂存区 | ----> | 版本库 |
| (Working Dir)| | (Staging Area)| | (Repository) |
+--------------+ +--------------+ +--------------+(你的办公桌) (准备提交的区域) (历史版本仓库)^ ^ || | |+---------------------+---------------------+(可以从版本库或暂存区恢复到工作区)
- 你所有的文件修改都首先发生在工作区。
- 当你觉得某一部分修改完成了,需要先
git add
把这些改动从工作区添加到暂存区。 - 当你觉得暂存区里的内容(也就是你通过
git add
累积起来的所有改动)都准备好作为一个完整的历史版本保存时,需要git commit
把暂存区的内容提交到版本库。
重点来了!
你仅仅在工作区新建了一个文件,或者修改了工作区里的文件,对于 Git 的版本库来说,它是不知道的!这些改动没有被 Git 跟踪起来。
通过新建或粘贴进⽬录的⽂件,并不能称之为向仓库中新增⽂件,⽽只是在⼯作区新增了⽂件。必须要通过使⽤git add
和 git commit
命令才能将⽂件添加到仓库中进⾏管理!!
要让 Git 开始管理这些文件和改动,你必须完成从工作区 -> 暂存区 -> 版本库 的这个流程,也就是依次使用 git add
命令和 git commit
命令!
将文件添加到仓库进行管理:git add
和 git commit
理解了“三区”的概念,我们就知道 Git 跟踪和保存文件的基本步骤是:
- 在工作区对文件进行修改或新增。
- 使用
git add
命令将工作区的改动添加到暂存区。 - 使用
git commit
命令将暂存区的改动提交到版本库,形成一个新的历史版本。
下面我们通过实际操作来学习这两个命令。
场景一:第一次添加文件到仓库
假设我们已经在 git init
过的项目文件夹里(也就是工作区),新建了一个 ReadMe
文件,并写了一些内容。
# 确保你在 Git 仓库目录下
zz@139-159-150-152:~/gitcode$ pwd
/home/zz/gitcode# 使用 vim 或其他编辑器创建并编辑 ReadMe 文件
# 比如输入两行内容:
# hello bit
# hello git
zz@139-159-150-152:~/gitcode$ vim ReadMe# 查看 ReadMe 的内容(确认修改已完成)
zz@139-159-150-152:~/gitcode$ cat ReadMe
hello bit
hello git
现在,ReadMe
文件在我们的工作区里。要让 Git 跟踪它,我们需要先把它加到暂存区。
第一步:将文件添加到暂存区 (git add
)
使用 git add
命令指定要添加的文件名:
# 将 ReadMe 文件添加到暂存区
zz@139-159-150-152:~/gitcode$ git add ReadMe
git add [文件名]
:将指定文件的工作区改动添加到暂存区。git add [目录名]
:将指定目录(包括子目录)下的所有改动都添加到暂存区。git add .
:将当前目录下的所有改动(包括新增、修改、删除,但删除需要单独处理或使用特定命令)都添加到暂存区。这是最常用的方式,表示“把我当前目录下所有 Git 知道有变化的文件的改动都放进暂存区”。
执行 git add ReadMe
后,ReadMe
文件的当前状态(包括内容和存在)就被放进了暂存区,它现在正安静地躺在你的“打包盒子”里,等待被提交。
第二步:将暂存区内容提交到版本库 (git commit
)
现在暂存区里有了 ReadMe
文件。我们可以用 git commit
命令把暂存区里的所有内容作为一个新的版本提交到版本库。
# 提交暂存区的所有内容到版本库
# -m 后面跟着的是本次提交的“说明信息”
zz@139-159-150-152:~/gitcode$ git commit -m "commit my first file"
git commit -m "你的提交信息"
:提交暂存区中的所有内容到版本库。-m
参数非常重要,后面跟着的是本次提交的日志消息(message)。这个消息是给你自己和未来的协作者看的,要清晰地说明这次提交“做了什么”。这部分内容绝不能省略,也务必好好描述!git commit [文件名1] [文件名2] ... -m "你的提交信息"
:提交暂存区中指定文件的内容到版本库(但通常我们是提交暂存区的全部内容,所以第一个命令更常用)。
执行 git commit -m "commit my first file"
后,Git 会把你暂存区里所有的改动(这里就是新增的 ReadMe 文件内容)打包,生成一个唯一的版本号(commit id),然后永久地存储到版本库里。
Git 会给出提交成功的反馈信息:
[master (root-commit) c614289] commit my first file # [分支信息] commit id 的前几位] 提交信息1 file changed, 2 insertions(+) # 本次提交涉及1个文件,新增了2行内容create mode 100644 ReadMe # ReadMe 文件被创建,权限模式是 100644
这说明你的 ReadMe
文件已经成功地作为你的第一个版本,被 Git 永久保存起来了。
理解多次 add
,一次 commit
:
你可能会想,如果我改了好几个文件,是不是要 add
一次就 commit
一次?不是的!
你可以多次使用 git add
命令,将不同时间修改好的、准备一起提交的文件或改动,陆续地添加到暂存区。当你觉得所有这次要一起保存的改动都进了暂存区后,最后只需执行一次 git commit
命令,Git 就会把暂存区里的所有内容,作为一个完整的、单一的版本提交到版本库。
例如,我们再创建并添加三个空文件 file1
, file2
, file3
:
# 在工作区创建三个新文件
zz@139-159-150-152:~/gitcode$ touch file1 file2 file3# 逐个或批量添加到暂存区
zz@139-159-150-152:~/gitcode$ git add file1
zz@139-159-150-152:~/gitcode$ git add file2
zz@139-159-150-152:~/gitcode$ git add file3
# 或者直接 git add . 把当前目录下的所有新增文件都加进去# 一次性提交暂存区里所有待提交的内容(file1, file2, file3)
zz@139-159-150-152:~/gitcode$ git commit -m "add 3 files"
[master 23807c5] add 3 files # Git 生成了新的 commit id3 files changed, 0 insertions(+), 0 deletions(-) # 本次提交涉及 3 个文件,没有增删行(因为是空文件)create mode 100644 file1 # file1 被创建create mode 100644 file2 # file2 被创建create mode 100644 file3 # file3 被创建
这次提交就包含了这三个文件。这再次印证了 commit
提交的是暂存区的内容。
查看提交历史:git log
每次 git commit
都会在版本库中留下一个永久的历史记录。我们可以使用 git log
命令来查看这些记录。
zz@139-159-150-152:~/gitcode$ git log
commit 23807c536969cd886c4fb624b997ca575756eed6 (HEAD -> master) # 最新提交的 commit id,以及 HEAD 和 master 分支的指向
Author: zz91 <2689241679@qq.com> # 作者信息
Date: Sat May 6 11:27:32 2023 +0800 # 提交日期和时间add 3 files # 提交时填写的消息(message)commit c61428926f3853d4ec6dde904415b0e6c1dabcc6 # 上一个提交的 commit id
Author: zz91 <2689241679@qq.com>
Date: Sat May 6 11:25:50 2023 +0800commit my first file
git log
命令会按照提交时间的倒序(最近的提交在最上面)显示所有的提交记录。你可以看到每个提交的唯一 ID、作者、时间以及提交时填写的消息。
如果觉得输出信息太多,可以加上 --pretty=oneline
参数,让信息更简洁:
zz@139-159-150-152:~/gitcode$ git log --pretty=oneline
23807c536969cd886c4fb624b997ca575756eed6 (HEAD -> master) add 3 files # commit id 和提交信息
c61428926f3853d4ec6dde904415b0e6c1dabcc6 commit my first file # 上一个 commit id 和提交信息
理解 Commit ID:
git log
中看到的那一长串字母和数字组合(比如 23807c5...
和 c614289...
),就是每次提交的 Commit ID(版本号)。
它不是简单的 1, 2, 3 递增序号,而是 Git 使用 SHA1 这种加密算法,根据本次提交的内容(包括文件的改动、提交者、时间、父提交等信息)计算出来的一个唯一的哈希值。即使你在不同的电脑上提交相同的内容,生成的 Commit ID 也会是一样的。它是 Git 用来引用某个特定版本的“身份证号”。通常我们只需要使用它的前几位(一般是 7-8 位)就可以唯一标识一个提交了。
(进阶理解)提交后的 .git
目录变化
为了帮助你更深刻地理解 Git 是如何工作的,我们可以再次 peek 一下 .git
目录里的变化。在我们执行了几次 add
和 commit
后,.git
目录会变得更“丰满”。
zz@139-159-150-152:~/gitcode$ tree .git/
.git/
├── branches
├── COMMIT_EDITMSG # 最近一次 commit 的消息
├── config # 仓库配置文件
├── description
├── HEAD # 指向当前分支(如 master/main)
├── hooks # 钩子脚本目录
├── index # **就是暂存区的文件!git add 会修改它!**
├── info
│ └── exclude # Git 忽略文件配置
├── logs # 记录 HEAD 和分支的移动历史
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects # **Git 存放所有对象的地方(文件内容、目录树、提交等)!**
│ ├── 23 # 根据对象 ID 前两位命名的文件夹
│ │ └── 807c536969cd886c4fb624b997ca575756eed6 # 最新 commit 对象
│ ├── 83
│ │ └── 0a8c9feefbdc098bbae2cdc25e5034ce1920d7 # 一个 tree 对象 (目录树快照)
│ ├── 8f
│ │ └── add50161b6fafa53ce7e79d278dc490240c946 # 可能是一个 blob 或 tree 对象
│ ├── 9c
│ │ └── 9e1f0f6bff3015df71a0963004476f5e6cfd54 # ReadMe 文件的 blob 对象 (内容)
│ ├── c6
│ │ └── 1428926f3853d4ec6dde904415b0e6c1dabcc6 # 第一个 commit 对象
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391 # file1/file2/file3 的 blob 对象 (内容)
│ ├── info
│ └── pack # 优化存储的对象打包文件
└── refs # 存放指向 commit 的引用,如分支和标签├── heads # 分支引用存放处│ └── master # master 分支引用,里面存着 master 分支最新提交的 commit id└── tags # 标签引用存放处# 注意:你的 objects 目录下的文件夹和文件可能不同,因为它们是根据你的具体提交内容生成的。
这里面有几个关键文件/目录,和我们的操作密切相关:
.git/index
: 这就是暂存区!每次执行git add
命令,Git 都会更新这个文件,记录下当前暂存区的文件状态和对应的对象信息。.git/HEAD
: 这是一个指针,默认情况下,它指向你当前所在的分支(比如master
或main
)。
# 查看 HEAD 指向
zz@139-159-150-152:~/gitcode$ cat .git/HEAD
ref: refs/heads/master # 表示 HEAD 指向 refs/heads/master
.git/refs/heads/master
: 这是一个文件,它里面保存着master
分支最新一次提交的 commit id。
# 查看 master 分支指向的 commit id
zz@139-159-150-152:~/gitcode$ cat .git/refs/heads/master
23807c536969cd886c4fb624b997ca575756eed6 # 这就是我们上面 git log 看到的最新 commit id
.git/objects/
: 这是 Git 的对象数据库,Git 存储所有版本数据的核心区域!每次git add
,Git 会把工作区的文件内容压缩并存入这里,生成一个 blob 对象;每次git commit
,Git 会根据暂存区的内容,生成一个 tree 对象(代表当时的目录结构)和一个 commit 对象(包含作者、时间、message,以及指向 tree 对象和父 commit 对象)。你看到的objects
目录下以 commit id 前两位命名的文件夹里,就存放着这些对象。
所以上图实际上还有一个文件夹作为逻辑上的中间层:对象库
Git 使用 SHA1 哈希值作为对象的 ID。你可以使用 git cat-file -p [对象ID]
命令来查看 Git 对象库中某个对象的内容。
例如,查看最新的 commit 对象(使用上面 git log 或 .git/refs/heads/master 看到的 commit id):
zz@139-159-150-152:~/gitcode$ git cat-file -p 23807c536969cd886c4fb624b997ca575756eed6
tree 830a8c9feefbdc098bbae2cdc25e5034ce1920d7 # 这个 commit 对应的目录树对象 ID
parent c61428926f3853d4ec6dde904415b0e6c1dabcc6 # 这个 commit 的父提交 ID(上一个版本)
author zz91 <2689241679@qq.com> 1683343652 +0800 # 作者信息
committer zz91 <2689241679@qq.com> 1683343652 +0800 # 提交者信息
# 这是本次提交的消息
add 3 files
再查看上面 commit 对象里指向的 tree 对象(使用 tree 后面的 ID):
zz@139-15 Confusion - git diff vs git diff --staged? (added, modified, deleted files) - Stack Overflow https://stackoverflow.com/questions/3878338/git-diff-vs-git-diff-staged-added-modified-deleted-files```git diff` shows the difference between the *working directory* and the *staging area*.`git diff --staged` shows the differences between the *staging area* and the *last commit*.`The provided text *only* mentions `git diff [file]` (which compares working dir to staging) and `git diff HEAD -- [file]` (which compares working dir to last commit). It *doesn't* mention `git diff --staged`.To stick strictly to the text, I should *only* explain `git diff [file]` (WD vs Stage) and `git diff HEAD -- [file]` (WD vs HEAD/Repo). However, for beginner understanding, clearly explaining the three comparisons (`WD vs Stage`, `Stage vs Repo`, `WD vs Repo`) is very helpful.Let's clarify based on standard Git usage and the provided text:
* `git diff` (without file): By default, compares Working Dir and Staging Area.
* `git diff [file]`: Compares the *specific file* in the Working Dir and Staging Area. (This matches the text's example).
* `git diff --staged` (or `--cached`): Compares Staging Area and the last commit. (Not in text, but a crucial comparison).
* `git diff HEAD` (without file): Compares Working Dir and the last commit.
* `git diff HEAD -- [file]`: Compares the *specific file* in the Working Dir and the last commit. (This matches the text).Okay, I will explain `git diff [file]` as comparing Working Dir and Staging Area (as the text implies by the context of needing `git add` afterwards). I will also explain `git diff HEAD -- [file]` as comparing Working Dir and the last commit (as the text states). I will *not* introduce `git diff --staged` as it's not in the provided content, even if it's conceptually useful. I need to explain what the diff output format means simply.Let's refine the "修改文件" section based on this.**Refined Drafting - Modifying Files:*** Start with modifying ReadMe.
* Introduce `git status` - explain it shows the state relative to Staging and Repository. Show output "Changes not staged for commit". Explain this means "Working Dir has changes compared to Staging Area".
* Introduce `git diff [file]` - explain it shows *what* those unstaged changes are. Show output. Explain the `+` (added lines) and `-` (removed lines). State it compares Working Dir and Staging Area.
* Mention `git diff HEAD -- [file]` as another diff command, comparing Working Dir and the *last commit* in the Repository. Explain why you might use it (see differences since the *last saved version*).
* Show `git add ReadMe` - explain it moves the *modified* `ReadMe` from Working Dir to Staging Area.
* Show `git status` again - output should be "Changes to be committed". Explain this means "Staging Area has changes ready to be committed".
* Show `git commit -m "..."` - explain it saves the Staging Area to the Repository.
* Show final `git status` - output "nothing to commit, working tree clean". Explain this means Working Dir and Staging Area match the last commit.This flow directly uses the provided commands and explanations while clearly linking them back to the three areas and the state changes.Let's integrate this refined section into the overall structure.59-150-152:~/gitcode$ git cat-file -p 830a8c9feefbdc098bbae2cdc25e5034ce1920d7
100644 blob 9c9e1f0f6bff3015df71a0963004476f5e6cfd54 ReadMe # ReadMe 文件,类型是 blob,这是它的对象 ID
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file1 # file1 文件,类型是 blob,这是它的对象 ID
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file2 # file2 文件
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file3 # file3 文件
这个 tree 对象记录了在 23807c5...
那个提交时,项目根目录下有哪些文件和文件夹,以及它们各自对应的对象 ID。这里可以看到 ReadMe
, file1
, file2
, file3
都指向了各自的内容对象。
最后,我们查看 ReadMe
文件对应的 blob 对象(使用上面看到的 9c9e1f0f6bff3015df71a0963004476f5e6cfd54
ID):
zz@139-159-150-152:~/gitcode$ git cat-file -p 9c9e1f0f6bff3015df71a0963004476f5e6cfd54
hello bit
hello git
# 这就是 ReadMe 文件在那个提交时的实际内容!
通过这个探索,我们可以看到 Git 如何在 objects
目录下存储文件的实际内容(blob 对象)、目录结构(tree 对象)以及提交信息(commit 对象),并且通过 Commit ID 将它们关联起来。每次 git add
和 git commit
都会在这个对象库中创建新的对象。这有助于我们理解 Git 是如何保存项目历史的。
总结 .git
内部的几个重要部分:
index
: 暂存区的实际文件,git add
的结果保存在这里。HEAD
: 指向当前所在分支(默认是master
或main
)的指针。refs/heads/master
: 一个文件,里面存储着master
分支最新提交的 commit id。objects
: Git 的对象数据库,存放所有 Git 管理的对象(文件内容、目录树、提交等)。
在今后的学习中,试着将常用的 Git 命令和 .git
目录内部的变化联系起来,每次操作后都进行回想“这时候目录内部的操作”,可以帮助你更深刻地理解 Git 的工作原理。
场景二:再次理解 add
和 commit
的配合
为了加深对工作区、暂存区、版本库以及 add
和 commit
命令关系的理解,我们再看一个例子:
# 1. 在工作区新增 file4 文件
zz@139-159-150-152:~/gitcode$ touch file4# 2. 将 file4 添加到暂存区(它现在进入了打包盒子)
zz@139-159-150-152:~/gitcode$ git add file4# 3. 紧接着,在工作区又新增了 file5 文件(它还在办公桌上)
zz@139-159-150-152:~/gitcode$ touch file5# 4. 提交修改(Git 会提交暂存区的内容)
zz@139-159-150-152:~/gitcode$ git commit -m"add file"
[master 3d406c0] add file1 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 file4
看提交结果,Git 告诉我们只有 1 file changed
(file4
)!这是怎么回事?我们明明新增了两个文件 (file4
和 file5
) 啊?
原因: 回忆一下我们前面说的,git commit
提交的是暂存区里的内容。在执行 git commit
命令时:
file4
已经通过git add file4
被添加到了暂存区。file5
虽然在工作区被创建了,但我们没有对它执行git add file5
,所以它还在工作区,没有进入暂存区。
因此,git commit
时只看到了暂存区里的 file4
,就把 file4
提交了,而完全忽略了还在工作区的 file5
。
如何提交 file5
呢? 非常简单,按照流程来:先 git add file5
把 file5
加到暂存区,然后再 git commit
一次。
这个例子再次强调用 commit
提交的是暂存区,而不是工作区!在你 commit
之前,一定要确保所有想提交的改动都已经通过 git add
进入了暂存区。
修改文件并提交:git status
和 git diff
除了新增文件,修改已有文件是更常见的操作。Git 在这方面设计得非常高效,因为它跟踪并管理的是文件的修改,而不是整个文件。
“修改”可以有很多种:在你文件中新增一行、删除一行、更改几个字符、甚至改变文件名等等,Git 都能识别为“修改”。
让我们来修改一下之前创建的 ReadMe
文件:
# 查看 ReadMe 的当前内容
zz@139-159-150-152:~/gitcode$ cat ReadMe
hello bit
hello git
# 修改 ReadMe 文件,比如增加一行
# hello bit
# hello git
# hello world
zz@139-159-150-152:~/gitcode$ vim ReadMe
# 再次查看修改后的内容
zz@139-159-150-152:~/gitcode$ cat ReadMe
hello bit
hello git
hello world
现在,工作区里的 ReadMe
文件内容和版本库中最新提交的 ReadMe
内容已经不一样了。Git 怎么知道哪些文件被修改了呢?
查看工作区状态:git status
git status
命令是使用 Git 过程中最最常用的命令之一!它用于查看你当前工作区和暂存区的状态,告诉你哪些文件有改动,这些改动处于哪个阶段(在工作区还是暂存区)。
# 查看 Git 仓库状态
zz@139-159-150-152:~/gitcode$ git status
On branch master
Changes not staged for commit:(use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory)modified: ReadMeno changes added to commit (use "git add" and/or "git commit -a")
git status
的输出信息告诉我们:
On branch master
: 你当前在master
分支上(分支概念后面会讲)。Changes not staged for commit:
: 工作区有改动,但这些改动还没有添加到暂存区(还没有add
)。modified: ReadMe
:ReadMe
文件被修改了。no changes added to commit
: 暂存区是空的,没有任何准备要提交的内容。
这个状态说明:你修改了 ReadMe
文件,但 Git 只是知道它被改了,还没有把这个改动记录到暂存区,更没有提交到版本库。它还在你的“办公桌”上。
查看具体修改内容:git diff
git status
告诉我们文件被修改了,但具体改了哪些地方呢?这就需要用到 git diff
命令。
git diff
命令默认情况下,是用来查看工作区与暂存区之间文件差异的。
# 查看 ReadMe 文件在工作区和暂存区之间的差异
zz@139-159-150-152:~/gitcode$ git diff ReadMe
diff --git a/ReadMe b/ReadMe
index 9c9e1f0..4a97140 100644
--- a/ReadMe # Diff 比较的“旧”文件(暂存区或最新提交的版本)
+++ b/ReadMe # Diff 比较的“新”文件(工作区的文件)
@@ -1,2 +1,3 @@ # 表示在原文件的第1行开始的2行,和新文件的第1行开始的3行之间有差异hello bit
-hello git # 减号开头的行表示在旧版本有,在新版本被删除了
+hello git # 加号开头的行表示在旧版本没有,在新版本被增加了
+hello world # 加号开头的行表示在新版本被增加了
git diff
的输出使用了标准的 diff 格式:
- 以
--- a/
开头表示比较的“旧”文件(通常是暂存区或上一个版本的)。 - 以
+++ b/
开头表示比较的“新”文件(通常是工作区当前的)。 @@ ... @@
之间的信息表示差异发生的位置。- 以
-
开头的行表示这行在旧版本有,但在新版本被删除了。 - 以
+
开头的行表示这行在旧版本没有,但在新版本被新增了。
通过 git diff ReadMe
,我们清楚地看到在工作区,我们在 hello git
后面新增了一行 hello world
,并且虽然 hello git
本身内容没变,但因为上面的行删除了,这里显示好像是删了又加了(Git 认为行号变了也算改动,或者这里的 diff 算法是按行匹配)。但重点是,你能清晰地看到 hello world
是新增的。
另一个常用的 diff 比较:工作区与版本库最新提交的差异
如果你想直接看工作区的文件和版本库里最新提交的版本有什么不同,可以使用 git diff HEAD -- [文件名]
命令:
# 查看工作区 ReadMe 文件和版本库最新提交版本 ReadMe 文件的差异
git diff HEAD -- ReadMe
这个命令会比较你当前工作区的状态和 HEAD
指针指向的那个提交(也就是当前分支的最新版本)的文件状态。了解这个有助于你区分工作区和暂存区在 diff 命令中的不同作用。
提交修改后的文件
现在我们知道了 ReadMe
被修改了,并且通过 git diff
确认了修改内容。接下来,按照流程,把这个修改也保存到版本库中。
第一步:将修改添加到暂存区 (git add
)
虽然文件是修改,不是新增,但流程一样,还是要先 add
到暂存区:
zz@139-159-150-152:~/gitcode$ git add ReadMe
执行 git add ReadMe
后,ReadMe
文件在工作区里的修改就被添加到了暂存区。暂存区里现在包含了 ReadMe
文件修改后的新内容。
再次查看状态 (git status
):
现在 ReadMe
的修改已经在暂存区了,我们再看看状态:
zz@139-159-150-152:~/gitcode$ git status
On branch master
Changes to be committed:(use "git restore --staged <file>..." to unstage)modified: ReadMe
这次的输出变了!ReadMe
文件出现在了 Changes to be committed:
这个区域下,并且前面显示 modified: ReadMe
。这表明 ReadMe
文件在暂存区里有改动,这些改动已经准备好被提交到版本库了。
第二步:将暂存区内容提交到版本库 (git commit
)
暂存区里有内容了,我们就可以执行 commit
命令来保存这个修改版本了:
# 提交暂存区的修改到版本库,并写上提交信息
zz@139-159-150-152:~/gitcode$ git commit -m "add modify ReadMe file"
[master 94da695] add modify ReadMe file1 file changed, 2 insertions(+), 1 deletion(-) # 这次修改的结果:1 个文件改动,增加了 2 行,删除了 1 行
提交成功!ReadMe
文件的这次修改已经被作为一个新的版本永久保存在版本库里了。
最后查看状态 (git status
):
提交完成后,工作区和暂存区都应该是干净的(和版本库最新提交的状态一致)。
zz@139-159-150-152:~/gitcode$ git status
On branch master
nothing to commit, working tree clean
nothing to commit, working tree clean
:这说明当前工作区和暂存区都没有任何需要提交的改动,它们的状态是干净的,和版本库里最新的版本是同步的。这是一个很好的状态!
总结一下 Git 的基本操作流程
通过上面的学习,我们现在对 Git 的基本操作流程有了清晰的认识:
- 在工作区里工作: 新建、编辑、删除文件。
- 查看状态: 经常使用
git status
查看工作区和暂存区的状态,了解哪些文件有改动,它们处于哪个阶段。 - 查看具体改动: 使用
git diff [文件名]
查看工作区里的文件相对于暂存区的具体修改内容。 - 将改动添加到暂存区: 使用
git add [文件名]
或git add .
将工作区中准备提交的改动放入暂存区。 - 提交暂存区的改动: 使用
git commit -m "有意义的提交信息"
将暂存区的内容作为一个新版本提交到版本库。 - 查看历史: 使用
git log
查看已经提交的版本历史。
理解工作区 -> 暂存区 -> 版本库 这个流程,以及 git add
和 git commit
在其中扮演的角色,是掌握 Git 的关键。每次改动都需要经过 add
和 commit
两步(或类似操作)才能真正被 Git 永久记录下来。
接下来,我们将继续学习 Git 的其他常用操作,比如如何回退版本,如何忽略文件等等。
相关文章:
[Git] 认识 Git 的三大区域 文件的修改和提交
文章目录 认识 Git 的三大区域:工作区、暂存区、版本库工作区、暂存区、版本库的关系流程图解 (概念) 将文件添加到仓库进行管理:git add 和 git commit场景一:第一次添加文件到仓库查看提交历史:git log(进阶理解&…...
交叉编译DirectFB报错解决方法
configure: error: *** DirectFB compilation requires fluxcomp *** Unless you are compiling from a distributed tarball you need fluxcomp available from git://git.directfb.org/git/directfb/core/flux installed in your PATH. 需要先编译安装flux git clone http…...
AllToAll通信为什么用于EP并行?
1 AllToAll通信原理 首先要明白ALLTOALL通信是做了什么事情。 假设我们有3个进程(A、B、C),每个进程都有三段数据,分别是a1, a2, a3;b1, b2, b3;c1, c2, c3。 进程A想发送:a1到进程A自己&…...
深入掌握Node.js HTTP模块:从开始到放弃
文章目录 一、HTTP模块入门:从零搭建第一个服务器1.1 基础概念解析1.2 手把手创建服务器 二、核心功能深入解析2.1 处理不同请求类型2.2 实现文件下载功能 三、常见问题解决方案3.1 跨域问题处理3.2 防止服务崩溃3.3 调试技巧 四、安全最佳实践4.1 请求头安全设置4.…...
python安装与使用
Python的安装 1.官网下载python安装包 https://www.python.org/ 2.安装python 勾选add python 3.8 to api将python加入变量 选择Customize installation进行自定义安装 一直选next直到下面界面,根据自己需要将python安装到指定位置,然后install 等贷…...
2025最新版Visual Studio Code for Mac安装使用指南
2025最新版Visual Studio Code for Mac安装使用指南 Installation and Application Guide to The Latest Version of Visual Studio Code in 2025 By JacksonML 1. 什么是Visual Studio Code? Visual Studio Code,通常被称为 VS Code,是由…...
VSCode GitHub Copilot 安装与使用完全指南
文章目录 一、安装准备1.1 系统要求1.2 Copilot订阅选择1.3 获取访问权限 二、安装步骤2.1 安装GitHub Copilot基础扩展2.2 安装GitHub Copilot Chat扩展2.3 登录和授权 三、基本使用:代码自动完成3.1 内联代码建议3.2 自定义Copilot配置3.3 使用注释引导Copilot 四…...
Github超19k+ strar的实时协同编辑的开源框架yjs
Yjs 是一个用于实现实时协同编辑的开源框架,具有以下关键特性和应用价值: 核心特性 基于 CRDT 算法 Yjs 采用无冲突复制数据类型(CRDT),确保多用户同时编辑同一文档时无需复杂锁机制或中央协调,最终实现数据…...
【Node.js】工具链与工程化
个人主页:Guiat 归属专栏:node.js 文章目录 1. Node.js 工具链概述1.1 工具链的作用1.2 Node.js 工具链全景 2. 包管理与依赖管理2.1 npm (Node Package Manager)2.2 yarn2.3 pnpm2.4 锁文件与依赖管理2.5 工作空间与 Monorepo 3. 构建工具与打包3.1 Web…...
OceanBase数据库全面指南(函数篇)函数速查表
文章目录 一、数学函数1.1 基本数学函数1.2 三角函数二、字符串函数2.1 基本字符串函数2.2 高级字符串处理函数三、日期时间函数3.1 基本日期时间函数3.2 日期时间计算函数四、聚合函数4.1 常用聚合函数4.2 分组聚合4.3 高级聚合函数五、条件判断函数5.1 基本条件函数5.2 CASE表…...
Chrome 缓存文件路径
Chrome 缓存文件路径查看方法 启动 Chrome 浏览器, 输入 Chrome://Version Google浏览器版本号以及安装路径 Windows 缓存目录 在 “运行” 中输入 %TEMP% 可打开, 一般路径是: C:\Users\Administrator\AppData\Local\Temp, 其中 Administrator 是用户名。 Windows 目录…...
Ubuntu Desktop 24.04 常用软件安装步骤
文章目录 Ubuntu Desktop 24.04 常用软件安装步骤Snipaste F1快捷截图(超方便 | 我6台电脑每台都用)搜狗输入法快速浏览工具 | 空格键快速预览文件壁纸工具 | varietySSH 工具 | Termius 终端分屏工具 | TmuxCaffeine | 避免息屏小工具 一些设置将启动台…...
Chrome 插件网络请求的全面指南
在 Chrome 插件开发中,网络请求可以在多个上下文中实现,而不仅限于 background.js 和 content.js。以下是完整的网络请求实现方案: 一、主要请求实现位置 1. Background Script (后台脚本) 特点: 生命周期最长适合处理敏感数据…...
SpringBoot Day_03
目录 一、数据校验 二、统一异常处理 1、局部异常处理(少) 2、全局异常处理(多) 三、定时器 四、springboot日志 五、swagger 六、springboot自动装配原理 总结 1、如何实现参数校验功能(掌握) …...
Ubuntu 新建用户
在 Ubuntu 22.04 中创建新用户并赋予 root 权限的步骤如下,综合多篇文档推荐的安全方法: 一、创建新用户 使用 adduser 命令创建用户 sudo adduser your_username系统会提示设置密码及填写用户信息(全名、电话等,可直接回车跳过&a…...
从法律视角看湖北理元理律师事务所的债务优化实践
债务问题解决需要专业法律支持。本文将从实务角度,解析湖北理元理律师事务所在债务优化领域的工作方法,为有需要的读者提供参考。 一、法律框架下的债务重组 利率合法性审查 识别超过法定上限的利息部分 收集相关证据材料 启动协商或诉讼程序 还款…...
# JavaSE核心知识点02面向对象编程
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 JavaSE核心知识点02面向对象编程JavaSE核心知…...
从原理到实践:一文详解残差网络
在深度学习的发展历程中,神经网络的深度一直是提升模型性能的关键因素之一。随着网络层数的增加,模型理论上可以学习到更复杂、更抽象的特征表示。然而,在实际训练过程中,研究人员发现,当网络深度达到一定程度后&#…...
把银河装进镜头里!动态星轨素材使用实录
仰望夜空时,神秘的银河与闪烁繁星总令人向往。如今,无需复杂拍摄,借助素材平台就能将绝美星轨融入创作,今天重点安利 制片帮素材! 动态星轨:宇宙的浪漫印记 星轨是地球自转时,星星运动留下的轨…...
C++23中std::span和std::basic_string_view可平凡复制提案解析
文章目录 一、引言二、相关概念解释2.1 平凡复制(Trivially Copyable)2.2 std::span2.3 std::basic_string_view 三、std::span和std::basic_string_view的应用场景3.1 std::span的应用场景3.2 std::basic_string_view的应用场景 四、P2251R1提案对std::…...
【KWDB 2025 创作者计划】_KWDB时序数据库特性及跨模查询
一、概述 数据库的类型多种多样,关系型数据库、时序型数据库、非关系型数据库、内存数据库、分布式数据库、图数据库等等,每种类型都有其特定的使用场景和优势,KaiwuDB 是一款面向 AIoT 场景的分布式、多模融合、支持原生 AI 的数据库…...
树 Part 9
二叉树的建立 了解了二叉树的遍历方法,我们如何在内存中生成一棵二叉链表的二叉树呢?树都没有,哪来遍历。所以我们还得来谈谈关于二叉树建立的问题。 如果要在内存中建立一个如左图这样的树,为了能让每个结点确认是否有左右孩子…...
leetcode每日一题 -- 3362. 零数组变换 III
思路 题意是要找出[最少的区间]使nums数组变为零数组,并且使用的区间可以不连续 我的第一想法是先给区间按照左边界排序(就像区间合并题的准备工作那样)这样的可以使用最大堆,每次将右区间值最大(也就是区间范围最大)的区间应用到差分数组中但是,后续如何处理还是不太会,遂看…...
PARSCALE:大语言模型的第三种扩展范式
----->更多内容,请移步“鲁班秘笈”!!<----- 随着人工智能技术的飞速发展,大语言模型(LLM)已成为推动机器智能向通用人工智能(AGI)迈进的核心驱动力。然而,传统的…...
【 开源:跨平台网络数据传输的万能工具libcurl】
在当今这个互联互通的世界中,数据在各种设备和平台之间自由流动,而 libcurl,就像一把跨平台的万能工具,为开发者提供了处理各种网络数据传输任务所需的强大功能。它不仅是一个库,更是一种通用的解决方案,可…...
2025版 JavaScript性能优化实战指南从入门到精通
JavaScript作为现代Web应用的核心技术,其性能直接影响用户体验。本文将深入探讨JavaScript性能优化的各个方面,提供可落地的实战策略。 一、代码层面的优化 1. 减少DOM操作 DOM操作是JavaScript中最昂贵的操作之一: // 不好的做法&#x…...
RAGFlow知识检索原理解析:混合检索架构与工程实践
一、核心架构设计 RAGFlow构建了四阶段处理流水线,其检索系统采用双路召回+重排序的混合架构: S c o r e f i n a l = α ⋅ B M...
leetcode 148. Sort List
148. Sort List 题目描述 代码: /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNod…...
C#学习11——集合
一、集合 是一组对象的容器,提供了高效的存储、检索和操作数据的方式。 C# 集合分为泛型集合(推荐使用)和非泛型集合,主要位于System.Collections和System.Collections.Generic命名空间中。 二、集合有哪些? 1&…...
paddlehub搭建ocr服务
搭建环境: Ubuntu20.041080Ti显卡 由于GPU硬件比较老,是Pascal架构,只能支持到paddle2.4.2版本,更高版本无法支持;同时,因为paddle老版本的依赖发生了变化,有些地方存在冲突,花费了…...
CSS3过渡
一、什么是CSS3过渡 CSS3 过渡(transitions)是一种效果,它允许你平滑地改变CSS属性的值,从一个状态过渡到另一个状态。是一种动画转换的过程,如渐现、渐弱、动画快慢等。过渡效果可以在用户与页面进行交互时触发&#…...
比斯特自动化|移动电源全自动点焊机:高效点焊助力移动电源制造
在移动电源市场蓬勃发展的当下,电池组合的点焊工艺要求愈发严格。移动电源全自动点焊机应运而生,成为提升生产效率与产品质量的关键设备。 工作原理与结构组成 移动电源全自动点焊机通过瞬间放电产生高温,使电池极耳与镍带等材料在极短时间…...
游戏引擎学习第305天:在平台层中使用内存 Arena 的方法与思路
回顾前一天内容,并为今天的开发工作设定方向 我们正在直播制作完整游戏,当前正在实现一个精灵图(sprite graph)的排序系统。排序的代码已经写完,过程并不复杂,虽然还没做太多优化,但总体思路比…...
[Java][Leetcode middle] 6. Z 字形变换
法一,自己想的 使用一个复合结构的 List<ArrayList<String>> 来存储每一行的字母,最后按序输出。 使用flag来判断到底放到哪一行上去。flag按照:0–1–2–1–0–1–2这样变化,实现躺着的Z字形。 public String conve…...
零基础设计模式——第二部分:创建型模式 - 原型模式
第二部分:创建型模式 - 5. 原型模式 (Prototype Pattern) 我们已经探讨了单例、工厂方法、抽象工厂和生成器模式。现在,我们来看创建型模式的最后一个主要成员——原型模式。这种模式关注的是通过复制现有对象来创建新对象,而不是通过传统的…...
完整改进RIME算法,基于修正多项式微分学习算子Rime-ice增长优化器,完整MATLAB代码获取
1 简介 为了有效地利用雾状冰生长的物理现象,最近开发了一种优化算法——雾状优化算法(RIME)。它模拟硬雾状和软雾状过程,构建硬雾状穿刺和软雾状搜索机制。在本研究中,引入了一种增强版本,称为修改的RIME…...
【1——Android端添加隐私协议(unity)1/3】
前言:这篇仅对于unity 发布Android端上架国内应用商店添加隐私协议,隐私协议是很重要的东西,没有这个东西,是不上了应用商店的。 对于仅仅添加隐私协议,我知道有三种方式,第一种和第二种基本一样 1.直接在unity里面新…...
笔记本6GB本地可跑的图生视频项目(FramePack)
文章目录 (一)简介(二)本地执行(2.1)下载(2.2)更新(2.3)运行(2.4)生成 (三)注意(3.1)效…...
Android View的事件分发机制
ViewGroup的事件分发逻辑 从Activity传递给Window,再传递给ViewGroup,ViewGroup的dispatchTouchEvent()会被调用,如果onInterceptTouchEvent()返回true 转交自身onTouchEvent()处理,如果返回false继续向子View传递,子View的dispatchTouchEve…...
Python字符串格式化(二): f-string的进化
文章目录 一、Python 3.6:重新发明字符串格式化(2016)1. 语法糖的诞生:表达式直嵌技术2. 性能与可读性的双重提升3. 奠定现代格式化的基础架构 二、Python 3.7:解锁异步编程新场景(2018)1. 异步…...
力扣HOT100之二叉树:124. 二叉树中的最大路径和
这道题是困难题,靠自己想还是挺难想的,还是去看的灵神的题解,感觉还是要多复习一下这道题。这道题的思路和之前做的543. 二叉树的直径很像,可以参考之前的这篇博客。这里我们还是用递归来做,定义一个lambda函数来实现递…...
【C++】位图+布隆过滤器
1.位图 概念 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的或是否被标记。 1.二进制位表示 : 位图中的每一位(bit)代表一个元素的状态。通常&…...
Google Agent Development Kit与MCP初试
Google Agent Development Kit与MCP初试 一、背景知识二、搭建智能大脑 - Ollama服务器2.1 为什么要先搭建Ollama?2.2 搭建ollama服务器2.2.1 安装2.2.2 试着用curl命令"问"AI一个问题: 三、构建智能体工坊 - ADK环境3.1 创建容器3.2 安装核心…...
云原生+大数据
虚拟化: 虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提…...
基于cornerstone3D的dicom影像浏览器 第二十一章 显示DICOM TAGS
系列文章目录 第一章 下载源码 运行cornerstone3D example 第二章 修改示例crosshairs的图像源 第三章 vitevue3cornerstonejs项目创建 第四章 加载本地文件夹中的dicom文件并归档 第五章 dicom文件生成png,显示检查栏,序列栏 第六章 stack viewport 显…...
【记录】PPT|PPT打开开发工具并支持Quicker VBA运行
文章目录 打开开发者工具支持Quicker VBA运行 打开开发者工具 参考文章,微软文档:显示“开发工具”选项卡,以下直接复制,如侵私删。 适用对象:Microsoft 365 专属 Excel Microsoft 365 专属 Outlook Microsoft 365 专属…...
西门子 S1500 博途软件舞台威亚 3D 控制方案
西门子 S1500 PLC 是工业自动化领域的主流控制器,适合高精度、高可靠性的舞台威亚控制。下面为你提供基于博途 (TIA Portal) 软件的 3D 控制方案设计。 系统架构设计 舞台威亚 3D 控制系统通常包含以下组件: 硬件层: S1500 PLC 主机伺服驱动…...
第三十二天打卡
import pandas as pd from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier # 加载鸢尾花数据集 iris load_iris() df pd.DataFrame(iris.data, columnsiris.feature_names) …...
同步/异步电路;同步/异步复位
同步/异步电路;同步/异步复位 在 FPGA 设计中,同步电路、异步电路、同步复位和异步复位是基础且关键的概念,它们的特性直接影响电路的可靠性、时序性能和设计复杂度。 一、同步电路(Synchronous Circuit) 定义 同步电…...
spring boot 实现resp视频推流
1、搭建resp服务(docker方式) docker pull aler9/rtsp-simple-serverdocker run -d --restartalways \--name rtsp-server \-p 8554:8554 \aler9/rtsp-simple-server2、maven依赖 <dependency><groupId>org.bytedeco</groupId><a…...