.git 的内部目录结构 🔗
Git 是一个内容寻址(content-addressable)文件系统, 在此之上提供了一个版本控制系统。
$ ls -F1
config
description
HEAD
hooks/
info/
objects/
refs/
HEAD 文件指向目前被检出的分支。.git/objects 目录存储数据内容。 refs 目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针。index 文件保存暂存区信息。
上层命令 与 底层命令 🔗
checkout、branch、remote 等 git 子命令为上层命令。
底层命令得以让你窥探 Git 内部的工作机制,也有助于说明 Git 是如何完成工作的。
例如 底层命令 git hash-object 可将任意数据保存于 .git/objects 目录(即 对象数据库),并返回指向该数据对象的唯一的键
如何向 Git 中存入内容,以及如何将它们取出?
echo 'test content' | git hash-object -w --stdin
git cat-file -p 查看对象文件。
对象 🔗
Blob数据对象。 tree目录对象。commit 版本对象。以单独文件的形式保存在.git/objects目录
删除工作目录下的文件,可以用 git 从对象文件中恢复回来。 git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
文件的每个版本所对应的 SHA-1 不好记。 blob 对象里没有没有存文件名(类似 inode 里没有存文件名), 引入 tree 对象了。
tree 目录对象解决多个文件组织,存文件名的问题。
git cat-file -p master^{tree} master 分支上最新的提交所指向的树对象。
commit 对象。跟踪项目的不同快照。
echo 'first commit' | git commit-tree d8329f git cat-file -p fdf4fc3
git 引用 🔗
Git 分支的本质:一个指向某一系列提交之首的指针或引用。
find .git/refs -type f -type f 指定只查找普通文件(files)。
.git/refs 目录下。
.git/refs/heads 包含了本地分支的引用。每个文件的内容是相应分支的最新提交的哈希值。
.git/refs/tags 包含了标签的引用。每个文件的内容是相应标签所指向的提交的哈希值。
.git/refs/remotes 包含了远程分支的引用。每个文件的内容是相应远程分支的最新提交的哈希值。
git update-ref refs/heads/test cac0ca
包文件 🔗
一个大文件,只修改了一行,存在两个 blob 对象文件里很占用空间。“包文件(packfile)”的二进制文件
git gc
work dir, index/staging area, repository 🔗
work dir (touch a.txt) -- git add a.txt --> index/staging area(blob 文件) --git commit -m "aa" --> repository.
undo the changes, rewrite history with confidence 🔗
git revert
git reset --soft HEAD~1 git reflog
git cherry-pick commit-id git log -g
diff & patch, merge, 3 way merge, rebase(只操作本地的 commit,远程其他人依赖的 commit 不要操作)。
删除 commit 🔗
git reset 🔗
git reset --soft 仅移动 HEAD, git reset --mixed 移动 HEAD,更改 index 暂存区, git reset --hard 移动 HEAD,更改 index 暂存区,更改工作目录。
git log git reset --hard commit_id git push origin HEAD --force // 误删除后的恢复 git relog git reset --hard hash_id
git revert 🔗
git cheri-pick git reflog
git rebase 🔗
这个视频很清楚。https://www.youtube.com/watch?v=CRlGDDprdOQ 两个用处: 分支合并,基于的 commitid 变基分支。 合并 local commit 记录,需要 rebase 的所有 commits 历史还没有被 push 过。
合并 commit 🔗
有些对 git 的提交记录有要求,需要合并 commit git merge --squash xx_branch 接着需要 git commit -m "merge info"
整合来自不同分支的修改主要有两种方法:merge 以及 rebase。
git pull 与 git pull -rebase 的区别 🔗
fetch 之后的 merge 和 rebase 操作不同。
git pull == git fetch + git merge FETCH_HEAD
git pull -rebase == git fetch + git rebase FETCH_HEAD
git internals 内部 🔗
执行 git commit 时发生了什么? 每次 commit 时存储了什么? git init 时发生了什么?
object: blob, tree, commit。
分支 branch。
working directory, staging area, repository。
可能会遇到的问题 🔗
git cat-file -p objectName -> Fatal error : Not a valid object name 🔗
.git/objects/ff/e531e3643e95e811da231410f14c76e12a68be objectName=ffe531e3643e95e811da231410f14c76e12a68be