【Git#1】初识 git(配置 & 基本认识 & 文件操作)
一、前言
在工作或学习时经常遇到这样的情况:我们在编写各种文档时,为了防止文档丢失,更改失误,失误后能恢复到原来的版本,不得不复制出一个副本,比如:
- “报告-v1”
- “报告-v2”
- “报告-v3”
- “报告-确定版”
- “报告-最终版”
每个版本有各自的内容,但最终会只有一份报告需要被我们使用。但在此之前的工作都需要这些不同版本的报告,于是每次都是复制粘贴副本,产出的文件就越来越多,文件多不是问题,问题是:随着版本数量的不断增多,你还记得这些版本各自都是修改了什么吗? 文档如此,我们写的项目代码,也是存在这个问题的!!
如何解决–版本控制器
为了能够更方便我们管理这些不同版本的文件,便有了版本控制器。所谓的版本控制器,就是能让你了解到一个文件的历史,以及它的发展过程的系统。通俗的讲就是一个可以记录工程的每一次改动和版本迭代的一个管理系统,同时也方便多人协同作业
最主流的版本控制器就是 Git
- Git 可以控制电脑上所有格式的文件,例如 doc、excel、dwg、dgn、rvt等等。对于我们开发人员来说,Git最重要的就是可以帮助我们管理软件开发项目中的源代码文件!
注意事项
还需要再明确一点,所有的版本控制系统,Git 也不例外,其实只能跟踪文本文件的改动,比如 TXT 文件,网页,所有的程序代码等等。
- 版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
Git 安装
- Git 是开放源代码的代码托管工具,最早是在Linux下开发的。开始也只能应用于Linux平台,后面慢慢的被移植到windows下,现在,Git可以在Linux、Unix、Mac和Windows这几大平台上正常运行了。
如果你的的平台是ubuntu,安装git相当简单,以我的ubuntu20.04为例
- 首先,你可以试着输入git,看看系统有没有安装Git:
$ git
Command 'git'not found, but can be installed with:
sudo apt install git
- 出现像上面的结果,Linux会友好地告诉你Git没有安装,还会告诉你如何安装Git。安装 Git:
sudo apt-get install git -y
- 查看 git 版本
git --version
二、git 基本操作
1. 创建 Git 本地仓库
要提前说的是,仓库是进行版本控制的一个文件目录。我们要想对文件进行版本控制,就必须先创建一个仓库出来。
创建一个 Git 本地仓库对应的命令为 git init
,注意命令要在文件目录下执行,例如:
lighthouse@VM-8-10-ubuntu:gitcode$ git init
Initialized empty Git repository in /home/lighthouse/code/gitcode/.git/
lighthouse@VM-8-10-ubuntu:gitcode$ ll
total 12
drwxrwxr-x 3 lighthouse lighthouse 4096 Apr 7 10:02 ./
drwxrwxr-x 7 lighthouse lighthouse 4096 Apr 7 09:49 ../
drwxrwxr-x 7 lighthouse lighthouse 4096 Apr 7 10:02 .git/
注意:当我们在一个目录下初始化git时 可能会出现下面这个提示
代码语言:javascript代码运行次数:0运行复制lighthouse@VM-8-10-ubuntu:gitcode$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/lighthouse/code/gitcode/.git/
解决方案:一般情况下 我们先设置默认分支为master级别
代码语言:javascript代码运行次数:0运行复制git config --global init.defaultBranch master
我们发现,当前目录下多了一个.git 的隐藏文件,.git
目录是 Git 来跟踪管理仓库,不要手动修改这个目录里面的文件,不然改乱了,就把 Git 仓库给破坏了。其中包含 Git 仓库的诸多细节
lighthouse@VM-8-10-ubuntu:gitcode$ tree .git/
.git/
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
9 directories, 17 files
2. 配置 git
当安装 Git 后首先要做的事情是设置你的 用户名称 和 e-mail 地址,这是非常重要的。配置命令为:
代码语言:javascript代码运行次数:0运行复制git config [--global] user.name "Your Name"
git config [--global] user.email "email@example"
# 把 Your Name 改成你的昵称
# 把 email@example 改成邮箱的格式,只要格式正确即可。
其中 --global
是一个可选项。如果使用了该选项,表示这台机器上所有的 Git 仓库都会使用这个配置。如果你希望在不同仓库中使用不同的 name或,e-mail,可以不要 --global
选项,但要注意的是,执行命令时必须要在仓库里。
查看配置命令为:
git config -l
删除对应的配置命令为:
代码语言:javascript代码运行次数:0运行复制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分支会做相应的更新,可以简单理解为:此时暂存区的目录树才会被真正写到版本库中
四、文件操作
1. 添加文件 – 场景一
在包含 .git
的目录下新建一个文件,我们可以使用 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,由用户自己完成,这部分内容绝对不能省略,并要好好描述,是用来记录你的提交细节,是给我们人看的
案例如下:
代码语言:javascript代码运行次数:0运行复制lighthouse@VM-8-10-ubuntu:gitcode$ touch book
lighthouse@VM-8-10-ubuntu:gitcode$ vim book
lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
lighthouse@VM-8-10-ubuntu:gitcode$ git add book
lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "commit my first file"
[master (root-commit) dc24b53] commit my first file
1 file changed, 1 insertion(+)
create mode 100644 book
git commit
命令执行成功后会告诉我们,1个文件被改动(就是我们新添加的文件),插入了一行内容(说明:当前新增文件里面有一行内容)
我们还可以多次 add 不同的文件,而只 commit
一次便可以提交所有文件,
- 原因:需要提交的文件是通通被 add 到暂存区中,然后一次性 commit 暂存区的所有修改
举个例子:
代码语言:javascript代码运行次数:0运行复制$ touch file1 file2
$ git add file1
$ git add file2
h$ git commit -m "add 2 files"
[master 23807c5] add 2 files
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file1
create mode 100644 file2
截至目前为止,我们已经更够将代码直接提交至本地仓库了。我们可以使用 git log
命令,来查看下历史提交记录:
lighthouse@VM-8-10-ubuntu:gitcode$ git log
commit dc24b53156838598792f3ff69cccfb4f612edb05 (HEAD -> master)
Author: island0920 <island0920@163>
Date: Mon Apr 7 10:52:54 2025 +0800
commit my first file
该命令显示从最近到最远的提交日志,并且可以看到我们 commit
时的日志消息。如果嫌输出信息太多,看得眼花缭乱的,可以试试加上 --pretty=oneline
参数:
lighthouse@VM-8-10-ubuntu:gitcode$ git log --pretty=oneline
dc24b53156838598792f3ff69cccfb4f612edb05 (HEAD -> master) commit my first file
- 需要说明的是,我们看到的一大串类似 23807c5…56eed6 的是每次提交的 commit id(版本号),Git的
commit id
不是1,2,3……递增的数字,而是一个 SHA1 计算出来的一个非常大的数字,用十六进制表示
2. 了解 .git 下目录及文件
添加完新的文件之后,再来查看 .git,会发现它下面的文件就发生了变化,如下:
代码语言:javascript代码运行次数:0运行复制lighthouse@VM-8-10-ubuntu:gitcode$ tree .git/
.git/
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 59
│ │ └── 8dc4cd6941181b51e351f03f0073323d620438
│ ├── ad
│ │ └── 943250ad5c0627b624be300fb6882ae574e31a
│ ├── dc
│ │ └── 24b53156838598792f3ff69cccfb4f612edb05
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
15 directories, 25 files
.git
目录是 Git 版本控制系统的核心,存储了仓库的所有元数据和对象。以下是各个目录和文件的详细介绍:
① 顶级目录和文件
branches
(已废弃)
- 早期 Git 版本中用于存储分支的引用,现代 Git 已不再使用此目录。现在分支信息存储在
refs/heads/
中。
COMMIT_EDITMSG
- 作用:临时保存最近一次提交时编写的提交消息(Commit Message)。
- 生成时机:当运行
git commit
进入编辑提交消息的界面时,Git 会将消息暂存于此文件。提交完成后,内容会被存储到提交对象中,此文件保留最后一次提交的消息
config
- 仓库的配置文件,包含当前仓库的 Git 配置(如远程仓库地址、分支跟踪、别名等)。
- 可通过
git config
命令修改(例如git config user.name "Your Name"
)。
description
- 用于 GitWeb(Git 的网页界面)显示仓库的描述信息,默认是一个示例文本,可手动编辑。
HEAD
注意:HEAD
指向的是当前分支,而分支才指向提交(默认指向 master)
例如:
代码语言:javascript代码运行次数:0运行复制lighthouse@VM-8-10-ubuntu:gitcode$ cat .git/HEAD
ref: refs/heads/master
其实默认的 master 分支,就是:
代码语言:javascript代码运行次数:0运行复制lighthouse@VM-8-10-ubuntu:gitcode$ cat .git/refs/heads/master
dc24b53156838598792f3ff69cccfb4f612edb05
打印的字符什么东西呢?保存的就是当前最新 的 commit id
② hooks
目录
- 存放 Git 钩子脚本的示例文件(
.sample
后缀)。钩子用于在特定 Git 操作(如提交、推送)前后触发自定义脚本。 - 常用钩子示例:
pre-commit.sample
: 提交前执行(例如代码格式检查)。commit-msg.sample
: 检查提交消息格式。post-update.sample
: 推送后触发(例如自动部署)。
- 要启用钩子,需移除
.sample
后缀并赋予可执行权限。
③ index
- 作用:Git 的 暂存区(Staging Area) 的二进制表示,记录了当前已暂存的文件状态(如文件路径、SHA-1 哈希、时间戳等)。
- 操作关联:
git add
会将文件状态写入index
。git commit
会将index
的内容生成一个提交对象。
- 查看内容:可用
git ls -files --stage
查看暂存区文件信息。
④ logs/
目录
- 作用:记录仓库中 引用(如分支、HEAD)的变更历史,用于实现
git reflog
命令(恢复误删的提交或分支)。logs/HEAD
: 记录所有 HEAD 的移动历史(如切换分支、提交、重置等)。logs/refs/heads/master
: 记录master
分支的提交历史。
- 文件格式:每行包含旧提交哈希、新提交哈希、操作者信息、时间戳和操作描述。
⑤ info
目录
exclude
- 用于定义仓库的忽略规则,类似
.gitignore
,但此文件不会被提交到远程仓库。适合个人本地忽略的临时文件。
- 用于定义仓库的忽略规则,类似
⑥ objects
目录
- 存储 Git 的所有对象(提交、文件内容、目录结构等),每个对象通过 SHA-1 哈希值命名。
info/
: 包含对象存储的附加信息。pack/
: 压缩后的对象包(Git 为优化存储将小对象打包)
- 对象存储:每个对象是一个文件,路径由 SHA-1 哈希的前两位作为目录,剩余字符作为文件名
- 常见对象:
- blob:存储文件内容。
- tree:存储目录结构(类似文件系统的文件夹)。
- commit:存储提交信息(作者、时间、父提交哈希、关联的 tree 对象)
objects 为 Git 的对象库,里面包含了创建的各种版本库对象及内容。
- 当执行
git add
命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,就位于"git/objects"目录下,让我们来看看这些对象有何用处:
lighthouse@VM-8-10-ubuntu:gitcode$ ls .git/objects/
59 ad dc info pack
查找 object 时要将 commit id
分成2部分,其前2位是文件夹名称,后38位是文件名称。找到这个文件之后,一般不能直接看到里面是什么,该类文件是经过sha(安全哈希算法)加密过的文件,好在我们可以使用 git cat -file
命令来查看版本库对象的内容:
lighthouse@VM-8-10-ubuntu:gitcode$ git cat-file -p
dc24b53156838598792f3ff69cccfb4f612edb05
tree ad943250ad5c0627b624be300fb6882ae574e31a
author island0920 <island0920@163> 1743994374 +0800
committer island0920 <island0920@163> 1743994374 +0800
commit my first file
# 这就是最近一次的提交
其中,还有⼀行 tree ad943250ad5c0627b624be300fb6882ae574e31a
,我们使用同样的方法,看看结果:
lighthouse@VM-8-10-ubuntu:gitcode$ git cat-file -p ad943250ad5c0627b624be300fb6882ae574e31a
100644 blob 598dc4cd6941181b51e351f03f0073323d620438 book
- 再看 book 文件对应的
lighthouse@VM-8-10-ubuntu:gitcode$ git cat-file -p 598dc4cd6941181b51e351f03f0073323d620438
Hello Island1314
# 这就是对 ReadMe 做的修改,已被记录
⑦refs
目录
- 存储引用(指针),包括分支和标签。
heads/
: 分支的引用(例如refs/heads/main
指向main
分支的最新提交)。tags/
: 标签的引用(例如refs/tags/v1.0
指向某个提交的标签)。
总结
- 对象存储:
objects
目录是 Git 的底层数据库,所有数据(文件内容、提交记录等)均以对象形式存储 - 引用管理:
refs
目录通过简单的文本文件指向对象的 SHA-1 哈希值,实现分支和标签的快速定位 - 本地配置:
config
和hooks
允许定制化 Git 行为,而exclude
和.gitignore
用于文件忽略
index:暂存区,git add 后会更新该内容。 HEAD:默认指向 master 分支的一个指针。 refs/heads/master:文件里保存当前 master 分支的最新 commit id objects:包含了创建的各种版本库对象及内容,可以简单理解为放了 git 维护的所有修改。
3. 添加文件 – 场景二
那么我们再展示一种添加文件的场景,能加深对工作区、暂存区、版本库的理解,示例如下
代码语言:javascript代码运行次数:0运行复制$ touch file4 #1. 新增file4⽂件
$ git add file4 #2. 将file4添加到暂存区
$ touch file5 #3. 新增file5⽂件
$ git commit -m"add file" #4. 提交修改
[master 3d406c0] 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 即可。
4. 修改文件
Git 比其他版本控制系统设计得优秀,因为 Git 跟踪并管理的是修改,而非文件。
- 什么是修改? ===> 比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。对 book 文件进行一次修改:
lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
此时,仓库中的 book
和我们工作区的 book
是不同的,如何查看当前仓库的状态呢?
git status
命令用于查看在你上次提交之后是否有对文件进行再次修改。
lighthouse@VM-8-10-ubuntu: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: book
no changes added to commit (use "git add" and/or "git commit -a")
上面的结果告诉我们,ReadMe被修改过了,但还没有完成添加与提交。
- 目前,我们只知道文件被修改了,但是并不知道具体哪些地方被修改了
git diff [file]
命令用来显示暂存区和工作区文件的差异,显示的格式正是Unix通用的diff格式。
- 也可以使
git diff HEAD -- [file]
命令来查看版本库和工作区文件的区别。
lighthouse@VM-8-10-ubuntu:gitcode$ git diff book
diff --git a/book b/book
index 598dc4c..92a1e2d 100644
--- a/book
+++ b/book
@@ -1 +1,2 @@
Hello Island1314
+Hello World
知道了对当前文件做了什么修改后,再把它提交到本地仓库就放心多了。
git add
之后,就没有看到上面no changes added to commit(use "git add" and/or "git commit -a")
的消息了。- 接下来让我们继续
git commit
即可:
lighthouse@VM-8-10-ubuntu:gitcode$ git add book
lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "add modify Book file"
[master b2f0ee2] add modify Book file
1 file changed, 1 insertion(+)
lighthouse@VM-8-10-ubuntu:gitcode$ git status
On branch master
nothing to commit, working tree clean