理解 Git 的三个工作区:工作区、暂存区和版本库

文章目录

创建 Git 本地仓库

要提前说的是,仓库是进⾏版本控制的⼀个⽂件⽬录。我们要想对⽂件进⾏版本控制,就必须先创建⼀个仓库出来。创建⼀个 Git 本地仓库对应的命令为 git init ,注意命令要在⽂件⽬录下执⾏,例如:

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ pwd
/home/XMLife/Git_code
[XMLife@VM-8-6-centos Git_code]$ git init
Initialized empty Git repository in /home/XMLife/Git_code/.git/
[XMLife@VM-8-6-centos Git_code]$ ll -a
total 12
drwxrwxr-x 3 XMLife XMLife 4096 Sep 19 09:30 .
drwx------ 5 XMLife XMLife 4096 Sep 19 09:29 ..
drwxrwxr-x 7 XMLife XMLife 4096 Sep 19 09:30 .git

我们发现,当前⽬录下多了⼀个 .git 的隐藏⽂件, .git ⽬录是 Git 来跟踪管理仓库的,不要⼿动

修改这个⽬录⾥⾯的⽂件,不然改乱了,就把 Git 仓库给破坏了.如果大家感兴趣可以打开看看.


配置Git

当首次安装配置 Git 后⾸先要做的事情是设置自己的 ⽤⼾名称e-mail 地址,这是⾮常重要的。如果忘记配置会出现不必要的问题,配置命令为

cpp 复制代码
git config [--global] user.name "Your Name" 
git config [--global] user.email "email@example.com" 
# 把 Your Name 改成你的昵称
# 把 email@example.com 改成邮箱的格式,只要格式正确即可

其中 --global 是⼀个可选项。如果使⽤了该选项,表⽰这台机器上所有的 Git 仓库都会使⽤这个

配置。如果你希望在不同仓库中使⽤不同的 name 或 e-mail ,可以不要 --global 选项,但要

注意的是,执⾏命令时必须要在仓库⾥。

查看配置命令为:

c 复制代码
git config -l

删除对应的配置命令为:

c 复制代码
git config [--global] --unset user.name
git config [--global] --unset user.email

认识⼯作区、暂存区、版本库

  • ⼯作区:是在电脑上你要改动你的代码或⽂件的⽬录。
  • 暂存区:英⽂叫 stage 或 index。⼀般存放在 .git ⽬录下的 index ⽂件(.git/index)中,我们把暂存区有时也叫作索引(index)。
  • 版本库:⼜名仓库,英⽂名 repository 。⼯作区有⼀个隐藏⽬录 .git ,它不算⼯作区,⽽
    是 Git 的版本库。这个版本库⾥⾯的所有⽂件都可以被 Git 管理起来,每个⽂件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以"还原"。

下⾯这个图展⽰了⼯作区、暂存区和版本库之间的关系:

  • 图中左侧为⼯作区,右侧为版本库。Git 的版本库⾥存了很多东西,其中最重要的就是暂存区。
  • 在创建 Git 版本库时,Git 会为我们⾃动创建⼀个唯⼀的 master 分⽀,以及指向 master 的⼀个指针叫 HEAD。
  • 当对⼯作区修改(或新增)的⽂件执⾏ git add 命令时,暂存区⽬录树的⽂件索引会被更新。
  • 当执⾏提交操作 git commit 时,master 分⽀会做相应的更新,可以简单理解为暂存区的⽬录
    树才会被真正写到版本库中。

由上述描述我们便能得知:通过新建或粘贴进⽬录的⽂件,并不能称之为向仓库中新增⽂件,⽽只是在⼯作区新增了⽂件。必须要通过使⽤ git add 和 git commit 命令才能将⽂件添加到仓库中

进⾏管理!!!

  • Git 追踪管理的其实是修改,而不是文件

添加⽂件--场景

在包含 .git 的⽬录下新建⼀个 Fileme ⽂件,我们可以使⽤ git add 命令可以将⽂件添加到暂存区.

  • 添加⼀个或多个⽂件到暂存区: git add [file1] [file2] ...
  • 添加指定⽬录到暂存区,包括⼦⽬录: git add [dir]
  • 添加当前⽬录下的所有⽂件改动到暂存区: git add .

再使⽤ git commit 命令将暂存区内容添加到本地仓库中:

  • 提交暂存区全部内容到本地仓库中: git commit -m "message"
  • 提交暂存区的指定⽂件到仓库区: git commit [file1] [file2] ... -m "message"

注意 git commit 后⾯的 -m 选项,要跟上描述本次提交的 message,由⽤⼾⾃⼰完成,这部分内

容绝对不能省略,并要好好描述,是⽤来记录你的提交细节,是给我们开发人员看的.

