rebase失败后的恢复

记一次翻车现场

记一次翻车的现场,很早之前提的PR后面由于需求的变便去忙别的事情了,等到要做这个需求的我时候,发现已经 落后版本了,并且有很多文件的冲突,然后就用rebase去拉代码解决冲突,然后解完之后推代码,但是之后发现一 个文件在解决冲突的时候丢失了。这时候去查看git提交历史,发现rebase之后找不到这个文件了。

最后如何解决呢,要是把丢失的文件在写一遍,那就真的变成了一名咸鱼了。这时候我们就需要去弄明白rebase 的原理了。

rebase的使用流程

rebase就是把主分支的最新代码拉取自己当前的开发分之上,只不过使用rebase,会形成 更加干净的git线。

那么它的使用流程:

基于forked模式的开发。

、forked代码仓库
、 git clone <个⼈仓库地址>
、 添加远程仓库
git remote add remote <远程仓库地址>
、 查看远程仓库版本
git remote -v
、 rebase
git pull remote master --rebase
、 遇到冲突
git add .
git rebase --continue
git push -f origin XXXXX

rebase失败如何恢复

使用reflog撤销变基

$ git reflog
8c79a588 HEAD@{}: checkout: moving from JM- to JM-
e7b1f794 HEAD@{}: checkout: moving from JM- to JM-
97c945d8 HEAD@{}: commit: fix response
HEAD@{}: commit: sql的整理
427423c2 HEAD@{}: checkout: moving from master to JM-
438a1d75 HEAD@{}: rebase finished: returning to refs/heads/master
438a1d75 HEAD@{}: pull remote master --rebase: checkout 438a1d75c4faf8056216980d6538de1fe11e0e4e
753e6308 HEAD@{}: checkout: moving from JM- to master
427423c2 HEAD@{}: rebase finished: returning to refs/heads/JM-
427423c2 HEAD@{}: rebase: 外审整改计划修改文档的命名
HEAD@{}: rebase: 外审整改计划导入的细节部分修改,增加条款信息的查询
c8b18fc1 HEAD@{}: pull remote master --rebase: 为甚整改计划修改文档的命名
9e1450c4 HEAD@{}: pull remote master --rebase: 外审整改计划增加条款项的查询
c25f7ab4 HEAD@{}: pull remote master --rebase: 修改参数的大小写问题
b16eb983 HEAD@{}: pull remote master --rebase: 外审整改计划添加详情添加外审计划的信息
c5519548 HEAD@{}: pull remote master --rebase: 外审整改计划添加是否关联不符合项的查询条件
29819e65 HEAD@{}: pull remote master --rebase: 外审整改计划修改修改测试文件
4e3a6084 HEAD@{}: pull remote master --rebase: 外审整改计划修改添加文件上传的功能
2e516dfa HEAD@{}: pull remote master --rebase: 外审整改计划修改count的查询方式
8e970d7c HEAD@{}: pull remote master --rebase: 外审整改计划初步提交
1e0fa8b3 HEAD@{}: pull remote master --rebase: sql
9c384393 HEAD@{}: pull remote master --rebase: checkout 9c384393b1913f67c4eef633ecdeaa23cc4ce397
8b9129ed HEAD@{}: checkout: moving from JM- to JM-
8c79a588 HEAD@{}: commit: 修复外审计划错误的查询
9a08a751 HEAD@{}: commit: fix test response
HEAD@{}: commit: code review修改导出的状态码
6b5e693f HEAD@{}: commit: code review调整错误的返回的位置
010c7c8e HEAD@{}: commit: code review代码细节修改
deca577b HEAD@{}: commit: code review代码细节修改
874fed06 HEAD@{}: commit: 修改导入的模板的路径
9607489f HEAD@{}: rebase finished: returning to refs/heads/JM-
9607489f HEAD@{}: rebase: 包资源的替换
a4f5fb85 HEAD@{}: rebase: 包资源的替换

上面是所有的日志 我们可以逐条分析,找到我们rebase的节点 只要输入下面的命令就好了

git reset --hard HEAD@{}

或者

