标准用法请参考git-scm。本文记录笔者对git的一些理解,如有错误,欢迎指正。
引用内容已用markdown记号标出。版权所有,转载请注明出处。
文章完成中

这是引用内容

First Edition:2021-01-27

文中的记号约定

<当前分支>:用尖括号包裹,需要被替换

软件环境

笔者将介绍 命令行,TortiseGit,VS中git的使用

git学习指引

更适合把git当作某种数据结构来理解,从底层理解git

git中的一些概念

git分支并不是一个实体,而是一个指针,分支只存放了指向某个commit的指针,不保存其他信息。在master分支创建新提交后,分支指针指向为新的commit。

HEAD表示当前指向的位置,master/main一般用于主分支。不要混淆两者概念

working-tree index lib
working-tree为工作目录,即可以直接操作
index,也称stage,git commit将当前index状态保存,即git commit不处理工作目录

git基本命令

  • add 添加文件到index
git add new.txt

  • commit 将当前index提交到Local Repository
git  commit  -m "<这里是commit的注释>"
git  commit  -m "<这里是commit的注释>" --allow-empty //使用此命令学习git分支
git  commit  -m "<这里是commit的注释>" --allow-empty-message -m "" //允许空注释

  • checkout 修改HEAD指针 底层修改 ./git/HEAD
git checkout <指定位置> //修改HEAD 指针到<指定位置>

  • switch 修改HEAD指针,使其指向某个分支而不是某个结点
git switch <分支> //切换到某个分支
//switch与checkout的区别:
//checkout功能更加底层,修改HEAD指针的内容,使其指向branch或者commit
//switch只能指向分支

  • branch 创建分支
git branch new_branch //新建分支new_branch

  • reset 修改当前分支的指针 底层修改文件 ./git/refs/head/<分支名>
git reset ad13f1 //修改当前分支的指针
//git reset与checkout的区别
//git reset不修改HEAD指针,修改当前分支指向的commit
//git checkout修改HEAD指针

git指令

git rebase
git revert
git reset
git checkout
git merge
git cherry-pick

git merge命令
当前工作再branch_master分支,此分支指向commitA,develop分支指向commitB,(AB字母仅供标识,没有其他含义)。使用指令git merge develop,创建一个新的commitC,commitC以commitA和commitB为父结点。再次强调,git的分支是一个指针,存放在./git/refs文件夹下。分支所包含的结点是以类似链表的方式的进行查找的,并不是线性记录在某个文件中。
git中删除分支并不会直接删除commit object,不过分支指针丢失了,难以进行查找,并且git有gc垃圾回收机制,会清理悬挂对象。(git误操作后恢复数据原理,分支指针被清除,对象并未清除,而且在./git/logs文件夹内有日志。) git fsck 命令验证数据库中对象的连通性和有效性。
git revert命令
当前master分支有commitA commitB commitC
使用git revert commitA命令生成commitD,commitD的父节点为commitC,commitD的内容与A一致,但并不破坏历史记录.
注:git对象是以链表的形式组织。链表上的结点不能自由移动,但可以对读取结点上的内容,创建新结点,这看起来像是回到了某次提交。
git reset命令
修改当前分支指向的结点(分支指针总是指向该分支的最后一个结点,或者说分支指针记录了该分支最后一个结点,checkout命令是移动HEAD指针)
当前master分支有commitA commitB commitC
git reset commitA后,如果没有分支线包含commitB,commitC,那么B、C不会显示在git log中(因为git log是动态搜索),B、C可能会被清除。
注:git使用链接式的数据结构。
git cherry-pick命令

git区域

这几个区域是使用概念上的区别。
git Working-Tree 即工作文件夹
git index index区内容,注意这里不是空的,使用git add 命令,将file1添加到object和index内。
git commit区域 git commit将index内容打包到tree obejct,建立commit object,修改当前分支的指针,在logs文件夹内写入HEAD和当前分支的变更日志。
在git中,数据存放在以sha1为键名的数据库中,以链表方式组织数据。这样数据更加灵活。
git reflog是保存到本地的,不保存到远程。git log是动态计算的

git对象 blob tree commit
git引用 分支引用 HEAD引用 标签引用 远程引用
git本地的远程分支也仅保存指针,不保存数据。数据保存在object中。远程分支标记了commit object。(由于sha1的特点,一般地,不同的文件不会具有相同的sha1)

