理解 Git

主要内容介绍

1.设计思想

2.数据流向

3.git flow

4.其他介绍

5.思考讨论

6.参考资料

1.设计思想

1.快照记录,每一次commit ,记录工作目录的完整快照。
2.不变模式,任何改变都将生成一个新的对象(类似java string 设计)。
3.分布式 ,几乎所有操作都在本地仓库完成(非常高效且无依赖),不同节点可以通过同步来更新内容。
4.复用,使用对象池复用对象,相同内容的文件,在对象池中只会存储一份。

2.数据流向

git数据交互.png

2.1术语

  • work-dir :
    表示工作目录,与.git 绑定的目录,其他名称(working-tree,工作空间)
    不一定与.git 目录在相同的位置(默认是相同的)

  • repo:
    表示.git 目录里面的内容

  • commit-tree:
    每一次提交对应的tree,其他名称(tree,tree-ish,commit),commit 结构见 4其他介绍

  • index/cache:
    对应.git/index 文件,其他名称(cache,index,stage(区别于 stash))

  • object-pool:
    对应.git/objects/ 目录下面的内容,里面存有的对象有 blob(文件),tree(dir and subdir) ,commit ,tag

2.2数据流向

1.repo(object-pool) —> work-dir
2.work-dir —>repo(object-pool)
3.git-inter(object-pool) —>merge object (object-pool)-->new object(object-pool)

2.3 主要操作:

  1. 无work-dir, 向repo 写入内容,
  2. 使用work-dir 向repo 写入内容
  3. repo内容检出到work-dir
  4. work-dir,index(cache),repo(commit-tree),比较
  5. commit-tree 构建,新增,合并,重建,撤销
  6. commit-log 查看

2.4 测试结果查看关键命令

查看work-dir 查看repo 内容
ls git ls-files :查看index 文件内容。git ls-files -s:查看index 文件内容,并且显示blob id
tree git ls-tree [commit-id] :查看commit 对应的tree 结构,以及在tree 上面所有的文件
cat git cat-file -t <blob-id>:查看blob 文件类型,blob-id 为对象池里面对应对象的id
find find .git/objects -type f : 查找文件 find ./ -mmin -1 -type f :查找最近一分钟修改的文件 git log:查看commit log, (其他命令git show ) git log --all --graph —oneline:查看所有提交日志 git log --graph --oneline :查看当前分支提交日志
git diff: 比较[repo ,work-dir], [repo,repo],[repo,index],[index,worlk-dir] 其他比较命令:diff-tree/diff-files/diff-index
git status : work-dir ,index,tree 对比后的状态查看
git for-each-ref :查看所有引用(指针)

2.5 测试以及命令解释

2.5.1 无work-dir, 向repo 写入内容

详细描述: https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
主要命令:

  • git hash-object : 向object-pool 写入文件对象
  • git update-index : 向 index 文件添加 blob 记录(关联到blob)
  • git ls-files -s : 查看index 文件内容
  • git write-tree: 用index 文件内容向 object-pool 写入tree 对象
  • git read-tree : 用commit-tree 生成内容,写入index 文件
  • git ls-tree: 查看tree 内容
  • git commit-tree : 写入commit 对象
  • git log : 查看commit 日志

2.5.2 使用work-dir 向repo 写入内容

  • git stash : 暂时保存work-dir /index 内容,产生一次特殊的commit(stash commit)


    stash-commit.png
  • git add : 工作空间内容添加到object-pool,index (cache)文件记录添加的文件以及blob-id

  • git commit:生成 commit 对象,用index中的文件内容构建commit-tree(tree)

注:流程:工作空间—>缓存(index)—>存储

2.5.3 repo内容检出到work-dir

  • git checkout :检出repo 到work-dir,index,修改相关指针(HEAD ,分支),repo 对象(blob,tree)
  • git checkout-index: 用index 文件记录的内容,覆盖work-dir,repo 对象 为 blob,tree
  • git reset:git add 的逆操作 ,修改index,修改work-dir,修改指针(HEAD),repo 对象为 blob,tree
  • git revert :git commit 的逆操作,repo 对象为 tree