git reset --hard 

rebase使用的意义

使用rebase的提交历史

对比merge

使用rebase会得到一个干净的,线性的提交历史,没有不必要的合并。 使用merge能够保存项目完整的历史,并且避免公共分之上的commit。

rebase工作的原理

为了弄清楚rebase的原理,首先需要弄清楚git的工作原理。

git工作原理

首先我们先来了解下git的模型。 首先我们可以看到在每个项目的下面都有一个.git的隐藏目录

关于git的一切都存储在这个目录里面(全局配置除外)。这里面有一些子目录和文件, 记录到了git所有的信息。

文件里面存储的都是一些配置文件:

  • info:初始化时只有这个文件,用于排除提交规则,与 .gitignore 功能类似。他们的区别在 于.gitignore 这个文件本身会提交到版本库中去,用来保存的是公共需要排除的文件;而info/exclude 这里设置的则是你自己本地需要排除的文件,他不会影响到其他人,也不会提交到版本库中去。

  • hooks:这个目录很容易理解, 主要用来放一些 git 钩子,在指定任务触发前后做一些自定义的配置,这 是另外一个单独的话题,本文不会具体介绍。

  • objects:用于存放所有 git 中的对象,里面存储所有的数据内容,下面单独介绍。

  • logs:用于记录各个分支的移动情况,下面单独介绍。

  • refs:用于记录所有的引用,下面单独介绍。

  • HEAD:文件指示目前被检出的分支

  • index:文件保存暂存区信息

git对象

git是面向对象的!

举个栗子

假如我们init了一个新的仓库,然后提交了两个文件,那么会有那些对象呢?

$ git init
$ echo 'aaaaa'>a.txt
$ echo 'bbbbb'>b.txt
$ git add *.txt

上面提交了两个文件到了暂存区,我们了解到对象都存储在object文件夹中,那我们去到里面看下。

$ tree .git/objects
.git/objects
├── cc
│ └── c3e7b48da0932cc0f7c4ce7b4fd834c7032fe1
├── db
│ └── 754dbd326f1b7c530672afbbfef8d9223033b7
├── info
└── pack

git cat-file [-t] [-p] 号称git里面的瑞士军刀,我们来剖析下,t可以查看object的类型,-p可 以查看object储存的具体内容。

$ git cat-file -t ccc3e
blob
$ git cat-file -p ccc3e
aaaaa

可以发现object是一个blob类型的节点,内容是aaa,这就是object存储的内容

这里我们遇到了第一种Git object,blob类型,它只储存的是一个文件的内容,不 包括文件名等其他信息。然后将这些信息经过SHA1哈希算法得到对应的哈希值 ccc3e7b48da0932cc0f7c4ce7b4fd834c7032fe1 ,作为object在git中的唯一身份证。

然后我们进行一次commit

 git commit -am '[+] init'
[master(根提交) d290482] [+] init
files changed, insertions(+)
create mode a.txt
create mode b.txt

再次查看object

$ tree .git/objects
.git/objects
├── 3b
│ └── e060dffd163e01ca6f44dfc6746dda5ae19d5d
├── cc
│ └── c3e7b48da0932cc0f7c4ce7b4fd834c7032fe1
├── d2
│ └── 904827c81ba3c05072d66d1dd466e01bcdee69
├── db
│ └── 754dbd326f1b7c530672afbbfef8d9223033b7
├── info
└── pack
里面变成了四个对象了

让我们‘瑞士军刀’剖析下

$ git cat-file -t 3be0
tree git cat-file -p 3be0
blob ccc3e7b48da0932cc0f7c4ce7b4fd834c7032fe1 a.txt
blob db754dbd326f1b7c530672afbbfef8d9223033b7 b.txt

我们发现这里出现了另一种object类型-tree。它将当前的提交目录打了一个快照,存储了当前提交的目录结构。

再看下两一个object里面的信息

$ git cat-file -p d2904
tree 3be060dffd163e01ca6f44dfc6746dda5ae19d5d
author liz <rick.lizhan@gmail.com> +
committer liz <rick.lizhan@gmail.com> +