git commit 命令执⾏成功后会告诉我们,1个⽂件被改动(就是我们新添加的ReadMe⽂件),插

⼊了两⾏内容(ReadMe有两⾏内容)。如下:

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ vim Fileme
[XMLife@VM-8-6-centos Git_code]$ cat Fileme
hello git
[XMLife@VM-8-6-centos Git_code]$ git add Fileme
[XMLife@VM-8-6-centos Git_code]$ git commit -m "commit my first file"
[master (root-commit) 05f37ff] commit my first file
 1 file changed, 1 insertion(+)
 create mode 100644 Fileme

我们还可以多次 add 不同的⽂件,⽽只 commit ⼀次便可以提交所有⽂件,是因为需要提交的⽂件是通通被 add 到暂存区中,然后⼀次性 commit 暂存区的所有修改。如下:

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ touch file1 file2 file3
[XMLife@VM-8-6-centos Git_code]$ git add file1 file2 file3
[XMLife@VM-8-6-centos Git_code]$ git commit -m "add 3 file"
[master 1f3d1a3] add 3 file
 3 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file1
 create mode 100644 file2
 create mode 100644 file3

截⾄⽬前为⽌,我们已经更够将代码直接提交⾄本地仓库了。我们可以使⽤ git log 命令,来查看下历史提交记录.如下:

cpp 复制代码
[XMLife@VM-8-6-centos Git_code]$ git log
commit 1f3d1a3b718a4eab4fb951808b20a9545cbd54a8
Author: XMLife <1277707726@qq.com>
Date:   Tue Sep 26 09:29:33 2023 +0800

    add 3 file

commit 05f37ff848941e9b4c53b0e8daf604f4e18c9f2f
Author: XMLife <1277707726@qq.com>
Date:   Tue Sep 26 08:46:37 2023 +0800

    commit my first file

该命令显⽰从最近到最远的提交⽇志,并且可以看到我们 commit 时的⽇志消息。

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上 --pretty=oneline 参数:如下:

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ git log --pretty=oneline
1f3d1a3b718a4eab4fb951808b20a9545cbd54a8 add 3 file
05f37ff848941e9b4c53b0e8daf604f4e18c9f2f commit my first file

需要说明的是,我们看到的⼀⼤串类似1f3d1a...05f37ff 的是每次提交的 commit id (版本

号),Git 的 commit id 不是1,2,3......递增的数字,⽽是⼀个 SHA1加密 计算出来的⼀个⾮常⼤的数字,⽤⼗六进制表⽰(你看到的 commit id 和我的肯定不⼀样,以你⾃⼰的为准)


查看 .git ⽂件

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ ll -al
total 16
-rw-rw-r-- 1 XMLife XMLife    0 Sep 26 09:28 file1
-rw-rw-r-- 1 XMLife XMLife    0 Sep 26 09:28 file2
-rw-rw-r-- 1 XMLife XMLife    0 Sep 26 09:28 file3
-rw-rw-r-- 1 XMLife XMLife   10 Sep 26 08:45 Fileme
drwxrwxr-x 8 XMLife XMLife 4096 Sep 26 09:29 .git

.git 是我们的版本库 (仓库)

其余文件是我们的工作区.

先来看看我们的 .git 的⽬录结构:

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ tree .git/
.git/
|-- branches
|-- COMMIT_EDITMSG
|-- config
|-- description
|-- HEAD
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- prepare-commit-msg.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|       `-- heads
|           `-- master
|-- objects
|   |-- 05
|   |   `-- f37ff848941e9b4c53b0e8daf604f4e18c9f2f
|   |-- 1f
|   |   `-- 3d1a3b718a4eab4fb951808b20a9545cbd54a8
|   |-- 2a
|   |   `-- 318fbaab981ff723a3621e39c862bbfa0b8082
|   |-- 8d
|   |   `-- 0e41234f24b6da002d962a26c2495ea16a425f
|   |-- e6
|   |   `-- 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
|   |-- ef
|   |   `-- 877764d92409acd539cdf1408ddb8e859d7785
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    |   `-- master
    `-- tags

18 directories, 24 files
  1. index 就是我们的暂存区,add 后的内容都是添加到这⾥的.
  2. HEAD 就是我们的默认指向 master 分⽀的指针.
c 复制代码
[XMLife@VM-8-6-centos Git_code]$ cat .git/HEAD
ref: refs/heads/master

⽽默认的 master 分⽀,其实就是

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ cat .git/refs/heads/master
1f3d1a3b718a4eab4fb951808b20a9545cbd54a8

打印的 1f3d1a3b718a4eab4fb951808b20a9545cbd54a8是什么东西呢?保存的就是当前最新的 commit id

  1. objects 为 Git 的对象库,⾥⾯包含了创建的各种版本库对象及内容。当执⾏ git add 命令
    时,暂存区的⽬录树被更新,同时⼯作区修改(或新增)的⽂件内容被写⼊到对象库中的⼀个新的对象中,就位于 ".git/objects" ⽬录下,让我们来看看这些对象有何⽤处:
