当前位置: 首页 > news >正文

[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 主要涉及以下三个区域:

  1. 工作区(Working Directory)
    • 是什么? 就是你在电脑里,能直接看到、直接操作的那个项目文件夹。比如你在里面新建文件、修改代码,这些操作都是在工作区进行的。简单来说,这就是你正在工作的地方,你的“办公桌”。

  1. 暂存区(Staging Area / Index)
    • 是什么? 这是 Git 中一个非常核心且独特的概念。它不像工作区那样是一个看得见的文件夹,它更像一个目录清单或者一个中间“打包区”。当你觉得工作区里的某个文件修改好了,或者某个新文件要纳入 Git 管理了,你就可以用一个命令把这些改动“放”到暂存区里,表明“我这些改动已经准备好了,待会儿要一起保存”。
    • 在哪儿? 暂存区的信息通常存放在 Git 仓库目录(那个隐藏的 .git 文件夹)下的 index 文件里(路径是 .git/index)。所以,有时候人们也把暂存区叫做“索引”(Index)。可以想象成你的“打包盒子”,你把准备好一起提交的文件放进去。
  2. 版本库(Repository)
    • 是什么? 这就是 Git 用来永久存储你的项目历史版本的地方。它包含了所有提交过的版本数据,分支信息,以及 Git 管理项目所需的一切数据。
    • 在哪儿? 就是你项目文件夹里那个隐藏的 .git 文件夹。注意,这个 .git 文件夹不属于工作区!它是独立于工作区的版本库本身。版本库就像你的“仓库”或“档案室”,所有经过 commit 保存的版本都安全地存放在这里,随时可以追溯或恢复。
工作区、暂存区、版本库的关系流程图解 (概念)

想象一下,它们之间的关系就像这样:

+--------------+       +--------------+       +--------------+
|   工作区     | ----> |    暂存区    | ----> |    版本库    |
| (Working Dir)|       | (Staging Area)|       | (Repository) |
+--------------+       +--------------+       +--------------+(你的办公桌)       (准备提交的区域)    (历史版本仓库)^                     ^                     ||                     |                     |+---------------------+---------------------+(可以从版本库或暂存区恢复到工作区)
  • 你所有的文件修改都首先发生在工作区
  • 当你觉得某一部分修改完成了,需要先 git add 把这些改动从工作区添加到暂存区
  • 当你觉得暂存区里的内容(也就是你通过 git add 累积起来的所有改动)都准备好作为一个完整的历史版本保存时,需要 git commit暂存区的内容提交版本库

重点来了!

你仅仅在工作区新建了一个文件,或者修改了工作区里的文件,对于 Git 的版本库来说,它是不知道的!这些改动没有被 Git 跟踪起来。

通过新建或粘贴进⽬录的⽂件,并不能称之为向仓库中新增⽂件,⽽只是在⼯作区新增了⽂件。必须要通过使⽤git addgit commit 命令才能将⽂件添加到仓库中进⾏管理!!

要让 Git 开始管理这些文件和改动,你必须完成从工作区 -> 暂存区 -> 版本库 的这个流程,也就是依次使用 git add 命令和 git commit 命令!

将文件添加到仓库进行管理:git addgit commit

理解了“三区”的概念,我们就知道 Git 跟踪和保存文件的基本步骤是:

  1. 在工作区对文件进行修改或新增。
  2. 使用 git add 命令将工作区的改动添加到暂存区
  3. 使用 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 目录里的变化。在我们执行了几次 addcommit 后,.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 目录下的文件夹和文件可能不同,因为它们是根据你的具体提交内容生成的。

这里面有几个关键文件/目录,和我们的操作密切相关:

  1. .git/index: 这就是暂存区!每次执行 git add 命令,Git 都会更新这个文件,记录下当前暂存区的文件状态和对应的对象信息。
  2. .git/HEAD: 这是一个指针,默认情况下,它指向你当前所在的分支(比如 mastermain)。
# 查看 HEAD 指向
zz@139-159-150-152:~/gitcode$ cat .git/HEAD
ref: refs/heads/master # 表示 HEAD 指向 refs/heads/master
  1. .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
  1. .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 addgit commit 都会在这个对象库中创建新的对象。这有助于我们理解 Git 是如何保存项目历史的。

总结 .git 内部的几个重要部分:

  • index: 暂存区的实际文件,git add 的结果保存在这里。
  • HEAD: 指向当前所在分支(默认是 mastermain)的指针
  • refs/heads/master: 一个文件,里面存储着 master 分支最新提交的 commit id
  • objects: Git 的对象数据库,存放所有 Git 管理的对象(文件内容、目录树、提交等)。

在今后的学习中,试着将常用的 Git 命令和 .git 目录内部的变化联系起来,每次操作后都进行回想“这时候目录内部的操作”,可以帮助你更深刻地理解 Git 的工作原理。

场景二:再次理解 addcommit 的配合

为了加深对工作区、暂存区、版本库以及 addcommit 命令关系的理解,我们再看一个例子:

# 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)!这是怎么回事?我们明明新增了两个文件 (file4file5) 啊?

原因: 回忆一下我们前面说的,git commit 提交的是暂存区里的内容。在执行 git commit 命令时:

  • file4 已经通过 git add file4 被添加到了暂存区。
  • file5 虽然在工作区被创建了,但我们没有对它执行 git add file5,所以它还在工作区,没有进入暂存区。

因此,git commit 时只看到了暂存区里的 file4,就把 file4 提交了,而完全忽略了还在工作区的 file5

如何提交 file5 呢? 非常简单,按照流程来:先 git add file5file5 加到暂存区,然后再 git commit 一次。

这个例子再次强调用 commit 提交的是暂存区,而不是工作区!在你 commit 之前,一定要确保所有想提交的改动都已经通过 git add 进入了暂存区。

修改文件并提交:git statusgit 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 的基本操作流程有了清晰的认识:

  1. 在工作区里工作: 新建、编辑、删除文件。
  2. 查看状态: 经常使用 git status 查看工作区和暂存区的状态,了解哪些文件有改动,它们处于哪个阶段。
  3. 查看具体改动: 使用 git diff [文件名] 查看工作区里的文件相对于暂存区的具体修改内容。
  4. 将改动添加到暂存区: 使用 git add [文件名]git add . 将工作区中准备提交的改动放入暂存区。
  5. 提交暂存区的改动: 使用 git commit -m "有意义的提交信息" 将暂存区的内容作为一个新版本提交到版本库。
  6. 查看历史: 使用 git log 查看已经提交的版本历史。

理解工作区 -> 暂存区 -> 版本库 这个流程,以及 git addgit commit 在其中扮演的角色,是掌握 Git 的关键。每次改动都需要经过 addcommit 两步(或类似操作)才能真正被 Git 永久记录下来。

接下来,我们将继续学习 Git 的其他常用操作,比如如何回退版本,如何忽略文件等等。

http://www.xdnf.cn/news/580015.html

相关文章:

  • linux杀死进程自身
  • Docker实战
  • docker network 自定义网络配置与管理指南
  • 数字孪生技术如何重塑能源产业?
  • 生成树协议(STP)配置详解:避免网络环路的最佳实践
  • java基础(api)
  • 第八天的尝试
  • 印度语言指令驱动的无人机导航!UAV-VLN:端到端视觉语言导航助力无人机自主飞行
  • AllToAll通信为什么用于EP并行?
  • Linux性能监控工具nmon
  • 【开源解析】基于深度学习的双色球预测系统:从数据获取到可视化分析
  • Axure系统原型设计首页模版方案
  • InetAddress 类详解
  • AI大模型技术全景解析:核心原理与关键技术拆解
  • 【C++ 真题】P5736 【深基7.例2】质数筛
  • HJ23 删除字符串中出现次数最少的字符【牛客网】
  • 《Effective Java(第三版)》笔记
  • ESP32-S3 (ESP IDF 5.4.1 - LVGL 9.2.0)九宫格拼音输入法
  • 工业控制解决方案三段论
  • Java 实现四种单例(都是线程安全)
  • 【Linux】了解 消息队列 system V信号量 IPC原理
  • 常见字符串相似度算法详解
  • 使用Pandoc实现Markdown和Word文档的双向转换
  • 基于LiveData和ViewModel的路线管理实现(带PopupWindow删除功能)
  • 人工智能价值:技术革命下的职业新坐标
  • 【java】Java注解
  • 通信协议详解(分层技术解析)
  • 4-码蹄集600题基础python篇
  • 16、Python运算符全解析:位运算实战、字符串拼接与列表合并技巧
  • 如何在电脑上登录多个抖音账号?多开不同IP技巧分解