里面存储的是提交者的信息

那么有一个问题,一次commit生成的快照是全局的还是提交部分的呢? 我们再来看。 修改a.txt,然后提交,看看新的提交

修改a.txt文件里面的内容为
aaaaa
aaaaa

提交commit

$ git commit -am '[+] init'
[master f5af32c] [+] init
file changed, insertion(+)

我们再次打印树结构

$ tree .git/objects
.git/objects
├── 1c
│ └── 30d6ba3439ec5e8e68aed15a79371db2f9be8d
├── 3b
│ └── e060dffd163e01ca6f44dfc6746dda5ae19d5d
├──
│ └── 200a14c72d35c97979bea3b46bee414e86185b
├── cc
│ └── c3e7b48da0932cc0f7c4ce7b4fd834c7032fe1
├── da
│ └── 8ebda5480840ecde47656e10317c55b965ad3b
├── db
│ └── 754dbd326f1b7c530672afbbfef8d9223033b7
├── f5
│ └── af32c14e49bb408de53e4ed22f1b8dd95c2353
├── info
└── pack

对象数量变成了8个也就是之前的2倍,所以可以看出存储的是当前全新的文件快照,而不 是仅仅提交部分的快照。 那么问题来了,这样有什么好处呢,每次会新建一个全新的blob object 其实是Git在时间很空间上的一个取舍,如果我们需要checkout或commit。或对比两个commit 之间的差异。如果存储的只是变更的部分,如果需要拿到一个commit的内容都需要从第一个 提交开始查找,会浪费很多的时间,而存储权限快照的方法就很快了,这种策略相当于通过 空间换时间。

总结下: 当我们新增两个文件的时候,就会有两个数据对象,每个文件都对应一个数据对象。当文件被 修改时,即使新增了一个字母,也会生成一个数据对象。

其次会有一个树对象来维护一些列的数据对象,叫树对象的原因是它持有的不仅可以是数据 对象,还可以是两一个对象。比如某次提交了两个文件和一个文件夹,那么树对象里面就有三 个对象,两个是数据对象,文件夹则用另一个树对象表示。这样递归下去就可以表示任意层 次的文件了。

最后则是提交对象,每个提交对象都有一个树对象,用来表示某一次提交所涉及的文件。除此 以外,每一个提交还有自己的父提交,指向上一次提交的对象。

git引用

git是面向对象的,里面的标签和分支都是指向提交对象的指针。

git日志

在 .git/logs 目录中,有一个文件夹和一个 HEAD 文件,每当 HEAD 引用改变了指向的位置,就会在 .git/logs/HEAD 中 添加了一个记录。而 .git/logs/refs/heads 这个目录中则有多个文件,每个文件对应一个分支,记录了这个分支 的指向位置 发生改变的情况。 当我们执行 git reflog 的时候,其实就是读取了 .git/logs/HEAD 这个文件。

rebase的原理

对于rebase的撤销,其实并不是真正意义上的撤销,只是通过reset修改HEAD和当前分支的指向,后面的提交只是没有指针的指向。 但是还是真实存在的。

参考

