Cygwin专用Bash函数:git-filter-branch,从Git仓库提交历史记录中永久删除某些文件

Cygwin专用Bash函数:git-filter-branch,此函数把 git filter-branch命令做了上层封装,针对多个文件自动生成应用脚本shell,以便快捷方便地从Git仓库提交历史记录中永久删除某些文件;
使用方法:
在Cygwin中运行 git-filter-branch xxx即可
注意使用文件的相对路径,支持同时指定多个文件,支持使用通配符;

使用帮助:

$ git-filter-branch --help

 git-filter-branch

功能:过滤分支,从Git提交历史中永久移除某些文件,参数请传递文件名或文件的相对路径!
说明:支持一个或多个,善用通配符 * 匹配多个文件,可用单引号包裹 * 号防止通配符被展开。

Usage  :git-filter-branch /path/to/file1 [/path/to/file2] [/path/to/file3] ...
Example:git-filter-branch application/config.php application/database.php
         git-filter-branch application/*.php application/tests/*
         git-filter-branch 'vendor/topthink/think-captcha/assets/bgs/*'



git-filter-branch() {
	# git filter-branch命令封装,从历史记录中永久删除某些文件;
	[ $# -eq 0 ] && echo -e "缺少参数!请传递文件名或文件相对路径。"
	if [ $# -eq 0 ] || [[ "${*,,}" =~ "-h" || "${*,,}" =~ "--help" ]];then
		echo -e "\n git-filter-branch \n"
		echo -e "功能:过滤分支,从Git提交历史中永久移除某些文件,参数请传递文件名或文件的相对路径!"
		echo -e "说明:支持一个或多个,善用通配符 * 匹配多个文件,可用单引号包裹 * 号防止通配符被展开。\n"
		echo -e "Usage  :git-filter-branch /path/to/file1 [/path/to/file2] [/path/to/file3] ..."
		echo -e "Example:git-filter-branch application/config.php application/database.php"
		echo -e "\t git-filter-branch application/*.php application/tests/*"
		echo -e "\t git-filter-branch 'vendor/topthink/think-captcha/assets/bgs/*'"
		return
	fi
	local gitTmpScript=$(mktemp)
	for file in "$@";
	do 
		echo "准备移除 $file ..."
		cat>>"$gitTmpScript"<<<"git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch ${file}' --prune-empty --tag-name-filter cat -- --all"	
	done
	cat>>"$gitTmpScript"<<<"trap \"rm -vf \$0\" 0"  #TempScript运行结束后,自动删除脚本自身...
	print_color 40 "提示:执行前请确保本地或上游远程仓库有原始备份!"
	local cr=`echo $'\n> .'`
	local cr=${cr%.}
	#See Also:https://stackoverflow.com/questions/4296108/how-do-i-add-a-line-break-for-read-command
	read -p "filter-branch 临时脚本生成完成,是否查看其内容以确保万无一失?默认为否。yes/no (y/N):$cr" -e catTmpScript
	if [[ "${catTmpScript,,}" == "y" || "${catTmpScript,,}" == "yes" ]];then
		echo "-------------------"
		cat "$gitTmpScript"
		echo "-------------------"
	fi
	print_color 40 "警告:filter-branch一旦被执行,历史记录将被篡改,相对应的文件记录将会永久丢失,过程不可逆!"
	read -p "是否确认运行 git filter-branch重写分支历史?默认为否,yes/no (y/N):$cr" -e realDoScript
	if [[ ! "${realDoScript,,}" == "y" && ! "${realDoScript,,}" == "yes" ]];then
		print_color 40 "\`git-filter-branch\` 中断执行,程序退出..."
		return
	fi
	print_color 33 "开始执行 \`git filter-branch\` 脚本,过程耗时可能比较长,清耐心等待..."
	bash "$gitTmpScript"
	read -p "是否运行 \`git gc\` 对Git仓库进行回收垃圾?默认为是,yes/no (y/N):$cr" -e doGCRepo
	if [[ ! "${doGCRepo,,}" == "n" && ! "${doGCRepo,,}" == "no" ]];then
		print_color 33 "gc垃圾回收ing..."
		#rm -rf .git/refs/original/
		/usr/bin/git reflog expire --expire=now --all
		/usr/bin/git gc --prune=now
		/usr/bin/git gc --aggressive --prune=now
	fi
	print_color 40 "所有操作完成,视情况你可能需要\`git push --force\`强制推送到上游仓库以覆盖原有的历史记录!"
	print_color 40 "如需推送,请手动运行命令:\ngit push --force" 
	print_color 40 "git push --force origin"
	print_color 40 "git push --force origin --all"
	[ -f "$gitTmpScript" ] && rm -f "$gitTmpScript"
}

运行截图:

帮助提示:


运行过程:


注:脚本函数中依赖的print_color函数为自建函数,目的是为了打印不同颜色和背景色的终端字体,换成echo命令一样的,不影响脚本运行效果;

附:print_color函数代码

print_color() {
	## print_color 打印带颜色的文字
	# $1 -- 颜色编号,(可省略);缺省为3 ——绿色字
	# $2 或 $* -- 打印的文字内容
	# -----------------------------
	:<<EOF
echo -e "\033[字背景颜色;文字颜色m字符串\033[0m"
例如: 
echo -e "\033[47;30m I love Android! \033[0m"
	 其中47的位置代表背景色, 30的位置是代表字体颜色,需要使用参数-e,man  echo 可以知道-e     enable interpretation of backslash escapes。
----------
See Also:
https://www.cnblogs.com/fengliu-/p/10128088.html
EOF
	if [ $# -eq 0 ];
	then
		echo -e "\033[30m 黑色字 \033[0m"
		echo -e "\033[31m 红色字 \033[0m"
		echo -e "\033[32m 绿色字 \033[0m"
		echo -e "\033[33m 黄色字 \033[0m"
		echo -e "\033[34m 蓝色字 \033[0m"
		echo -e "\033[35m 紫色字 \033[0m"
		echo -e "\033[36m 天蓝字 \033[0m"
		echo -e "\033[37m 白色字 \033[0m"

		echo -e "\033[40;37m 黑底白字 \033[0m"
		echo -e "\033[41;37m 红底白字 \033[0m"
		echo -e "\033[42;37m 绿底白字 \033[0m"
		echo -e "\033[43;37m 黄底白字 \033[0m"
		echo -e "\033[44;37m 蓝底白字 \033[0m"
		echo -e "\033[45;37m 紫底白字 \033[0m"
		echo -e "\033[46;37m 天蓝底白字 \033[0m"
		echo -e "\033[47;30m 白底黑字 \033[0m"
		echo 
		echo -e "See Also:\n\thttps://www.cnblogs.com/fengliu-/p/10128088.html"
		return
	fi
	local color=3 #默认颜色
	#判断第一个参数是否为纯数字,如果是数字,则认定为设定颜色编号
	if [ $# -ge 2 ];
	then
		expr $1 "+" 10 &> /dev/null  
		if [ $? -eq 0 ];then
			local color=$1
			shift
		fi
	fi
	local str="$*"
	case $color in
		1)
		echo -e "\033[30m${str}\033[0m"
		;;              
		2)              
		echo -e "\033[31m${str}\033[0m"
		;;              
		3)              
		echo -e "\033[32m${str}\033[0m"
		;;              
		4)              
		echo -e "\033[33m${str}\033[0m"
		;;              
		5)              
		echo -e "\033[34m${str}\033[0m"
		;;              
		6)              
		echo -e "\033[35m${str}\033[0m"
		;;              
		7)              
		echo -e "\033[36m${str}\033[0m"
		;;              
		8)              
		echo -e "\033[37m${str}\033[0m"
		;;
		9)
		#红底白字
		echo -e "\033[41;37m${str}\033[0m"
		;;
		10)
		#白底黑字
		echo -e "\033[47;30m${str}\033[0m"
		;;
		33)
		#绿底黄字
		echo -e "\033[42;33m${str}\033[0m"
		;;
		40)
		#黑底黄字
		echo -e "\033[40;33m${str}\033[0m"
		;;
		41)
		#红底黄字
		echo -e "\033[41;33m${str}\033[0m"
		;;
		*)
		#蓝底白字
		echo -e "\033[44;37m${str}\033[0m"
		;;
	esac
}
posted @ 2022-01-19 17:25  晴云孤魂  阅读(293)  评论(0编辑  收藏  举报