cpp 复制代码
[XMLife@VM-8-6-centos Git_code]$ ls .git/objects/
05  1f  2a  8d  e6  ef  info  pack

查找 object 时要将 commit id 分成2部分,其前2位是⽂件夹名称,后38位是⽂件名称。

找到这个⽂件之后,⼀般不能直接看到⾥⾯是什么,该类⽂件是经过 sha (安全哈希算法)加密过的⽂件,好在我们可以使⽤ git cat-file 命令来查看版本库对象的内容:

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ git cat-file -p 1f3d1a3b718a4eab4fb951808b20a9545cbd54a8

tree ef877764d92409acd539cdf1408ddb8e859d7785
parent 05f37ff848941e9b4c53b0e8daf604f4e18c9f2f
author XMLife <1277707726@qq.com> 1695691773 +0800
committer XMLife <1277707726@qq.com> 1695691773 +0800

add 3 file

# 这就是我们最近⼀次的提交!

其中,还有⼀⾏ tree ef877764d92409acd539cdf1408ddb8e859d7785 ,我们使⽤同样的⽅

法,看看结果:

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ git cat-file -p ef877764d92409acd539cdf1408ddb8e859d7785
100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f	Fileme
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	file1
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	file2
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	file3

在看 Fileme 对应的 8d0e41234f24b6da002d962a26c2495ea16a425f :

cpp 复制代码
[XMLife@VM-8-6-centos Git_code]$ git cat-file -p 8d0e41234f24b6da002d962a26c2495ea16a425f
hello git
# 这是我们对ReadMe做的修改!!被git记录了下来!!

回过头我们在看看 parent 05f37ff848941e9b4c53b0e8daf604f4e18c9f2f

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ git cat-file -p 05f37ff848941e9b4c53b0e8daf604f4e18c9f2f
tree 2a318fbaab981ff723a3621e39c862bbfa0b8082
author XMLife <1277707726@qq.com> 1695689197 +0800
committer XMLife <1277707726@qq.com> 1695689197 +0800

commit my first file

他保存的是我们上一次提交的记录

  • 总结
    在本地的 git 仓库中,有⼏个⽂件或者⽬录很特殊
  • index: 暂存区, git add 后会更新该内容。
  • HEAD: 默认指向 master 分⽀的⼀个指针。
  • refs/heads/master: ⽂件⾥保存当前 master 分⽀的最新 commit id 。
  • objects: 包含了创建的各种版本库对象及内容,可以简单理解为放了 git 维护的所有修改。

添加⽂件--场景⼆

我们已经清楚了如何向仓库中添加⽂件,并且对于⼯作区、暂存区、版本库也有了⼀定

的认识。那么我们再展⽰⼀种添加⽂件的场景,能加深对⼯作区、暂存区、版本库.

c 复制代码
[XMLife@VM-8-6-centos Git_code]$ touch file4
[XMLife@VM-8-6-centos Git_code]$ git add file4
[XMLife@VM-8-6-centos Git_code]$ touch file5
[XMLife@VM-8-6-centos Git_code]$ git commit -m "add file"
[master bcadde4] add file
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file4

提交后发现打印了 1 file changed, 0 insertions(+), 0 deletions(-) ,意思是只有⼀个⽂件改变了,这时我们提出了疑问,不是新增了两个⽂件吗?

再来回忆下, git add 是将⽂件添加到暂存区, git commit 是将暂存区的内容添加到本地仓库

中。由于我们并没有使⽤ git add file5 ,file5 就不在暂存区中维护,所以我们 commit 的时候

其实只是把已经在暂存区的 file4 提交了,⽽遗漏了⼯作区的 file5。如何提交 file5 呢?很简单,再次add , commit 即可,

相关推荐
Smile丶凉轩12 小时前
微服务即时通讯系统的实现(服务端)----(1)
c++·git·微服务·github
和你一起去月球21 小时前
TypeScript - 函数(下)
javascript·git·typescript
我不是程序猿儿1 天前
【GIT】TortoiseGit的变基(Rebase)操作
git
yyycqupt1 天前
git使用(一)
git
Kkooe1 天前
GitLab|数据迁移
运维·服务器·git
Beekeeper&&P...1 天前
git bash是什么,git是什么,git中的暂存区是什么,git中的本地仓库是什么,git中工作目录指的是什么
开发语言·git·bash
Stara05112 天前
Git推送+拉去+uwsgi+Nginx服务器部署项目
git·python·mysql·nginx·gitee·github·uwsgi
lsswear2 天前
GIT 操作
git