# Git series

TIP

There are a lot of posts out there about learning the basic commands of git, this is not one of them. What I’m going to try here is a different approach.

  • Linux之父 Linus Torvalds 继Linux内核后奉献给全世界程序员的第二个礼物

git

  • 工作区(WORKING DIRECTORY): 直接编辑文件的地方,肉眼可见直接操作;
  • 暂存区(STAGING AREA):数据(快照)暂时存放的地方;
  • 版本库(GIT DIRECTORT(RESPOSITORY)):存放已经提交的数据,push 的时候,就是把这个区的数据 push 到远程git仓库了。
  • git add就是将工作区的修改缓存在暂存区
  • git commit就是将暂存区的数据快照提交到本地库

# Technical-term

# SHA-1

  • git 为每一个实体生成一个160位的散列值,通常使用40个字符长度的16进制字符串表示 头信息(Header)和校验和(checksum)
    • 一个文件对应一条内容
    • The subdirectory is named with the first 2 characters of the SHA-1, and the filename is the remaining 38 characters
  • 散列碰撞(当不同的内容产生了相同的 SHA1):
    • 几乎不会出现散列碰撞情况(相同SHA1,出现冲突)
    • 通常情况下你不需要担心该散列值会产生碰撞,对于 160 位数,你有 2160 或者大约 1048 种可能的 SHA1 散列值。
  • git 是基于内容来生成 SHA1
    • 对应相同的内容得到的永远是相同的 SHA1

# SNAPSHOT

TIP

Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot.

  • 当你删除一个文件后,文件原来所占的磁盘空间并不是被清空,而是被文件系统标记为“已废弃,可修改”的状态,快照的作用就相当于将旧文件所占的空间保留下来,并且保存一个引用,而新文件中会继续使用与旧文件内容相同部分的磁盘空间,不同部分则写入新的磁盘空间
  • 快照并不是这次 commit 时项目中所有文件的拷贝,而是一种索引,通过这个索引可以找到这次 commit 时的所有文件
  • 而 git 在每次 commit 时对项目中所有文件进行扫描,如果某文件发生变化则会对应生成一个新的文件 blob,记录当前 commit 时该文件的文件内容,而文件名是对文件内容的一次 SHA-1 运算得到的 40 位字符串,如果该文件内容没有发生变化,就不会产生新的 blob 对象(因为相同内容的 SHA-1 hash值唯一)
  • 快照就是记录所有这次提交 commit 时 blob 文件名 SHA-1 hash 字符串集合,所以就可以通过某次 commit 的快照找到当时所有文件的 blob 对象文件 hash 字符串集合从而找到所有的文件,加载所有文件后就还原到了当时 commit 的项目状态。

# Merkle Tree

$  git cat-file -p master^{tree}  //master 分支上最新的提交所指向的树对象
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    1.text
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    2.txt
  • object是不可变的,默克尔树(Merkle Tree)判断变化
    • 默克尔树是一类基于哈希值的二叉树或多叉树,其叶子节点上的值通常为数据块的哈希值,而非叶子节点上的值,是将该节点的所有孩子节点的组合结果的哈希值。默克尔树的特点是,底层数据的任何变动,都会传递到其父亲节点,一直到树根。 tree
    • git会自底向上逐一创建这些新对象
    • git也只是根据最新内容创建一个新的blob对象,而不是修改或替换掉之前对应的blob对象。

# 炫技

  • graph list git log --graph --abbrev-commit --decorate --all --oneline
  • 抹除commit黑历史 git reset --soft ur_commit 保留修改的同时,ur_commit之后的历史抹掉
  • 回滚 git reset --hard [_commit_]
  • 排除某个文件提交
    • 用.gitignoreb不管是全局还是本地都会变成delete mode xxx ,问题是我不想删啊
    git add .
    git reset -- .vscode\settings.json
    or
    git add  .  :^.vscode\settings.json
    

# 参考

Last Updated: 2022/8/18 上午10:36:56