首页 > 其他分享 >如何修剪git reflog历史

如何修剪git reflog历史

时间:2023-02-07 17:45:22浏览次数:42  
标签:修剪 git obj objects dst intermediate reflog commit

背景:

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
那么步骤为:

  1. 找到.git/objects/12/34567xx...
  2. 删除或者移动它 (建议移动到一个目录下,万一想要查看的时候还能还原)

因为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,obj,objects,dst,intermediate,reflog,commit
From: https://www.cnblogs.com/Bolia/p/17099288.html

相关文章

  • git合并、修改一些已经提交的命令
    折腾了一下(写一下,免的忘了)1、首先查看查看是到多少,命令 gitlog2、开始变基最开始的几个是(head~多少),其余的大家用的时候再查阅其他的看看,我就说说简......
  • git 分支
    如果主分支不为master,如new_trunk:1、#gitcheckout-bV3.18.45origin/V3.18.452、#gitbranch-va3、#gitcheckoutnew_trunk4、#gitmergeV3.18.45-m“Build-Ta......
  • 58-CICD持续集成工具-Git和GitLab
    Ubuntu编译安装git拉取git安装包(获取国外资源网速受限,可以clon到gitee项目中,从国内拉取)[root@ubuntu2204~]#aptupdate;apt-yinstallgccmakedh-autoreconflibcurl4......
  • ubuntu22.04 git升级
     git--version //查看版本 sudoadd-apt-repositoryppa:git-core/ppa  //通过PPA源方式安装软件的添加PPA源到Sourcelist中的命令,新手可以了解一下ubuntu专用......
  • git技能树总结
    1.git简介版本控制:指的是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。版本控制系统发展可分三个阶段:本地版本控制系统->集中式版本控制系......
  • git 删除本地分支
    这篇文章没有讲底层只是提供命令我觉得还不错给自己做一个笔记删除本地分支命令:gitbranch-d+分支名称来删除本地分支如果发现删除不了,一般会有提示如:“error:The......
  • CentOS 7 安装配置git
    安装yuminstallgit-y验证[root@localhost~]#git--versiongitversion1.8.3.1[root@localhost~]#配置基本信息//配置基本信息[root@localhost~]#gi......
  • git常用命令
    常用命令初始化一个仓库:gitinit查看分支:gitbranch将已修改或未跟踪的文件添加到暂存区:gitadd[file]或gitadd.提交至本地仓库:gitcommit-m"提及记录xxxx"本......
  • git忽略指定文件或者指定文件
    在使用git进行协作开发的时候经常会遇到一些配置问题,不同成员使用的IDE可能不同,那么IDE生成的配置文件也就不同,比如开发JAVA,idea生成的配置文件为.iml,而eclipse为.project,......
  • 每个程序员必学的10个Git命令
    希望在团队中处理代码时有效协作并跟踪更改的程序员来说,版本控制至关重要。Git是一个版本控制系统,允许您跟踪修订、识别文件版本并在必要时恢复旧版本。 具有一定编......