Git 内幕探索:从底层文件系统到历史编辑的全面指南

微信搜索“好朋友乐平”关注公众号。

在这里插入图片描述


1. Git 底层文件对象

存储文件内容
组织目录和文件结构
记录变更和链接到树
被标记
创建/更新
创建
创建/移动分支指针
合并提交
变基提交
移动 HEAD 指针
更新工作目录和索引
Blob
Tree
Commit
Parent Commit
Tag
git add
git commit
git branch
git merge
git rebase
git reset
git checkout
$ ls .git
config #仅供 GitWeb 程序使用
description #项目特有的配置选项
HEAD #指向目前被检出的分支
hooks/ #包含客户端或服务端的钩子脚本(hook scripts)
info/ #包含一个全局性排除(global exclude)文件, 用以放置那些不希望被记录在 .gitignore 文件中的忽略模式(ignored patterns)
objects/ #存储所有数据内容
refs/ #存储指向数据(分支、远程仓库和标签等)的提交对象的指针
index #保存暂存区信息

1.1 Blob

blob(Binary Large Object)是一种数据类型,用于存储文件的内容。每个文件在 Git 中都被存储为一个 blob 对象。blob 对象包含了文件的原始内容,它们是 Git 中最基本的数据单元之一。

  1. 内容存储:blob 对象存储文件的实际内容。这些内容以二进制格式存储,并且是文件的原始数据。Git 不关心文件的类型,它将所有文件都视为二进制文件,并以 blob 对象的形式存储它们。

  2. 唯一标识:每个 blob 对象都有一个唯一的 SHA-1 哈希值,这个哈希值是通过 blob 对象的内容计算得到的。因为哈希值是根据内容计算的,所以相同内容的 blob 对象具有相同的哈希值,而不同内容的 blob 对象具有不同的哈希值。

  3. 不可变性:一旦创建了一个 blob 对象,它就是不可变的。这意味着 blob 对象的内容不能被修改。如果文件的内容发生了变化,Git 会创建一个新的 blob 对象来存储新内容,并将旧的 blob 对象保留在数据库中。

  4. 存储位置:blob 对象存储在 Git 仓库的 .git/objects 目录中。每个 blob 对象都存储在一个以其哈希值命名的文件中。这些文件通常是 zlib 压缩的,以节省存储空间。

  5. 版本控制:blob 对象是 Git 中文件版本控制的基础。通过存储每个文件的内容的 blob 对象,Git 可以跟踪文件的历史变化,并在需要时恢复到特定版本的文件内容。

1.2 Tree

tree 对象可以存储文件名,同时也允许存储一组文件。Git 以一种类似 UNIX 文件系统但更简单的方式来存储内容。所有内容以 tree 或 blob 对象存储,其中 tree 对象对应于 UNIX 中的目录,blob 对象则大致对应于 inodes 或文件内容。

# master^{tree} 表示 branch 分支上最新提交指向的 tree 对象
$ git cat-file -p master^{tree}100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib

1.3 Commit

commit 对象有格式很简单:指明了该时间点项目快照的顶层树对象、作者/提交者信息(从 Git 设置的 user.name 和 user.email 中获得)以及当前时间戳、一个空行,以及提交注释信息。

$ git cat-file -p fdf4fc3tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579author Scott Chacon <schacon@gmail.com> 1243040974 -0700committer Scott Chacon <schacon@gmail.com> 1243040974 -0700first commit

每一个 commit 对象都指向了你创建的树对象快照。

1.4 Tag

Tag 对象非常像一个 commit 对象——包含一个标签,一组数据,一个消息和一个指针。最主要的区别就是 Tag 对象指向一个 commit 而不是一个 tree。它就像是一个分支引用,但是不会变化——永远指向同一个 commit,仅仅是提供一个更加友好的名字。

$ cat .git/refs/tags/v1.19585191f37f7b0fb9444f35a9bf50de191beadc2

2. Git 引用

$ find .git/refs.git/refs.git/refs/heads.git/refs/tags

