Skip to content

Latest commit

 

History

History
85 lines (51 loc) · 4.17 KB

36.精读when you Git in trouble.md

File metadata and controls

85 lines (51 loc) · 4.17 KB

036.精读《When You “Git” in Trouble- a Version Control Story》.md

git 作为现在最流行的版本控制系统,管理庞大的实际软件项目,通过实际例子描述,使用 git 对项目进行有效的维护,分享 git 使用经验和 git 内部实现机制

实际场景

  • 对于丢失的 commit 信息找回,需要找出这些 commit 的 SHA,然后添加一个指向他的分支

    • git 会记录下每次修改 HEAD 的操作,执行和提交或者修改分支的命令时 reflog 就会更新(git update-ref 也可以更新 reflog),也可以执行 git reflog 查看当前状态

    • $ git reflog
      1a410ef HEAD@{0}: 1a410efbd13591db07496601ebc7a059dd55cfe9: updating HEAD
      $ git log -g 查看更详细的reflog日志
    • # 确定丢失commit之后,可以在commit上创建一个新分支将其恢复,在commit(1a410ef)创建new-branch分支,即可找回丢失的commit数据
      $ git branch new-branch 1a410ef
      $ git log --pretty=online new-branch 
    • 如果引起的 commit 丢失原因没有记录在 reflog 上,即没有在.git/logs/上,导致丢失的 commit 不被任何东西引用,这是可以执行 git fsck --full,检查仓库完整性,显示其他所有未被其他对象引用的所有对象

    • $ git fsck --full
      dangling blob d670460b4b4aece5915caf5c68d12f560a9fe3e4
      dangling commit ab1afef80fac8e34258ff41fc1b867c702daa24b
      dangling tree aea790b9a58f6cf6f2804eeac9f0abbe9631e4c9
      dangling blob 7108f7ecb345ee9d0084193f147cdad4d2998293
    • 这样可以从 dangling commit 中找到丢失的 commit 信息, 确定丢失的 commit 信息之后,可以在这个 commit 上创建一个新分支将其恢复过来

git fsck

  • blob、commit 、tree 等关键字分析 git 内部数据化结构管理机制

    • git 版本控制实际是对文件进行管理和控制,管理方法就是对每个文件生成(key,object)结构,并且利用 SHA-1 算法对每一个文件生成唯一字符序列 hash_key,文件改变就会触发 hash 的更新

    • 通过 git init 初始化一个本地仓库,查看隐藏的.git 目录,objects 下有 info 和 pack 两个空文件夹,没有其他任何文件

    • blob 对象(记录文件内容)

      • 在项目仓库中添加了一个文件后,执行 git hash xxx.js,会生成一个 40 字符长度的 hash-key 序列,执行 git add xxx.js 后,objects 会多出一个 08 对象:

      • 40 位 hash_key 前两位作为目录名(08)后 38 位作为文件名,对象里面存放 xxx.js 的内容。可以查看对象的内容和类型

      • git cat-file -p [hash_key] // 内容
        git cat-file -t [hash_key] // 类型
        
    • tree 对象(目录结构)

      • tree 对象可以理解成储存目录,节点信息包括文件名。hash_key,文件类型,权限等,起到组织整个需要控制文件结构的作用,tree 对象是在 commit 的过程中生成的,会根据.git 目录下的 index 文件的内容来创建, git add 的操作就是将文件的信息保存到 index 文件中去,commit 时根据 index 内容生成 tree 对象

      • git cat-file -p main^[tree] // 后面的是main分支指向的tree对象
      • Tree --> Tree(目录路径) --> Blob OR 在根目录上没有 Tree 目录路径(~)

    • commit 对象(工作目录 tree 以及提交历史)

      • 执行 git commit 对象时才会根据 index 生成 tree 对象,commit 对象中有两个内容

        1. 代表项目目录 tree 对象的 key
        2. 上一个 commit 的 key
      • 每个 commit 对应的 key 前两位分别对应 objects 目录下的文件夹(65),他指向项目目录 tree 以及上一次的 commit,如果是第一个 commit 的话就不存在上一个

      • objects 结构

        commit(key) --> tree (program key)--> tree(dir key) --> blob

      • commit 对象指向工作目录 tree,只要切换 commit 就可以随意切换对应的版本内容,也就是切换到.git/object/下的不同目录的文件

summary

  • 对于使用 git 维护丢失的 commit 入手,带出 git 的工作流程和整体的数据结构管理,给与对应的解决思路和方案