Git分支与数据不直接关联。
数据中文件内容和文件元信息不直接关联。
commit不和文件直接关联。
远程分支建立在本地objects上,而不是简单粗暴地下载远程文件与本地文件比对。
git fetch操作是下载远程分支所关联地object(如果有某个结点有两个父节点,那么这两个方向的结点都会被下载),然后下载远程分支指针。
git是以节点链表为核心,不是以孤立的分支为核心。
git保证了与分支所关联的commit可以被安全保存。
patch分支修改了某项功能,随后在master分支上merge patch分支,删除patch分支。这三个节点都得到了保留。

附加:
TortiseGit

文件修改 文件增加 文件删除 文件重命名

git演示1

  1. 新建仓库
  • 命令行中git init
  • TortiseGit ,右键菜单Create repo
  • vs中 (待补充)
  1. 创建文件
  • 手动新建文件
  • 或者 echo “<字符>” >> new.txt
  • 或从 touch new.txt (windows下可能没有此命令)
    打开文件,写入new conent并保存
    注意:此时 ./.git/objects文件夹内并没有生成对应的文件
  1. 将文件添加到index git add new.txt
    注意./git/objects/文件夹内变化,增加了名为47的文件夹

查看该文件夹的内容

使用git底层命令查看该文件的内容git cat-file -p 47d2739ba2c34690248c8f91b84bb54e8936899a

使用同样的方法创建new.txt文件,并将其添加到index。在objects内生成了23/b6fc220420f74c5af7f34c106ef931a1fa15ea文件

注:47d2739ba2c34690248c8f91b84bb54e8936899a为内容的sha1,实际上objects文件夹为数据库,sha1与内容构成了键值对,按照<前2位sha1>/<后38位sha1>的方式存储。

注:将文件提交到index后,new.txt文件的内容已经被保存到了数据库中。即git add的作用并不是仅对文件做标记,而是将其内容保存到数据库中。可以将其分解为底层命令git hash-object,并未保存树对象
4.提交index到Local Repo

git commit -m "First Commit"

此时,查看objects文件夹的内容

新增了5d/ d4/文件夹
查看5d文件夹下新增文件的内容
使用git cat-file -p <sha1>指令查看新增objects的内容
使用git cat-file -t 指令查看新增objects的类型

查看d4文件夹下新增文件的内容

查看refs/heads文件夹

查看master文件的内容

发现其内容与新增的commit object的sha1一致。

总结:使用git commit指令后 objects内新增两个文件,分别为tree object,commit object。refs/heads文件夹内分支指针内容被改写。

  1. 查看当前HEAD指针的内容,HEAD指针指向了master分支
    注:HEAD 与heads不同

6.继续测试,使用git commit --allow-empty -m "empty commit"指令进行一次空提交
注:使用windows下软件everything 可以查看新增加的文件
以下文件的修改时间与刚才的操作时间匹配

分别为:

  • ./refs/heads/master
  • /logs/refs/heads/master
  • /logs/HEAD
  • 新增的object
  • COMMIT_EDITMSG (猜测,此文件可能供git comment --amend 选项使用)
    查看master文件内容,发现其指向了新的commit object
    logs文件夹内,有两个文件发生了变化
    查看HEAD文件内容,记录了HEAD指针的变化,新记录增加到文件末尾。第一个sha1值表示父commit,第二个sha1表示当前的commit。第一次提交没有父commit,所以用全0的sha1值表示。

查看master文件内容,记录了master指针的变化,新记录增加到文件末尾

使用git log命令

其内容与logs内文件内容相似,不过最新的提交在顶部,从新到旧。
使用命令git reflog

记录了HEAD指针的变化。
注:HEAD@{N}表示HEAD之前的值

提问:logs记录的日志是否供git使用
验证:将logs文件夹移动其他位置,运行git log指令和git reflog指令
运行git log指令,变更内容仍可输出
运行git reflog指令,无内容输出。
将logs文件夹移回,git reflog命令可正常使用
总结:git log遍历objects来建立日志,git reflog查询.git/logs文件夹下内容

注:git中箭头含义,箭头表示指向该节点,不能把箭头当作时间方向

TortiseGit介绍

学习指导:要从底层理解Git工作原理,将高层指令细分了若干低层操作。Git指令过多,且指令效果复杂,如果把Git当作黑箱,则有些功能难以理解。从Git的基本工作原理入手

Git Commit

这里ReCommit表示完成此次提交后不关闭当前窗口,可进行下一次提交。(与amend last commit不同)

Set author
Set author date 在Message中添加作者和日期。
Amend Last Commit (git commit --amend 修改上次提交)

Show Unversioned Files 是否显示未受版本控制的文件
Message only 只提交Message,不提交文件