3. reset & revert & rebase

  1. git reset

    • 本质:git reset 主要用于移动 HEAD 指针,并且可以改变当前分支的状态。它可以撤销提交、移动 HEAD 到不同的提交或分支,以及更改暂存区和工作目录的状态。
    • 适用场景:git reset 适用于需要撤销提交、移动 HEAD 或重置暂存区和工作目录的情况。例如,你可以使用 git reset --hard 来彻底取消之前的提交并且清除暂存区和工作目录中的所有更改。
  2. git revert

    • 本质:git revert 主要用于撤销一个或多个提交,并且会创建新的提交来记录撤销的操作。它不会改变历史提交,而是在历史提交之上创建新的提交来反转之前的更改。
    • 适用场景:git revert 适用于需要撤销特定提交而不改变历史记录的情况。例如,当你需要撤销一个错误的提交,但同时又希望保留原有的提交历史时,可以使用 git revert
  3. git rebase

    • 本质:git rebase 主要用于将一个分支的提交应用到另一个分支上,并且可以重新应用提交历史以改变提交的顺序或合并提交。它通过将一系列提交转移至另一个分支上来实现这个目的。
    • 适用场景:git rebase 适用于需要在不同分支之间移动或合并提交历史的情况。例如,当你需要将一个分支的提交应用到另一个分支上时,可以使用 git rebase 来移动提交。另外,git rebase 也可以用于合并提交、清理提交历史以及保持一个干净的历史记录。

git reset 适用于撤销提交、移动 HEAD 和重置状态的情况;git revert 适用于撤销特定提交而不改变历史记录的情况;git rebase 适用于在不同分支之间移动或合并提交历史的情况。通常情况下,git reset 更适合操作当下分支,而 git rebase 更适合操作多个分支。

graph LRA[开始状态] -->|git reset| B(Reset: 回到过去)A -->|git revert| C(Revert: 逆向提交)A -->|git rebase| D(Rebase: 变基)B -->|soft| B1(保留工作目录和索引)B -->|mixed| B2(保留工作目录,重置索引)B -->|hard| B3(重置工作目录和索引)C --> C1[生成新的逆向提交]D --> D1[变更基底提交]D --> D2[压缩/修改提交历史]

4. cherry-pick & rebase

Git Cherry-pick

功能: git cherry-pick 命令用于将其他分支上的提交应用到当前分支。它允许你选择一个或多个提交,并将这些提交作为新的提交引入到当前分支。

使用场景:

  1. 特定提交的应用: 当你只想从另一个分支取得特定的提交时,而不是整个分支的内容,可以使用 cherry-pick
  2. 修复错误: 如果在一个分支上修复了一个 bug,而这个修复需要应用到其他分支上,但不需要其他更改时,可以使用 cherry-pick
  3. 代码回滚: 在某些情况下,如果某个功能在被合并到主分支之后出现问题,你可能需要将这个功能的提交从主分支上移除。cherry-pick 可以用来选择性地撤销特定的提交。

Git Rebase

功能: git rebase 命令用于将一个分支的修改重新应用在另一个分支之上。它常用于保持一个干净的项目历史,通过将一系列的提交“重新播放”在另一分支上。

使用场景:

  1. 保持线性历史: 在合并特性分支之前,使用 rebase 可以保证一个线性的提交历史,这使得历史更容易理解和导航。
  2. 避免不必要的合并提交: 当你需要将最新的主分支变更合并到你的特性分支时,使用 rebase 而不是 merge 可以避免生成额外的合并提交。
  3. 整理提交: 在将特性分支合并到主分支前,你可以使用 rebase 来压缩(squash)或重新排序提交,以创建一个更清晰的提交历史。

区别

  • 操作对象: cherry-pick 是针对特定的提交操作,而 rebase 是对一系列提交的重新整理和应用。
  • 历史改写: rebase 会改写历史,cherry-pick 则在当前分支上创建新的提交。
  • 使用目的: cherry-pick 主要用于特定提交的应用,而 rebase 用于历史整理和保持项目历史的线性。
git rebase
git cherry-pick
cherry-pick
rebase
选择基底分支
当前分支
重新应用提交
整理提交历史
选择特定提交
当前分支
在当前分支应用该提交

5. 场景:仅下载需要的分支

在处理大型仓库时尤其有用,可以节省时间和资源。