注:
1.blob 可以用文件路径引用,tree 用commit-id引用,tree 对象比较时,如果是文件增加减少一般可以自动完成操作,如果涉及同一个文件的多次修改,操作可能失败,需要合并tree。
2.流程:工作空间<—缓存(index)<—存储

2.5.4 比较working-tree ,index, tree

  • git diff : 默认 working-tree diff index ,—cached [commit-id] : index diff tree,
  • git diff [commit-id] :tree diff commit-id-tree
  • git diff-index :git diff-index [commit-id],当前index 比较 commit-id-index
  • git diff-files :working-tree-file diff index-file
  • git diff-tree [commit-id]:比较tree,commit-id-tree diff commit-id-parent-tree


work-dir,working-tree 表示相同含义
index ,cache,cache-tree表示相同含义
commit-tree,tree,commit 表示相同含义

2.5.5 tree (commit / commit-tree) 构建,新增,合并,重建,撤销

  • git commit:生成 commit 对象,用index中的文件内容构建commit-tree(tree)
  • git merge : 当前分支的HEAD(tree) 合并 其他分支的HEAD(tree),生成一个新的tree ,且当前分支的指针移动到新的tree
  • git rebase :以 onto 为新的基点,重新构建 [to'parent ,to] 这一范围的tree
  • git cherry-pick:以cherry-pick 的commit ,重新构建当前分支的tree
  • git revert:将 revert [commit] 的内容,从当前分支tree移除,并产生一次新的提交来构建新的tree

2.5.6 commit-log 查看

  • git log ,- - online :一行日志 ,- - graph 图形展示,—pretty=raw 原始格式 - -all 所有分支,默认为当前分支
  • git show :见 git help show
  • git whatchanged:见git help show

3. git flow

  • 指针介绍:指向某一个提交的commit (也就能找到对应的tree)
  • 分支(如下图)
    master :指向F ,通过寻找parent commit 就可以构建一条完整的链路。
    experiment: 指向D,通过寻找parent commit 就可以构建一条完整的链路


    branch.png
  • 当前分支:当前分支指针位置(最后一次commit-id),值保留在HEAD 里面
  • stash 指针:git stash 产生的提交,最后的commit-id
    标签:也是指向一次commit-id 的位置,是不可变的(普通的分支还能进行提交)
    注:分支存储位置 .git/HEAD ,refs/*,里面都是保留最新的commit-id
  • 分支其他引用表示:
    commit-id :commit-id的前几位可以定位,只要依据前几位能够定位到内容
   $ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
   $ git show 1c002dd4b536e7479f
   $ git show 1c002d

HEAD@{5}/stash@{1}:reflog 与stash 引用
HEAD^[number] :head 的父节点,可以引用多个父节点(一个节点可能有多个直接父节点)
HEAD~[number] :head的父节点,只能指明第一个父节点
详见: https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection

3.1 分支协作

  • 单远程仓库:
    master:稳定分支,默认分支
    feature:功能分支,一般完成合并后,删除
    hotfix: 紧急bug 修复分支
    develop:开发分支

  • 多远程仓库:一个本地仓库可以对应多个远程仓库,可以同时在多个仓库协作开发。比如github fork, pull request 等操作

    注:多仓库配置见 git help config ,git help remote

4 其他介绍

  • .git目录
    HEAD :保存当前分支指针,指向refs
    index :缓存当前work-tree 目录结构以及文件,以及文件状态
    objects: git 的数据库,保存所有对象(tree,blob, tag ,commit) 。
    refs: 保存所有分支/tag(每个分支/tag记录自己当前指针位置)

  • 配置 见 git help config

  • git数据结构

    • blob对象:
      header={[blob-type][空格][content.length][\0]}
      body={[content]}
      sha1 = Digest::SHA1.hexdigest(header+body)
      store=Zlib::Deflate.deflate(header+body)

    • commit 对象:
      tree: 指向tree 对象的id
      parent:父commit (可能有多个parent,比如合并)
      author: 作者
      committer:提交者
      msg/log: 备注信息,日记显示内容
      commit-结构示例(如下图):


      commit-结构示例
    • tree 对象:
      记录文件,目录关系,以及文件对应的属性(修改时间,创建时间,文件类型等)

    • index 文件:
      记录working-tree 目录下面所偶遇文件以及文件对应的属性(修改时间,创建时间,文件类型等)
      文件不同区域对应的id, tree-hash-id,cache-hash-id,wdir-hash-id,通过对比不同区别的id 值来判断文件状态

5 思考/讨论

1、怎么合并tree ,以及找到tree 不同,git怎么决定冲突的?

1、 commit1-tree1,commit2-tree2
2、如果commit1是commit2 的祖先,直接使用commit2-tree2 (直接前驱,使用最新版本,无冲突)
3、commit1 与commit2 不是直接没有直接的祖父关系,则比较 tree1 ,tree2 ,
4、tree1,tree2 上面含有相同的文件路径,但是文件内容不同,则产生冲突。需要手动处理。(无法判断那一次的内容是最新版本,)
5、冲突处理方式, 使用 tree1(ours) ,使用tree2 (others),使用手动处理的版本
6、tree1,tree2 合并后产生一个新的tree-new。

2、git status 显示文件状态依据?

依据working-tree ,index(cache),tree 里面的对应的hash 值来判断。

3、怎么显示增量更新内容?

比较两次提交的tree。

4、 commit 操作具体是如何构建tree 的?

从当前 index 文件 构建tree

5、如何实现 git 与远程分支数量对比,本地落后远程几次提交,本地多于远程几次提交?

1、找到远程head 与本地head 共同的祖先A
2、 [A,remote-head] commit 数量为本地落后远程分支数量
3、 [A,local-head] commit 数量为本地多于远程分支数量
4、 git log 可以实现

6、delta storage VS snapshot storage,snapshot 有何优势 ?

1、snapshot 实现简单,高效(复用已有对象),保留了全部内容。可实现的功能更多
2、delta 模式,记录复杂,实现复杂。
3、delta storage VS snapshot storage:

delta vs snapshot.png

7、javer 如何开发git 适用工具 ?

dea4git 实现:
ProcessBuilder pb = new ProcessBuilder(cmdLine)
执行git 命令
解析git 命令输出结果

8、比较算法为何高效?

tree 比较算法介绍: http://thume.ca/2017/06/17/tree-diffing/
文件比较算法介绍: patience|minimal|histogram|myers https://blog.jcoglan.com/2017/09/19/the-patience-diff-algorithm/

9、如何更改commit 日志信息?

git rebase -i (reword):edit the commits which are rebased
git commit --amend : 修改提交commit-msg
注 amend:修改,修正,git rebase 交互模式详情:https://git-scm.com/docs/git-rebase

10、如何让work-tree clean ,不丢内容?

git stash,将work-dir 内容commit 。并checkout HEAD 内容到working-tree

11、如何debug git ?

1、查看.git/logs/ 目录下面日志 ,git 命令执行日志,不是commit(git log 命令) 日志。
2、使用git core (Plumbing Commands)命令
3、使用debug 选项 git ls-files —debug

12、git gc 与jvm gc 有何异同 ?

jvm gc 基于内存,会涉及内存碎片整理,有多种垃圾处理策略(标记整理,标记复制等)
git gc基于磁盘存储,不用整理磁盘碎片
都是基于tree 来查找垃圾对象

6、参考资料

1、Pro Git :https://git-scm.com/book/en/v2
2、 Manual Page https://git.github.io/htmldocs/
3、Pro Git 作者talk : https://www.youtube.com/watch?v=xbLVvrb2-fY
4、帮助 man git 、 git help [command]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • git 使用笔记 git原理: 文件(blob)对象,树(tree)对象,提交(commit)对象 tree对象 ...
    神刀阅读 3,757评论 0 10
  • 因为原文太长超出字数,Lesson 3 就放在另一篇文章里 How to Use Git and GitHub 标...
    赤乐君阅读 5,175评论 1 5
  • 什么是Git 基于文件快照的分布式版本控制工具 Git基础概念 三个重要的工作区: 数据仓库:保存了所有Git提交...
    无为无味无心阅读 544评论 0 1
  • 1.Git简介 Git是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。Git 是...
    qfstudy阅读 250评论 0 0
  • 看完了《摆渡人》这本书,内心久久不能平静。 如果人生是一条孤独的长河,谁会是你灵魂的摆渡人?我想在我们的一...
    MissS啦阅读 215评论 0 0