Git使用

Git使用

  • [1. Git初识](#1. Git初识)
    • [1.1 为什么需要Git?](#1.1 为什么需要Git?)
    • [1.2 Git 是什么?](#1.2 Git 是什么?)
    • [1.3 Git 的注意事项](#1.3 Git 的注意事项)
    • [1.4 Git安装](#1.4 Git安装)
  • [2. Git基本操作](#2. Git基本操作)
    • [2.1 创建Git本地仓库](#2.1 创建Git本地仓库)
      • [`git init`:本地版本控制的 "起点"](#git init:本地版本控制的 “起点”)
      • [Gitee 仓库:远程协作的 "平台"](#Gitee 仓库:远程协作的 “平台”)
    • [2.2 配置Git](#2.2 配置Git)
    • [2.3 Git 工作区、暂存区、版本库](#2.3 Git 工作区、暂存区、版本库)
    • [2.4 添加文件与提交版本](#2.4 添加文件与提交版本)
    • [2.5 查看提交历史](#2.5 查看提交历史)
    • [2.6 Git 底层结构与文件操作](#2.6 Git 底层结构与文件操作)
    • [2.7 版本回退](#2.7 版本回退)

1. Git初识

1.1 为什么需要Git?

在日常工作和学习中,我们经常会遇到这样的场景:编写文档或代码时,为了防止内容丢失、修改失误,需要保留不同阶段的版本,于是会出现 "报告 - v1" ,"报告 - v2" ,"代码最终版" ,"代码究极进化版" 这类大量重复的文件副本。

随着版本数量增多,我们很难清晰记得每个版本具体修改了什么内容。这种问题在软件开发项目的代码管理中尤为突出。

为了解决这类版本管理的痛点,版本控制器应运而生,而 Git 就是目前最主流的版本控制器。

1.2 Git 是什么?

版本控制器是一套可以记录文件(或工程)历史变更、发展过程的系统。它能帮我们:

  • 追踪文件的每一次改动,明确版本演进的脉络;
  • 方便多人协同作业,在团队开发中高效管理代码版本;
  • 支持版本回退,当修改失误时能快速恢复到之前的正确版本。

Git 作为主流版本控制器,可以管理几乎所有格式的文件 ,包括文档(doc、txt 等)、表格(excel)、代码文件,甚至工程图纸(dwg、dgn 等)。对于开发人员而言,Git 最核心的价值是管理软件开发项目中的源代码文件,保障代码开发的高效性和可追溯性。

1.3 Git 的注意事项

需要明确的是,Git(以及所有版本控制系统)对文本文件二进制文件的追踪能力是有区别的:

  • 文本文件(如 TXT、网页代码、程序源代码等):Git 可以精确追踪每一次改动,比如能明确告诉你 "在第 5 行添加了单词'Linux',在第 8 行删除了单词'Windows'"。
  • 二进制文件 (如图片、视频、音频等):Git 可以管理这些文件的版本,但无法追踪具体的内容变化,只能记录文件大小、修改时间等基本信息(例如仅知道图片从 100KB 变为 120KB,却无法知晓图片内容具体改了哪里)。

通过以上内容,我们可以快速理解 Git 出现的背景、核心作用以及使用时的关键注意点,为后续学习 Git 的具体操作打下基础。

1.4 Git安装

复制代码
# ubuntu系统安装
sudo apt install git -y

2. Git基本操作

2.1 创建Git本地仓库

仓库是 Git 进行版本控制的文件目录,要对文件进行版本管理,必须先创建一个仓库。

git init

使用 git init 命令在指定文件目录下创建 Git 本地仓库,执行时需注意命令要在目标文件目录下执行

c 复制代码
zmm@zmm:~$ pwd
/home/zmm
zmm@zmm:~$ mkdir gitcode
zmm@zmm:~$ cd gitcode/
zmm@zmm:~/gitcode$ git init
提示:使用 'master' 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中
提示:配置使用初始分支名,并消除这条警告,请执行:
提示:
提示:	git config --global init.defaultBranch <名称>
提示:
提示:除了 'master' 之外,通常选定的名字有 'main'、'trunk' 和 'development'。
提示:可以通过以下命令重命名刚创建的分支:
提示:
提示:	git branch -m <name>
已初始化空的 Git 仓库于 /home/zmm/gitcode/.git/

仓库的核心标识:.git 隐藏目录

执行 git init 后,当前目录会生成一个 .git 隐藏文件夹,它是 Git 跟踪管理仓库的核心目录,包含了仓库的版本信息、配置、历史记录等细节。

⚠️ 注意:不要手动修改 .git 目录内的文件 ,否则会破坏 Git 仓库的完整性。

git init 和 Gitee 上创建的仓库有本质区别,核心差异可以从定位、功能、使用场景三个维度来理解:

git init:本地版本控制的 "起点"

  • 定义git init 是 Git 命令,用于在本地计算机 创建一个 Git 仓库(生成 .git 隐藏目录),仅负责本地文件的版本管理(比如记录文件修改历史、版本回退等)。
  • 功能范围:仅支持本地操作,没有 "远程协作""代码托管" 等能力,相当于你在自己电脑上建了个 "版本管理文件夹"。
  • 典型场景 :个人开发时,想在本地记录代码 / 文档的修改历史,就用 git init 初始化本地仓库。

Gitee 仓库:远程协作的 "平台"

  • 定义 :Gitee 是基于 Git 的远程代码托管平台 ,你在 Gitee 上创建的仓库是托管在Gitee 服务器上的远程仓库。
  • 功能范围 :不仅支持版本控制,还提供多人协作 (如 Pull Request、代码评审)、DevOps 流程 (如 CI/CD)、权限管理(公开 / 私有仓库)等扩展功能,是团队协作和代码共享的工具。
  • 典型场景 :团队开发时,需要多人共享代码、审核修改、追踪问题,就会在 Gitee 上创建远程仓库,再结合本地 git init 的仓库进行协作。

2.2 配置Git

安装 Git 后,首先需要设置用户名称e-mail 地址,这是 Git 识别版本提交者身份的关键信息,也用于多人协作时的权限和记录管理。

复制代码
# 配置用户名
git config [--global] user.name "Your Name"

# 配置邮箱
git config [--global] user.email "email@example.com"
  • --global 选项
    • 若添加该选项,表示这台机器上所有 Git 仓库都会使用此配置
    • 若不添加 --global,则配置仅对当前仓库生效(执行命令时需在仓库目录内)。
  • 替换说明:将 Your Name 改为你的昵称,email@example.com 改为你的实际邮箱即可。

若想确认当前 Git 的配置信息,可执行:

复制代码
git config -l

如果需要删除已配置的用户名或邮箱,可执行:

复制代码
# 删除用户名配置
git config [--global] --unset user.name

# 删除邮箱配置
git config [--global] --unset user.email

(同样,--global 选项决定是删除全局配置还是仅当前仓库的配置,若之前是使用--global选项,则删除也需要带上--global)

2.3 Git 工作区、暂存区、版本库

1. 工作区

是你在电脑上写代码或存放文件的目录,就是你能直观看到的文件所在的文件夹。

2. 暂存区

英文名为 stageindex,一般存放在 .git 目录下的 index 文件(.git/index)中,也被称为索引(index)。它是工作区和版本库之间的 "中转站"。

3. 版本库

又名仓库,英文是 repository。工作区里的隐藏目录 .git 就是 Git 的版本库(它不算工作区)。版本库能跟踪管理所有文件的修改、删除等操作,让你可以随时追溯历史或还原版本。

4. 三者关系

  • 左侧是工作区 ,右侧是版本库 ,版本库中最关键的是暂存区(stage)
  • Git 初始化时会自动创建默认分支 master 和指向 master 的指针 HEAD(分支和 HEAD 后续详细讲)。
  • 当你在工作区修改或新增文件后,执行 git add 命令,暂存区的文件索引会被更新;执行 git commit 命令,master 分支会更新,相当于把暂存区的内容真正写入版本库。

简言之:新文件仅放在工作区时,不算加入版本库管理;必须通过 git add 放到暂存区,再通过 git commit 提交到版本库,才算完成版本跟踪。

2.4 添加文件与提交版本

场景一:添加单个文件到版本库

复制代码
# 1. 新建并编辑文件(以 vim 为例,也可通过其他方式创建)
vim ReadMe
# 2. 查看文件内容(可选)
cat ReadMe
# 3. 将文件添加到暂存区
git add ReadMe
# 4. 将暂存区内容提交到本地版本库(-m 后跟提交说明,必须填写)
git commit -m "commit my first file"

执行 git commit 后,会提示文件改动信息(比如新增了几行内容),表示提交成功。

场景二:批量添加多个文件到版本库

复制代码
# 1. 新建多个文件
touch file1 file2 file3
# 2. 分别将文件添加到暂存区(也可一次性 add 多个,如 git add file1 file2 file3)
git add file1
git add file2
git add file3
# 3. 一次性提交暂存区所有内容到版本库
git commit -m "add 3 files"

2.5 查看提交历史

git log执行后会显示从最近到最远的提交日志,包含提交者、时间、提交说明等信息:

git log --pretty=oneline当提交记录过多时,可通过该参数让输出更简洁,每行仅显示提交 ID 和提交说明:

其中可以看到的类似 23807c5...56eed6 的字符串是提交 ID(版本号),它是通过 SHA1 算法生成的十六进制大数字,而非简单的递增数字(每个人的提交 ID 都不同,以自己实际输出为准)。

2.6 Git 底层结构与文件操作

通过 tree .git/ 命令可以查看其目录结构,主要包含以下关键部分:

  • branches:早期 Git 分支管理的遗留目录,现在基本不用。
  • COMMIT_EDITMSG:存储最后一次提交的说明信息。
  • config:Git 的配置文件,包含用户信息、远程仓库等配置。
  • description:用于 GitWeb 等工具的仓库描述。
  • HEAD:指向当前所在分支的指针(如默认指向 master 分支)。
  • hooks:存放 Git 钩子脚本的目录,用于自动化触发操作(如提交前检查、推送后通知)。
  • index暂存区的核心文件git add 后的内容会更新到这里。
  • info:包含仓库的额外信息,如 exclude 文件(类似 .gitignore)。
  • logs:记录分支的历史操作日志。
  • objects:Git 的对象库,存储所有版本的文件内容、提交信息、目录结构等。
  • refs:存储分支和标签的引用,如 heads/master 指向当前 master 分支的最新提交 ID。

核心组件解析

  • index(暂存区)git add 命令会将文件添加到这里,是工作区和版本库之间的 "中转站"。

  • HEAD :是一个指针,默认指向 master 分支。执行 cat .git/HEAD 可查看其指向,示例输出 ref: refs/heads/master 表示当前在 master 分支。

    zmm@zmm:~/gitcode$ cat .git/HEAD
    ref: refs/heads/master

  • objects(对象库) :存储 Git 中的三种对象 ------blob(文件内容)、tree(目录结构)、commit(提交信息)。执行 git add 时,文件内容会被写入到 objects 目录下的新对象中。

    • 对象查找方式 :提交 ID(commit id)分为两部分,前 2 位是文件夹名,后 38 位是文件名。例如 23807c536969cd886c4fb624b997ca575756eed6 会存放在 objects/23/807c536969cd886c4fb624b997ca575756eed6
    • 查看对象内容 :使用 git cat-file -p <commit id/tree id/blob id> 命令,可查看提交、目录树、文件内容的详细信息。
  • 暂存区(清单):只记 "要提交什么文件、对应哪个货号",不存文件内容;
  • objects(货架):存文件的实际内容(blob)、目录结构(tree)、提交记录(commit),是所有数据的存储地;

假设你在工作区修改了 ReadMe 文件,执行 git add ReadMe

  • ① 先把 ReadMe当前内容 ,以 blob 类型对象的形式,写入 objects 目录(相当于把 "文章草稿" 的最终文本,存到 "数据档案室");
    • 比如文件内容会被压缩、计算 SHA1 哈希(就是后续的对象 ID),然后存到 objects/xx/xxxxxxxxxxxx(前两位是哈希前缀,后 38 位是完整哈希);
    • 此时 objects 里已经有了这个文件的当前版本数据,但这只是 "原始数据",还没和 "版本" 绑定。
  • ② 再更新 .git/index 文件(暂存区):把 ReadMe 的文件名、对应的 blob 对象 ID、文件权限等信息,记录到 index 里(相当于把 "文章草稿" 加入 "待发表清单");
    • 此时暂存区(index)知道 "要提交 ReadMe,且它的内容在 objects 目录的某个 blob 对象里",但这还不是一个完整的 "版本"。

👉 关键结论:git add 会往 objects 写文件内容(blob 对象),但 objects 不是 "暂存库"------ 暂存区是 index 文件(清单),objects 是存放清单对应 "原始数据" 的仓库。

执行 git commit -m "修改 ReadMe" 后,才会形成一个完整的版本:

  • ① 先创建一个 tree 类型对象,写入 objects 目录:
    • tree 对象记录了 "当前暂存区的目录结构"------ 比如 "当前目录下有 ReadMe 文件,对应哪个 blob 对象;有 docs 文件夹,对应哪个子 tree 对象"(相当于把 "待发表清单" 整理成 "文章目录");
    • 这个 tree 对象也会存在 objects 里,有自己的哈希 ID。
  • ② 再创建一个 commit 类型对象,写入 objects 目录:
    • commit 对象是 "版本的核心凭证",包含三部分关键信息:
      1. 指向刚才创建的 tree 对象(知道这个版本包含哪些文件 / 目录);
      2. 指向父提交对象(知道这个版本是基于哪个之前的版本修改的,形成版本链);
      3. 提交者信息、提交时间、提交说明(就是你 -m 后面写的内容);
    • 这个 commit 对象的哈希 ID,就是我们看到的 commit id(版本号)。
  • ③ 最后更新分支指针(比如 master 分支):
    • 把当前分支(如 refs/heads/master)的指针,指向这个新创建的 commit 对象(相当于把 "文章目录 + 核心凭证" 绑定到 "专栏",标记为最新版本)。

👉 关键结论:git commit 并没有把数据 "从 objects 搬到别的地方"------ 而是在 objects 里新增了 treecommit 对象,把之前 git add 存的 blob 对象(文件内容)"组织起来",形成一个可追溯的 "版本",最终记录到版本库中。

2.7 版本回退

版本回退是 Git 最核心的能力之一,当你发现最新代码出现严重问题时,它能帮你快速回到历史上的稳定版本。下面结合内容,从命令原理、操作场景、底层逻辑三个维度详细讲解。

git reset 是实现版本回退的命令,它通过不同的参数控制 "工作区、暂存区、版本库" 的回退范围,语法格式为:

复制代码
git reset [--soft | --mixed | --hard] [HEAD]

一般不要去使用--hard,mixed用的最多

HEAD 是 Git 中表示 "当前版本" 的指针,通过它可以灵活指定回退的目标版本:

  • HEAD:当前版本
  • HEAD^:上一个版本
  • HEAD^^:上上一个版本
  • HEAD~n:往上第 n 个版本(如 HEAD~3 表示往上 3 个版本)
  • 直接写 commit id:指定回退到某个具体版本(可通过 git loggit reflog 获取)
c 复制代码
zmm@zmm:~/gitcode$ cat ReadMe 
hello git
hello world
zmm@zmm:~/gitcode$ git log --pretty=oneline
e207f4e61cc36c7d1e1ad303ad090dc4d6974c17 (HEAD -> master) modify ReadMe
4299a6418c996357db5c26f00698028c21c63a4a add file4,5
b89c925366b6a7130255defd5c427317c365d47d add 3 file
269ced211fe34496dd3f820c99307755b27c4446 the first commit file
zmm@zmm:~/gitcode$ git reset --hard 269ced211fe34496dd3f820c99307755b27c4446
HEAD 现在位于 269ced2 the first commit file
zmm@zmm:~/gitcode$ ls
ReadMe
zmm@zmm:~/gitcode$ cat ReadMe 
hello git
zmm@zmm:~/gitcode$ git log --pretty=oneline
269ced211fe34496dd3f820c99307755b27c4446 (HEAD -> master) the first commit file
zmm@zmm:~/gitcode$ git reset --hard e207f4e61cc36c7d1e1ad303ad090dc4d6974c17
HEAD 现在位于 e207f4e modify ReadMe
zmm@zmm:~/gitcode$ ls
file1  file2  file3  file4  file5  ReadMe
zmm@zmm:~/gitcode$ git log --pretty=oneline
269ced211fe34496dd3f820c99307755b27c4446 (HEAD -> master) the first commit file
c 复制代码
# 第一次提交(version1)
echo "hello version1" >> ReadMe
git add ReadMe
git commit -m "add version1"

# 第二次提交(version2)
echo "hello version2" >> ReadMe
git add ReadMe
git commit -m "add version2"

# 第三次提交(version3)
echo "hello version3" >> ReadMe
git add ReadMe
git commit -m "add version3"

# 查看提交历史
git log --pretty=oneline
   
# 回退到 version2(用 --hard 参数)   
git reset --hard HEAD^  # 或直接用 version2 的 commit id,如 git reset --hard 14c12c3...
    
执行后:
工作区的 ReadMe 内容会回退到 version2;
git log 会显示当前版本是 version2,version3 的提交记录暂时 "消失"。    

如果回退后又想回到 version3,git log 已经看不到它的 commit id 了,这时候用 git reflog(记录所有操作历史):

复制代码
git reflog

输出中会显示所有操作的 commit id,找到 version3 对应的 commit id(如 d95c13f),再执行:

复制代码
git reset --hard d95c13f

就能回到 version3 版本。

底层逻辑:为什么版本回退这么快?

Git 版本回退的速度很快,因为它本质上是移动 HEAD 指针

  • 每个提交版本在 Git 中是 "链状存储" 的,refs/heads/master 文件里保存着当前分支的最新 commit id
  • 版本回退时,Git 只是把 HEAD 指针从 "新版本" 移动到 "旧版本" 的 commit id 上,并不删除历史版本数据;
  • 这也是为什么用 git reflog 能找回所有操作 ------ 历史版本的 commit id 一直存在,只是 HEAD 指针移动了。

核心本质:Git 的版本回退 / 复原 = 指针移动 ,所有已提交的版本数据(commit+tree+blob)都会保存在 objects 中,不会因为指针移动而删除;

复制代码
version3(commit id: C)← HEAD ← master 分支指针
       ↑
version2(commit id: B)
       ↑
version1(commit id: A)

执行 git reset --hard HEAD^ 回退到 version2
version3(commit id: C)【数据仍在 objects 中,只是没人指向它】
       ↑
version2(commit id: B)← HEAD ← master 分支指针
       ↑
version1(commit id: A)
相关推荐
_君莫笑8 小时前
大厂Git使用规范
git
无心水14 小时前
【Hermes:安全、权限与生产环境】39、智能体也会犯错?Hermes 纠错、回滚与遗忘机制全指南 —— 让 AI 的错误像 Git 一样可逆可控
人工智能·git·安全·mcp协议·openclaw·hermes·honcho
南境十里·墨染春水19 小时前
linux学习进展 git详解
linux·git·学习
zhangfeng113319 小时前
CodeBuddy ai对话框上面的git docs terminal Rulds 干嘛用的,以thinkphp fastadmin 为例,插件市场
人工智能·git·编程
OYangxf20 小时前
Git Conflict Resolution
大数据·git·elasticsearch
高斯林.神犇21 小时前
Git全套流程
git
次元工程师!1 天前
LangFlow开发(一)—安装和部署
git·python·大模型·langflow
怣疯knight1 天前
【无标题】
git
Jim-zf1 天前
git 锁文件
git
lcx_defender1 天前
Git常见操作与指令
git