当你想要通过 git clone 克隆仓库时,但只想克隆特定分支的内容,你可以使用 --single-branch 选项。这个选项告诉 Git 只克隆指定的分支,而不是克隆所有分支的内容。

这里是具体的命令格式:

git clone --single-branch --branch <branchname> <repository-url>
  • --single-branch: 这个选项限制 Git 只克隆指定的单个分支。
  • --branch <branchname>: 这里 <branchname> 是你想要克隆的分支名称。
  • <repository-url>: 这是你想要克隆的远程仓库的 URL。

例如,如果你只想克隆远程仓库中名为 develop 的分支,你可以运行:

git clone --single-branch --branch develop https://github.com/example/repository.git

这个命令会创建一个新的仓库副本,其中只包含 develop 分支的内容。

请注意,使用 --single-branch 时,克隆的仓库将只有一个追踪分支。这意味着你不会看到远程仓库中的其他分支,除非你手动添加追踪分支或者改变克隆的配置来包含更多分支。

5.1 查看所有远程分支

git fetch --all
git branch -r

这里,git fetch --all 会从远程获取所有分支的信息(但不下载这些分支的内容),而 git branch -r 会列出所有远程分支。

5.2 按需下载特定分支

git checkout -b [branch-name] origin/[branch-name]

这里,[branch-name] 是你想要检出的远程分支名。这条命令会创建一个新的本地分支,它跟踪对应的远程分支,并下载该远程分支的内容。

通过这种方式,你可以按需查看和下载远程仓库中的任何分支,而不需要一开始就下载所有分支的数据。这在处理大型仓库时尤其有用,可以节省时间和资源。

6. 场景:修改 commit 作者信息

如果提交过程中 usernameemail 提交操作了,需要批量修正,如把所有 aaa@aaa.com 的邮箱改为bbb@bbb.com,并把用户名aaa改为bbb,则可以用下面命令处理:

Unix:

git filter-branch --env-filter '
OLD_EMAIL="aaa@aaa.com"
CORRECT_NAME="bbb"
CORRECT_EMAIL="bbb@bbb.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
thenexport GIT_COMMITTER_NAME="$CORRECT_NAME"export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
thenexport GIT_AUTHOR_NAME="$CORRECT_NAME"export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

PowerShell:

git filter-branch --env-filter '
$OLD_EMAIL="aaa@aaa.com"
$CORRECT_NAME="bbb"
$CORRECT_EMAIL="bbb@bbb.com"
if ($Env:GIT_COMMITTER_EMAIL -eq $OLD_EMAIL) {$Env:GIT_COMMITTER_NAME=$CORRECT_NAME$Env:GIT_COMMITTER_EMAIL=$CORRECT_EMAIL
}
if ($Env:GIT_AUTHOR_EMAIL -eq $OLD_EMAIL) {$Env:GIT_AUTHOR_NAME=$CORRECT_NAME$Env:GIT_AUTHOR_EMAIL=$CORRECT_EMAIL
}
' --tag-name-filter cat -- --branches --tags

7. 场景:产出大文件提交

删除历史中误提交的大文件,如 a.mp4b.mp4

git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch a.mp4 b.mp4" \
--prune-empty --tag-name-filter cat -- --all

PowerShell:

git filter-branch --force --index-filter `
"git rm --cached --ignore-unmatch a.mp4 b.mp4" `
--prune-empty --tag-name-filter cat -- --all

随后可以加入 .gitignore中。

8. 场景:删除 node_modules 提交

git filter-branch --force --index-filter "git rm -r --cached --ignore-unmatch node_modules" --prune-empty --tag-name-filter cat -- --all

可以顺道清理下仓库:

git reflog expire --expire=now --all
git gc --prune=now --aggressive

9. 场景:产出提交中的私密信息

某个文件中含有秘钥,清楚秘钥。如将 123 456替换为 ***

git filter-branch --force --index-filter \
"git ls-files -z | xargs -0 sed -i'' -e 's/123 456/\*\*\*/g' \
--prune-empty --tag-name-filter cat -- --all

制定文件替换,如~/dir1/file1.txt

