撤销rebase与git原理
git对象
git是面向对象的,对象存储在.git/objects文件夹中。此文件夹中,一个对象就是一个文件,文件名就是对象的id
提交commit的时候,每个文件都是一个数据对象,一个树对象会用来维护一次提交的所有数据对象,如果提交的内容包含文件夹,那么这个文件夹也会是一个树对象
一次提交就是一个提交对象,这个对象包括了表示此次提交所有数据对象的树对象,以及对上一个提交对象的指针
# -t 打印对象类型;-p 打印对象内容
$ git cat-file -t 458ed8e
commit # 458ed8e是一个提交对象
$ git cat-file -p 458ed8e
tree 0ce2ac7bb5b76a74a03d1af4b3b87337ecb15e88 # 本次提交的树对象
parent dd5736397cacc07ba8fbf73201a53a0d733063b2 # 上一个提交对象的指针
author luozixi <luozixi@xxx.net> 1592392241 +0800
committer luozixi <luozixi@xxx.net> 1592392241 +0800
fix
$ git cat-file -t 0ce2ac7bb5b76a74a03d1af4b3b87337ecb15e88
tree # 查看本次提交的树对象类型
$ git cat-file -t dd5736397cacc07ba8fbf73201a53a0d733063b2
commit # 查看上一个提交对象的类型
$ git cat-file -p 0ce2ac7bb5b76a74a03d1af4b3b87337ecb15e88
100644 blob d45dda6a2a0d66f808c4999bb2b54ff0d931dde4 .editorconfig
040000 tree dc8ccda293623ed2a7f173c0c9714e95044a9125 utils
# 本次提交的树对象中,有一个数据对象(对应文件)和一个树对象(对应文件夹)
git指针
所有的分支和标签都是指向提交对象的指针
所有的本地分支指针都存储在 git/refs/heads 目录下,每一个分支对应一个文件,文件的内容就是本地分支最后一次提交的提交对象
$ cat .git/refs/heads/feature/feature1
458ed8e77466a5f5be0167ab7ab8977060ec21cf
HEAD指针,是一个指向指针的指针
$ cat .git/HEAD
ref: refs/heads/feature/feature1
它指向了feature/feature1的分支指针存储位置,而分支指针又指向分支最后一次提交的提交对象,所以说HEAD是一个指向指针的指针
它的作用是标识当前使用的是那个分支,使用git checkout切换分支的时候,实际上就是修改了HEAD指针的值
checkout和reset的区别:这两个命令都会改变 HEAD 的指向,区别是 checkout 不改变 HEAD 所指向的分支指针的指向,而 reset 会
git日志
.git/logs/HEAD文件记录了HEAD指针的变更记录
.git/logs/refs/heads则记录了所有分支指的变更记录
使用$ git reglog指令实际上就是读取了.git/logs/HEAD这个文件
而$ git log指令就不是直接读取文件了,这个指令的输出是由分支所指的提交对象一层层向前找父提交对象绘制而成的
撤销rebase
git中并不存在某次提交时的分支快照
但是通过HEAD的变更记录,我们可以找到rebase之前当前分支所指的提交对象,然后使用reset将当前分支指向那时的提交对象就可以了
$ git reset --hard HEAD@{30}
HEAD@{30}是需要回退的提交对象的简写
执行这个操作之后,可以发现HEAD的日志里多了一行
HEAD@{0}: reset: moving to HEAD@{30}
查看当前分支的日志,可以发现很有趣的事情:
0000000000000000000000000000000000000000 c77a9670c5cfdb8abd0ea05fdc4bfe71725c8ff4 luozixi 1591684691 +0800 branch: Created from develop
...
dd5736397cacc07ba8fbf73201a53a0d733063b2 458ed8e77466a5f5be0167ab7ab8977060ec21cf luozixi 1592392241 +0800 commit: fix
458ed8e77466a5f5be0167ab7ab8977060ec21cf b271f35c4e9552d23669a05509067a3cd8b7dd03 luozixi 1592536842 +0800 rebase finished: refs/heads/feature/feature1 onto e5168c3c5e2f8219e51ede4ccd40136e2f69777b
b271f35c4e9552d23669a05509067a3cd8b7dd03 458ed8e77466a5f5be0167ab7ab8977060ec21cf luozixi 1592538987 +0800 reset: moving to HEAD@{30}
每一行的第一个位置是移动分支指针前分支指针指向的提交对象的id,第二个位置是当前分支指针指向的提交对象的id
可以看到日志的一开始,父对象的id是全0的,这是所有分支的起点
458ed8e77466a5f5be0167ab7ab8977060ec21cf是此分支最后一次提交,然后就进行了rebase操作
rebase finished: refs/heads/feature/feature1 onto
e5168c3c5e2f8219e51ede4ccd40136e2f69777b
这个e5168c3c5e2f8219e51ede4ccd40136e2f69777b正是rebase目标分支(debelop)所指提交对象的id,即develop最新的提交
最后,我们执行了reset操作,使feature1的分支指针再次指向了458ed8e77466a5f5be0167ab7ab8977060ec21cf,即此分支的最后一次提交
git log里也没有了rebase的相关提交信息
那么表示rebase操作的b271f35c4e9552d23669a05509067a3cd8b7dd03这个提交对象消失了吗?
$ git cat-file -p b271f35c4e9552d23669a05509067a3cd8b7dd03
tree 1ee51eedb07f6ac0144e590668977eb19696a2c8
parent 64a34f53657544530961c8aadcf60091e3912b74
author luozixi <luozixi@xxx.net> 1592392241 +0800
committer luozixi <luozixi@xxx.net> 1592536842 +0800
可以看到,它没有消失,其实rebase之后形成的所有提交对象都没有消失,只不过已经没有分支指针指向它们了,它们变成了不可见的对象,也就是悬空对象(dangling objects)
如果我们还想再找回它们,去log里找到它的id就行
如果需要彻底删除这些悬空对象,见:http://liuhui998.com/2010/11/06/remove_commits_completely/
参考资料
https://juejin.im/post/5a65ac67f265da3e330473f7
撤销rebase与git原理的更多相关文章
- Git原理与命令大全
Git (wiki: en chs )是一个免费开源的分布式版本控制系统,由linux内核作者linus Torvalds开发,大型开源项目linux kernel.Android.chromium ...
- Git原理入门简析
为了获得更好的阅读体验,建议访问原地址:传送门 前言: 之前听过公司大佬分享过 Git 原理之后就想来自己总结一下,最近一忙起来就拖得久了,本来想塞更多的干货,但是不喜欢拖太久,所以先出一版足够入门的 ...
- Git原理入门解析
前言: 之前听过公司大佬分享过 Git 原理之后就想来自己总结一下,最近一忙起来就拖得久了,本来想塞更多的干货,但是不喜欢拖太久,所以先出一版足够入门的: 一.Git 简介 Git 是当前流行的分布式 ...
- git rebase 与git merge 小结
git merge是用来合并两个分支的. $ git merge b 将b分支合并到当前分支 同样 $ git rebase b ,也是把 b分支合并到当前分支 ---------------- ...
- git原理学习记录:从基本指令到背后原理,实现一个简单的git
一开始我还担心 git 的原理会不会很难懂,但在阅读了官方文档后我发现其实并不难懂,似乎可以动手实现一个简单的 git,于是就有了下面这篇学习记录. 本文的叙述思路参照了官方文档Book的原理介绍部分 ...
- Git原理及常用操作命令总结
git原理介绍及操作 git 原理——
- Merge和Rebase在Git中的区别
git命令Merge和Rebase的区别 git merge 会生成一个新得合并节点,而rebase不会 比如: D---E test / A---B---C---F master 使用merge合并 ...
- git rebase和git merge的用法
http://softlab.sdut.edu.cn/blog/subaochen/2016/01/git-rebase%E5%92%8Cgit-merge%E7%9A%84%E7%94%A8%E6% ...
- git rebase vs git merge详解
https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa#.std3ddz0g 请参考另外一篇文 ...
随机推荐
- dpwwn-02靶机渗透
dpwwn-02靶机渗透 将两台机器都配置为net模式. 进行一下内网扫描: 发现主机10.10.10.10,进行端口扫描. 发现有80,111,443,2049等端口开放,443值得注意. 访问网站 ...
- 转载:pycharm IDE 导入自定义模块
http://www.mamicode.com/info-detail-2241193.html
- 手对手的教你用canvas画一个简单的海报
啦啦啦,首先说下需求,产品想让用户在我们app内,分享一张图片到微信.qq等平台.图片中包含用户的姓名.头像.和带着自己信息的二维码.然后,如何生成这张海报呢~~~首先我们老大告诉我有一个插件叫htm ...
- Centos-显示或修改系统时间与日期-date
date 显示或者修改系统时间与日期,只有超级用户才能用date命令设置和修改时间,普通用户只能显示时间 相关参数 -s 设置设置时间,格式为 Y-m-d H:M:S -d 对日期进行运算, + ...
- KEIL查看ARM-Cortex M架构soc的内核寄存器之 MSP
参考下图stm32l475的参考手册: MSP指向地址基地址为0x20000000的内存处.参考STM32L475的memory map可知MSP指向的是SRAM的一块地址.并且由上面的编译信息 ...
- Java知识系统回顾整理01基础01第一个程序02命令行格式编译和执行Java程序
一.先看运行效果 在控制台下运行第一个Java程序,可以看到输出了字符串 hello world 二.准备项目目录 通常都会在e: 创建一个project目录 在这个例子里,我们用的是e:/proje ...
- 《穷查理年鉴》诚实 & 希望 & 勇气 & 失败 & 改变(关于美好)
诚实 013.自欺是最常见的欺骗. 038.毫无顾忌进行欺骗的人是无所畏惧的. 043.问心无愧者永无所惧. 068.诚实的人从欺诈人手中得到的买卖,我们从争论中得到真理. 134.没有欺骗就没有信任 ...
- Lane-Detection 近期车道线检测论文阅读总结
近期阅读的几篇关于车道线检测的论文总结. 1. 车道线检测任务需求分析 1.1 问题分析 针对车道线检测任务,需要明确的问题包括: (1)如何对车道线建模,即用什么方式来表示车道线. 从应用的角度来说 ...
- 成理信安协会反序列化01-利用fastcoll实现md5碰撞
虽然是反序列化的题目,但主要考点在利用fastcoll实现md5碰撞. 直接上源码 <?php show_source(__FILE__); class CDUTSEC { public $va ...
- Eating Peach (peach)
Description On this day, the little monkey went looking for food. He came to a rectangular peach gar ...