show log同git log
show reflog 同git reflog
Browser References:浏览引用,即浏览分支
Revision graph,显示修订版本图(从图中也可以看出,分支只是指针,不是分支实体)

Repo Browser 仓库浏览器,可快速查看不同修订版本的内容,不需要修改Working-Tree内容。

git底层命令

git hash-object 写入object
git write-tree 将index内容写入一个树对象
git update-index 更新index
git cat-file [-p] [-t] [-s](pretty-print type size 查看文件

git 内部原理分析(参考git-scm)

https://git-scm.com/book/zh/v2/Git-内部原理-底层命令与上层命令

1. git命令

分为底层命令(plumbing),上层命令(porcelain)

2. git文件目录

(注意,info/ 表示文件夹 HEAD 表示文件。根据末尾的/来区分文件和文件夹)config(config 文件包含项目特有的配置选项)description(仅供 GitWeb 程序使用)HEAD(HEAD指针,指向目前被检出的分支hooks/(包含客户端或服务端的钩子脚本)info/(目录包含一个全局性排除(global exclude)文件, 用以放置那些不希望被记录在 .gitignore 文件中的忽略模式(ignored patterns)objects/(目录存储所有数据内容)refs/(存储指向数据(分支、远程仓库和标签等)的提交对象的指针)index(文件保存暂存区信息)

3. git对象

  • git对象(object)存放在./git/object/ 文件夹。以<hash的前两位>/<hash的后38位>的结构存储
  • 对象分为 数据对象(blob object),树对象(tree object),提交对象(commit object)
  • 数据对象仅保存了文件的内容,没有保存文件名。
    • git cat-file -p <指定的sha1> 从Git中取回数据(-p 表示pretty-print 自动判断类型 -t表示查看object的类型
    • git hash-object -w test.txt 将test.txt写入Git
  • 树对象(tree object)

    • 树对象将文件组织到一起,一个树对象包含了一条或多条树对象记录。每条记录含有一个指向数据对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息 * Git 根据某一时刻暂存区( index 区域,也称为stage区域,使用git
      add命令后文件被添加到这里)所表示的状态创建并记录一个对应的树对象。 * 底层命令 git
      update-index,必须为上述命令指定 --add
    • 文件模式为 100644,表明这是一个普通文件。 其他选择包括:100755,表示一个可执行文件; 120000,表示一个符号链接
    • git write-tree 命令将暂存区内容写入一个树对象
  • 提交对象(commit object)

    • 调用 commit-tree 命令创建一个提交对象。为此需要指定一个树对象的 SHA-1 值,以及该提交的父提交对象(如果有的话)。
    • 如果你做完了以上所有操作,那么现在就有了三个树对象,分别代表我们想要跟踪的不同项目快照。 然而问题依旧:若想重用这些快照,你必须记住所有三个 SHA-1 哈希值。
      并且,你也完全不知道是谁保存了这些快照,在什么时刻保存的,以及为什么保存这些快照。 而以上这些,正是提交对象(commit
      object)能为你保存的基本信息。
    • 提交对象 保存tree的sha1值,作者,保存时间,提交备注
    • 提交对象类似于数据结构中链表的结点,保存自身信息和父节点的位置

总结

  1. git blob object保存文件内容,tree object保存文件元信息以及目录信息,commit tree保存提交信息。
  2. 此时,通过object的sha1来查找object,未对object进行标注。

4.git引用(references,简写为refs)

笔者注:git引用可以理解为C语言的指针,指向某个地址。引用存放在.git/refs/heads/
对分支进行操作时就是在操作【references】
如果想更新某个引用,Git 提供了一个更加安全的命令 update-ref 来完成此事:
Git 分支的本质:一个指向某一系列提交之首的指针或引用。

HEAD 引用

HEAD 文件通常是一个符号引用(symbolic reference),指向目前所在的分支。 所谓符号引用,表示它是一个指向其他引用的指针。

标签引用

然而实际上还有第四种。 标签对象(tag object) 非常类似于一个提交对象——它包含一个标签创建者信息、一个日期、一段注释信息,以及一个指针。 主要的区别在于,标签对象通常指向一个提交对象,而不是一个树对象。 它像是一个永不移动的分支引用——永远指向同一个提交对象,只不过给这个提交对象加上一个更友好的名字罢了。

远程引用

远程引用是只读的。 虽然可以 git checkout 到某个远程引用,但是 Git 并不会将 HEAD 引用指向该远程引用。因此,你永远不能通过 commit 命令来更新远程引用。 Git 将这些远程引用作为记录远程服务器上各分支最后已知位置状态的书签来管理。

参考资料

  1. https://git-scm.com

git查看分支记录_git原理相关推荐

  1. git 查看分支创建时间

    git 查看分支创建时间 git reflog show --date=iso <branch name> 可以查看到指定分支的历次更改记录,最下面一条的时间即是分支创建时间.

  2. Git查看分支从哪个分支创建的

    使用命令 Git查看分支创建时间 git reflog show --date=iso <branch name> 如果是feature分支 git reflog show --date= ...

  3. git 查看分支编码_12个常用的Git命令,赶紧记一波!

    今天齐姐简单讲下 Git 的实现原理,知其所以然才能知其然:并且梳理了日常最常用的 12 个命令,分为三大类分享给你. 本文的结构如下: 作者和开发原由 Git 的数据模型 常用命令 资源推荐 作者和 ...

  4. git 查看分支_系统掌握Git之—探索.git

    文章概述 上文中,我们聊了聊git的配置与一些基本概念,今天来看看.git文件夹里面有什么内容.通过阅读本文,你将获得下面的知识: .git的内部信息. git的分支操作. 图形化git工具. 新建分 ...

  5. git查看分支与切换分支

    git branch -a 1.查看所有分支 切换分支 git checkout 分支名 https://www.cnblogs.com/vae860514/p/11009787.html

  6. git查看分支、创建分支、合并分支

    一.查看的git命令如下: git branch 列出本地已经存在的分支,并且当前分支会用*标记 git branch -r 查看远程版本库的分支列表 git branch -a 查看所有分支列表(包 ...

  7. Git查看分支创建时间

    实际应用中,可能需要准确知道指定分支的创建时间. 代码实例如下: git reflog show --date=iso mastergit reflog show --date=iso ####### ...

  8. git 移动分支指针_git 分支( branch ) 的基本使用

    分支( branches ) 是指在开发主线中分离出来,做进一步开发而不影响到原来主线. Git 存储的不是一系列的更改集( changeset ),而是一系列快照.当你执行一次 commit 时, ...

  9. git查看分支 -切换分支

    1.查看当前分支 git branch -a 2.查看本地分支 git branch 3.切换分支到test git checkout test 4.克隆项目 git clone 项目地址

最新文章

  1. 【Linux探索之旅】第二部分第五课:用户和权限,有权就任性
  2. 对于jQuery的初步印象
  3. Mysql5.7版本ERROR 1055问题
  4. 我的Ubuntu9.10安装与配置100
  5. 不能执行autowired_想用@Autowired注入static静态成员?官方不推荐你却还偏要这么做...
  6. STM32 进入Stop模式后电流还是很大怎么办?
  7. Excel图表横坐标设置怎么做?(亲测)
  8. java jdbc 删除_java使用jdbc实现各种类型添加删除修改数据
  9. netbeans java9_Java 开发新选择?Apache NetBeans IDE 9.0 备受好评
  10. 安装Python3.5后,pip报错Fatal error in launcher: Unable to create process using ‘“‘解决方案
  11. Cookie编码解码
  12. Linux下tomcat的catalina.out文件过大,以及目录更改解决办法
  13. SoapUI 入门指南
  14. [阅读笔记]专访刘毅:阿里巴巴云计算平台运维故障分析与排查
  15. R语言使用aggregate函数和median函数计算每个分组数据的中位数
  16. 【JAVA问题解决方案】01.EasyExcel导出数据超过Excel单表上限解决方案
  17. STM32F103_study69_The punctual atoms(STM32 SPI communication principle and configuration)
  18. 选购发烧游戏台式计算机的内存储器,游戏发烧友福音 惠普暗影精灵5 Super游戏台式电脑评测...
  19. mysql jail_FreeNAS:如何在Jail里面安装软件?
  20. Kettle Carte模式

热门文章

  1. 畅享云游戏,AWS云峰会邀你零距离体验强化学习!
  2. 从ICLR 2020、AAAI 2020看对话系统近期研究进展
  3. KDD 2019 | 使用神经网络为A*搜索算法赋能:以个性化路径推荐为例
  4. web公选课js基础Part1
  5. 06 | 全局锁和表锁 : 给表加个字段怎么有这么多阻碍
  6. SpringMVC中注解的使用
  7. 计算机IO系列「一」零拷贝技术
  8. mysql合并表中的数据
  9. Spring Security OAuth2——自定义OAuth2第三方登录(Gitee)
  10. PaddleLabel——重新识别失败【Can not recognise the detection box in 文件. Please change manually 】解决方案