如何修剪git reflog历史
背景:
vscode插件git-graph可以方便查看git-commit-graph,效果很好,关键是交互性很好。
点选任意commit即可预览提交内容,实在是太方便了,比我之前用命令行上git log --graph --oneline强太多了。
但同时带来的困扰是能看到的信息(commit历史)太多了,让我眼花缭绕。
例如,为了修复一个issue,前后进行了10次git commit --amend。也就是一共11次提及历史记录。
git graph大概长这样
初衷:
实际上当我合并这次的修改之后,我只想保留最后一次的记录在reflog里,其他的10次提交历史都不要了。这就涉及到了git reflog修剪了。
实现:
首先,git 是通过HEAD找commit hash ID,然后每个commit都有parent commit,如此组成一条链式结构。
commit是描绘git-graph的主要依据,其实只要删掉一个commit就能改变git-graph的结果。
每一次提交都会在.git/objects目录下生成至少一个commit类型的文件,其完整的文件路径为.git/objects/12/34567xx... (这里假设这个commit hash id 是1234567xx...)
git cat-file -t可以查看.git/objects目录下的文件是tree、commit还是blob类型。
例如:
注意:不能删除当前分支上可达的commit,不然链就断了,git就无法正常工作了。前面提到的"其他的10次提交历史" 因为在当前分支已经不可达,所以可以删除
例如我想从git-graph删除一个hash为 1234567的commit
那么步骤为:
- 找到.git/objects/12/34567xx...
- 删除或者移动它 (建议移动到一个目录下,万一想要查看的时候还能还原)
因为git commit hash有缩写形式、引用形式、完整形式,但是.git/objects/下的文件名都是完整形式,这种事情当然要写个脚本来一劳永逸了。
#!/bin/bash function zlipd() {
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - $@ | gzip - dc 2> /dev/null
} function move_intermediate_obj() {
local dst_path
dst_path=$1; shift
while [ -n "$1" ]; do
if [ -f .git /objects/ "${1:0:2}" / "${1:2}" ]; then
mv - v .git /objects/ "${1:0:2}" / "${1:2}" "$dst_path/$1"
fi
shift
done
}
# function migrate_intermediate_obj() {
# [ ! -d ./.git ] && { echo ".git dir not exist"; return; }
# [ ! -d ./intermediate_obj ] && mkdir -p intermediate_obj
# for f in $(git rev-list -n "${2:-1}" "${1:?params not enough}")
# do
# # echo "$f"
# move_intermediate_obj "$f"
# done
# } migrate_intermediate_obj ()
{
[ ! -d ./.git ] && {
echo ".git dir not exist" ;
return
}; local dst_dir
[ -d . /output ] && dst_dir=. /output/intermediate_obj ;
[ -z $dst_dir ] && dst_dir=. /intermediate_obj ;
mkdir -p $dst_dir if [ $ # -eq 1 ]
then
move_intermediate_obj $dst_dir "$1" ;
elif expr $2 + 0 > /dev/null 2>&1 # test $2 whether is number otherwise $? neq 0/1 if $2 non-integer argument
then
for f in $(git rev-list -n "${2:-1}" "${1:?params not enough}" );
do
move_intermediate_obj $dst_dir "$f" ;
done
else
move_intermediate_obj $dst_dir "$@" ;
fi
}
脚本使用方法:
source script.sh
migrate_intermediate_obj 1234567
脚本将会在当前目录下创建一个文件intermediate_obj,并将commit文件移动进去。
PS:在git gc的时候有些commit会被打包到.git/objects/pack文件夹下的pack后缀的文件里,这样的话在.git/objects/下就找不到这些commit文件了。
解决办法是使用git unpack-objects < .git/*.pack文件解压出来。(pack文件和index文件要事先从.git/objects/pack移出去该命令才会有效果)
PS2:git verify-pack -v .git/objects/pack/pack-xx.pack可以查看哪个pack文件包含你要的commit
如何修剪git reflog历史的更多相关文章
- Git清空历史,清空历史删除的文件,降低.git 文件大小
执行以下步骤之前 请做好源码备份 本操作用来清理github上面的历史删除文件,减少库的体积. 第一步骤 下载JDK环境和JAR包 https://rtyley.github.io/bfg-repo- ...
- Git reflog 引用日志使用详解
本章节主要介绍 git reflog 命令. Git 使用一种称为引用日志或"reflogs"的机制来跟踪分支顶端的更新. 许多 Git 命令接受用于指定引用或"ref& ...
- [译]git reflog
用法 git reflog 显示整个本地仓储的commit, 包括所有branch的commit, 甚至包括已经撤销的commit, 只要HEAD发生了变化, 就会在reflog里面看得到. git ...
- git reflog 和git log :no branch git 提交方式
git reflog 和git log的区别,外加git cherry-pick的一种用法 git reflog 可以查看所有分支的所有操作记录(包括(包括commit和reset的操作),包括已经被 ...
- Git相关二三事(git reflog 和彩色branch)【转】
转自:https://www.jianshu.com/p/3622ed542c3b 背景 git太常用了,虽然,用起来不难,但也有很多小技巧的东西... 1. 后悔药 哪天不小心,写完代码,没comm ...
- git 修改历史提交信息
当你不小心,写错了提交的注视/信息,该如何处理呢.理论上,SCM是不应该修改历史的信息的,提交的注释也是. 不过在git中,其commit提供了一个--amend参数,可以修改最后一次提交的信息. ...
- Git log和git reflog
1.git log log命令可以显示所有提交过的版本信息.显示信息如下: $ git log commit e1bdff6e4830e09383078c860f45334d03771b03 (HE ...
- git log 与 git reflog 的 区别
git log: commit 的版本日志 包含提交的版本 操作者 日期 (方便查看commit的版本,但是版本回退后,使用git log 看不到回退版本号之后的版本记录) commit ce0d69 ...
- git删除历史
Git如何永久删除文件(包括历史记录) 有些时候不小心上传了一些敏感文件(例如密码), 或者不想上传的文件(没及时或忘了加到.gitignore里的), 而且上传的文件又特别大的时候, 这将导致别 ...
- 利用git reflog找回错误的重置
在开发中经常需要reset分支,如果在reset前没有记住分支指向的提交ID,想要重置回原来的提交恐怕大多数开发者是重新拉取远程版本库,再rebase分支.但如果连不上远程版本库或没有远程版本怎么办呢 ...
随机推荐
- 利用递归的方式在JSON 数据中找到某个节点的多有父节点
在项目中遇到的问题-- 一个级联题,知道答案id 后将每一级的选项展示出来 例如 级联题的 json 数据是 [ { name: '北京', id: 1, children:[ { name: '朝 ...
- Training: WWW-Robots
原题链接:http://www.wechall.net/challenge/training/www/robots/index.php 打开网页他给我们说什么 说什么这是一个小挑战,你将会了解到机器人 ...
- 自学 TypeScript 第五天,手把手项目搭建 TS 篇
前言: 昨天咱们已经把贪吃蛇的页面写好了,今天咱们来写 TS 部分 TS 我们要用面向对象的形式去编写我们的功能,所以我们要以一个功能去定义一个对象 把这个项目分成几个模块,也就是几个对象功能 Foo ...
- C温故补缺(五):main函数的参数
main()的参数 main()函数的参数,用于在外部执行时传入参数,类似windows的bat脚本或linux的sh脚本.在bat脚本中传入参数,用%接收.sh脚本的参数用$接收. c语言编译成可执 ...
- jquery 简单分页插件jQuerypage
昨天项目手机端要用到table的分页,考虑到手机端界面小,系统数据不多,在没考虑大批量数据处理的前提前就下载了这个插件,简单. 展示数据datas为json格式. <!DOCTYPE html& ...
- oracle第二步创建表空间、用户、授权
Windows+r→键入sqlplus,输入已安装好的oracle数据库超级管理员账号密码登录.显示: 成功. 创建表空间: 创建用户并默认表空间: 授权该创建用户对数据库的操作: 代码: SQL&g ...
- hashlib加密 logging日志 subprocess
Day23 hashlib加密 logging日志 hahlib加密模块 logging日志模块 subprocess模块 1.hahlib加密模块 1.什么是加密? 将明文数据处理成密文数据的过程 ...
- SpringCloud Alibaba(三) - GateWay网关
1.基本环境搭建 1.1 依赖 <!-- Gatway 网关会和springMvc冲突,不能添加web依赖 --> <dependency> <groupId>or ...
- 我要涨知识——TypeScript 常见面试题(二)
又是一个年底来了,好大一批人可能又准备跑路了,最近回家待产,翻了翻掘金和 CSDN 发现好多大佬都有大厂 Offer ,看着看着我心动了! 话不多说,赶紧开干,给自己整了一个前端面试小助手--微信小程 ...
- 如何发布一个 TypeScript 编写的 npm 包
前言 在这篇文章中,我们将使用TypeScript和Jest从头开始构建和发布一个NPM包. 我们将初始化一个项目,设置TypeScript,用Jest编写测试,并将其发布到NPM. 项目 我们的库称 ...