git filter-branch --force --index-filter \
"git ls-files -z | xargs -0 sed -i'' -e 's/123 456/\*\*\*/g' -- ~/dir1/file1.txt" \
--prune-empty --tag-name-filter cat -- --all

微信搜索“好朋友乐平”关注公众号。

github原文地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/728693.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spark实战-基于Spark日志清洗与数据统计以及Zeppelin使用

Saprk-日志实战 一、用户行为日志 1.概念 用户每次访问网站时所有的行为日志(访问、浏览、搜索、点击)用户行为轨迹&#xff0c;流量日志2.原因 分析日志&#xff1a;网站页面访问量网站的粘性推荐3.生产渠道 (1)Nginx(2)Ajax4.日志内容 日志数据内容&#xff1a;1.访问的…

每天学习一个Linux命令之chown

每天学习一个Linux命令之chown 在Linux系统中&#xff0c;chown命令用于更改文件或目录的所有者。通常情况下&#xff0c;只有超级用户root和文件所有者本人可以使用chown命令。在这篇博客中&#xff0c;我们将详细介绍chown命令的用法以及所有可用的选项。 1. 命令格式 bas…

【动态规划】完全背包

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;完全背包 &#x1f449;&#x1f3fb;…

政安晨:【深度学习处理实践】(二)—— 最大汇聚运算

最大汇聚运算&#xff08;Max Pooling Operation&#xff09;是深度学习领域卷积神经网络常用的一种汇聚运算方式。在卷积神经网络中&#xff0c;经过一系列卷积层和激活函数层后&#xff0c;数据在空间尺寸上逐渐减小&#xff0c;特征图的深度也逐渐增加。为了降低数据尺寸并提…

微信小程序(五十三)修改用户头像与昵称

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.外界面个人资料基本模块 2.资料修改界面同步问题实现&#xff08;细节挺多&#xff0c;考虑了后期转服务器端的方便之处&#xff09; 源码&#xff1a; app.json {"window": {},"usingCompone…

算法打卡day11|栈与队列篇03|Leetcode 239. 滑动窗口最大值、347.前 K 个高频元素

小顶堆和大顶堆 小顶堆&#xff08;Min Heap&#xff09;和大顶堆&#xff08;Max Heap&#xff09;是两种特殊的完全二叉树&#xff0c;它们遵循特定的堆属性&#xff0c;即父节点的值总是小于或等于&#xff08;小顶堆&#xff09;或者大于或等于&#xff08;大顶堆&#xf…

Spring AOP相关注解及执行顺序

Aspect&#xff08;切面&#xff09;&#xff1a;用于标识一个类是切面的注解。通常与其他通知注解一起使用&#xff0c;定义切面类。 Pointcut&#xff08;切点&#xff09;&#xff1a; 注解来定义切点&#xff0c;它用于描述哪些连接点将会被通知所通知。 连接点&#xff…

Linux minfo命令教程:详解MS-DOS文件系统参数查看命令(附实例详解和注意事项)

Linux minfo命令介绍 minfo命令用于显示MS-DOS文件系统的各项参数&#xff0c;如磁区数、磁头数和柱面数等。它还可以打印一个mformat命令行&#xff0c;该命令行可以用于在其他媒体上创建类似的MS-DOS文件系统。 Linux minfo命令适用的Linux版本 minfo命令在大多数Linux发行…

算法D39 | 动态规划2 | 62.不同路径 63. 不同路径 II

今天开始逐渐有 dp的感觉了&#xff0c;题目不多&#xff0c;就两个 不同路径&#xff0c;可以好好研究一下 62.不同路径 本题大家掌握动态规划的方法就可以。 数论方法 有点非主流&#xff0c;很难想到。 代码随想录 视频讲解&#xff1a;动态规划中如何初始化很重要&#x…

Latex公式太长换行标号

Latex中公式太长换行&#xff0c;且编号&#xff0c;可以采用align&#xff0c;不编号行公式用\nonumber&#xff0c;示例如下&#xff1a; \begin{align}\nonumber %第1行公式不编号&abababababababa\\&cdm %第2行公式编号 \end{align}效果如下 原文件链接 公式不…