Git中rebase失败了如何进行恢复的更多相关文章

  1. git中如何切换分支,拉取分支,合并分支

    idea中如何使用git来做分支的切换合并: https://blog.csdn.net/autfish/article/details/52513465 本地分支与远程分支: https://seg ...

  2. Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase

    上篇博客聊了<git分支管理之rebase 以及 cherry-pick相关操作>本篇博客我们就以Learning Git中的关卡进行展开.下方列举了LearningGit中的 merge ...

  3. 关于git中git pull --rebase中的一些坑

    在公司里面,每次我更改完代码,准备pull最新代码时,总是会遇到各种各样的问题.,因为对应的问题不同,解决方法很多.但是比较通用的办法还是有的: git pull --rebase   //报错时 g ...

  4. Merge和Rebase在Git中的区别

    git命令Merge和Rebase的区别 git merge 会生成一个新得合并节点,而rebase不会 比如: D---E test / A---B---C---F master 使用merge合并 ...

  5. 如何在Git中撤销一切 | 干货

    翻译:李伟 审校:张帆 译自:Github JF杰微刊:如何在Git中撤销一切 任何一个版本控制系统中,最有用的特性之一莫过于 "撤销(undo)"操作.在Git中,"撤 ...

  6. 实用:Git 中的一些常见错误

    无论是数据科学家.算法工程师还是普通开发人员,在每个团队协作开发任务中,Git 都是必不可少的版本控制工具,因此掌握它的基本操作十分有必要.但即便是教程满天飞的今天,开发人员在使用 Git 时也还是会 ...

  7. 【转】如何在Git中撤销一切

    翻译:李伟 审校:张帆译自:Github 任何一个版本控制系统中,最有用的特性之一莫过于 “撤销(undo)”操作.在Git中,“撤销”有很多种含义. 当你完成了一次新的提交(commit),Git会 ...

  8. 右键快捷打开Git Bash here失败

    右键快捷打开Git Bash here失败,提示: Error: Could not fork child process: Resource temporarily unavailable (-1) ...

  9. 图解git中的最常用命令

    图解git中的最常用命令 Git命令参考手册(文本版) git init                                                  # 初始化本地git仓库(创 ...

随机推荐

  1. 蓝桥杯vip 字符串对比

    蓝桥杯vip 字符串对比 题目如下 给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一: 1:两个字符串长度不等.比如 Beijing 和 Hebei ...

  2. 基于java的OpenCV环境搭建

    一.OpenCV下载安装 OpenCV可以在官网下载链接https://opencv.org/releases.html 选择相应的版本下载保存就好(不过官网下载有时候真滴慢还会连不上.....)网盘 ...

  3. 通达OA rce复现

    通达OA下载:链接:https://pan.baidu.com/s/1c0P-M-IyY5VxfH5d0qKHsQ 提取码:l0pc 漏洞原因:未授权文件上传 + 文件包含(利用nginx日志也可以g ...

  4. 解决vscode 没有 c++11 的代码提示(如to_string()等)

    2019.5.4 更新: 参考了stackflow上的一个问题:to_string is not a member of std, says g++ (mingw),发现直接换新版mingw即可- m ...

  5. 被问到到http的时候你就这么回答!

    大家好,我是标题党,啊不,我是小雨小雨,致力于分享有趣的.实用的技术文章. 内容分为翻译和原创,如果有问题,欢迎随时评论或私信,希望和大家一起进步. 分享不易,希望能够得到大家的支持和关注. 什么是互 ...

  6. hdu1242 又又又是逃离迷宫(bfs模板题)

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1242/ 这次的迷宫是有守卫的,杀死一个守卫需要花费1个单位的时间,所以以走的步数为深度,在每一层进行搜索,由于走 ...

  7. Contest 158

    2019-10-14 15:30:38 总体感受:这次依然很快搞定了前三题,最后一题乍看之下还是比较简单的,但是出奇多的corner case让我非常苦恼,这也让我意识到要想真正征服最后一题,还有一个 ...

  8. 李宏毅老师机器学习课程笔记_ML Lecture 0-2: Why we need to learn machine learning?

    引言: 最近开始学习"机器学习",早就听说祖国宝岛的李宏毅老师的大名,一直没有时间看他的系列课程.今天听了一课,感觉非常棒,通俗易懂,而又能够抓住重点,中间还能加上一些很有趣的例子 ...

  9. UTF-8 AND UTF-8 without BOM(遇到了这个问题 郁闷了会儿)

    两者的区别: Unicode规范中有一个BOM的概念.BOM——Byte Order Mark,就是字节序标记.在这里找到一段关于BOM的说明: 在UCS 编码中有一个叫做"ZERO WID ...

  10. POJ-3134-Power Calculus(迭代加深)

    题意:输入一个n,问x从1次方开始,到n次方 ,可以乘或除已经计算出来的数 ,最少需要执行多少步? 思路:迭代加深 ,深度从0开始 ,直到返回值为真. 在深搜过程中剪枝(深度的判断 ,当前最大值尽全力 ...