清除Mac OS上Xcode占用的空间

最近自己的Mac OS存储空间严重不足&#xff0c;想了一下&#xff0c;大概是从安装 Xcode 之后出现&#xff0c;在系统下通过 du 命令分析各目录大小&#xff0c;发现大概下面几个目录占用空间比较大&#xff0c;所以针对这几个名目录作了一下清理&#xff0c;释放了几十个G的空…

Leetcode 268 火星词典

题目描述&#xff1a; 现有一种使用英语字母的火星语言&#xff0c;这门语言的字母顺序与英语顺序不同。 给你一个字符串列表 words &#xff0c;作为这门语言的词典&#xff0c;words 中的字符串已经 按这门新语言的字母顺序进行了排序 。 请你根据该词典还原出此语言中已知…

<网络安全>《65 微课堂<第6课 网间文件安全交换系统>》

1 5中文件传输方式 1.1 通过U盘、硬盘、光盘等硬件介质传输 优势是成本低。 劣势是1、无法对这个行为过程进行监控管理。2、大文件较大、高频率交换时需要专人负责。3、由于这个过程并没有杀毒、内容检测等环节&#xff0c;因此具有较大的安全风险。 1.2 FTP、SFTP等跨网传输…

WordPress建站入门教程:如何上传安装WordPress主题?

我们成功搭建WordPress网站后&#xff0c;默认使用的是自带的最新主题&#xff0c;但是这个是国外主题&#xff0c;可能会引用一些国外的资源文件&#xff0c;所以为了让我们的WordPress网站访问速度更快&#xff0c;强烈建议大家使用国产优秀的WordPress主题。 今天boke112百…

【C语言】球球大作战

前言&#xff1a; 这款简易版的球球大作战是一款单人游戏&#xff0c;玩家需要控制一个小球在地图上移动&#xff0c;吞噬其他小球来增大自己的体积。本游戏使用C语言和easyx图形库编写&#xff0c;旨在帮助初学者了解游戏开发的基本概念和技巧。 在开始编写代码之前&#xf…

Flutter中TextFormField的属性及使用详解

在Flutter中&#xff0c;TextFormField是一个常用的组件&#xff0c;用于接收用户的文本输入。它具有丰富的属性&#xff0c;可以用于实现各种输入框的需求。在本篇博客中&#xff0c;我们将详细介绍TextFormField的属性以及如何使用它来创建文本输入框。 1. 属性介绍 下面是…

js 操作JSON对象查找、删除、增加和修改

对JSON的查找 格式1&#xff1a; datas.key 格式2&#xff1a; datas[key] 示例&#xff1a; var obj {name: "张三", age: 18, gender: "男"}; console.log(obj.name); // 格式1&#xff1a;输出 张三 console.log(obj[name]); // 格式2&#xff1a;输…

【MySQL 系列】MySQL 架构篇

在我们开始了解 MySQL 核心功能之前&#xff0c;首先我们需要站在一个全局的视角&#xff0c;来看 SQL 是如何运作执行的。通过这种方式&#xff0c;我们可以在头脑中构建出一幅 MySQL 各组件之间的协同工作方式&#xff0c;有助于我们加深对 MySQL 服务器的理解。 文章目录 1、…

【洛谷 P8707】[蓝桥杯 2020 省 AB1] 走方格 题解(动态规划)

[蓝桥杯 2020 省 AB1] 走方格 题目描述 在平面上有一些二维的点阵。 这些点的编号就像二维数组的编号一样&#xff0c;从上到下依次为第 1 1 1 至第 n n n 行&#xff0c;从左到右依次为第 1 1 1 至第 m m m 列&#xff0c;每一个点可以用行号和列号来表示。 现在有个人…

深入浅出运维可观测工具(四):如何使用eBPF绘制网络拓扑图

哈喽~又到了我们技术分享环节了。eBPF这个系列自分享以来收到了很多朋友的喜欢&#xff0c;真是让博主又惊又喜&#xff0c;感谢大家的支持。话不多说&#xff0c;今天我们将对如何使用eBPF绘制网络拓扑图做一篇分享&#xff0c;文章较长&#xff0c;干货较多&#xff0c;大家可…