git自动压缩提交的脚本

可以将当前未提交的代码自动执行

  • git add
  • git commit
  • git squash

Git 命令安装指南

1. 创建脚本目录

如果目录不存在,创建它:

bash 复制代码
mkdir -p ~/.local/bin

2. 创建脚本文件

bash 复制代码
vim ~/.local/bin/git-squash

将完整的脚本代码复制到此文件中。

3. 设置脚本权限

bash 复制代码
chmod +x ~/.local/bin/git-squash

4. 配置 PATH

编辑 shell 配置文件(根据你使用的 shell 选择):

bash 复制代码
# 对于 bash
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

# 或对于 zsh
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc

重新加载配置:

bash 复制代码
source ~/.bashrc  # 或 source ~/.zshrc

5. 创建 Git 别名

bash 复制代码
git config --global alias.allen-squash '!git-squash'

6. 验证安装

检查脚本是否可执行:

bash 复制代码
ls -l ~/.local/bin/git-squash

检查脚本是否在 PATH 中:

bash 复制代码
which git-squash

检查 git 别名是否设置成功:

bash 复制代码
git config --get-regexp alias.*squash

7. 使用方法

可以通过以下两种方式使用:

bash 复制代码
# 直接使用脚本
git-squash

# 或使用 git 别名
git allen-squash

8. 常见问题排查

命令未找到

  1. 检查 PATH:
bash 复制代码
echo $PATH | grep -o ~/.local/bin
  1. 检查脚本权限:
bash 复制代码
ls -l ~/.local/bin/git-squash
  1. 检查 git 别名:
bash 复制代码
git config --list | grep allen-squash

管理别名

bash 复制代码
# 删除别名
git config --global --unset alias.allen-squash

# 修改别名
git config --global alias.allen-squash '!git-squash'

编辑脚本

bash 复制代码
vim ~/.local/bin/git-squash

9. 备份建议

建议进行以下备份:

bash 复制代码
# 备份脚本
cp ~/.local/bin/git-squash ~/.local/bin/git-squash.backup

# 备份 git 配置
cp ~/.gitconfig ~/.gitconfig.backup

10. 更新脚本

如需更新脚本:

bash 复制代码
# 编辑脚本
vim ~/.local/bin/git-squash

# 确保权限正确
chmod +x ~/.local/bin/git-squash

注意事项

  1. 确保 ~/.local/bin 目录存在并在 PATH 中
  2. 确保脚本具有可执行权限
  3. 重启终端或重新加载配置文件后更改才会生效
  4. 建议在使用前先进行配置备份
  5. 如果遇到权限问题,检查用户权限和文件权限

故障排除

如果命令不能正常工作,请按以下步骤检查:

  1. 确认脚本位置:

    • 检查 ~/.local/bin/git-squash 是否存在
    • 确认文件权限是否正确
  2. 检查 PATH 设置:

    • 确认 ~/.local/bin 在 PATH 中
    • 检查 shell 配置文件是否正确加载
  3. 验证 git 别名:

    • 检查别名是否正确设置
    • 确认 git 配置文件是否正确

脚本内容

sh 复制代码
#!/bin/bash

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 全局变量
COMMITS_TO_SQUASH=0

# 错误处理函数
handle_error() {
    echo -e "${RED}Error: $1${NC}"
    exit 1
}

# 获取与main分支的距离和可压缩提交数量
get_commit_info() {
    # 获取当前分支名
    current_branch=$(git branch --show-current)
    
    # 获取当前分支的总提交数
    total_commits=$(git rev-list HEAD --count)
    
    # 尝试获取与main分支的距离
    if git rev-parse --verify main >/dev/null 2>&1; then
        commits_from_main=$(git rev-list --count main..HEAD)
        echo -e "\n${YELLOW}Commit information:${NC}"
        echo -e "Current branch: ${GREEN}$current_branch${NC}"
        echo -e "Total commits in current branch: ${GREEN}$total_commits${NC}"
        echo -e "Commits ahead of main: ${GREEN}$commits_from_main${NC}"
        echo -e "Maximum commits that can be squashed: ${GREEN}$commits_from_main${NC}"
    else
        echo -e "\n${YELLOW}Commit information:${NC}"
        echo -e "Current branch: ${GREEN}$current_branch${NC}"
        echo -e "Total commits in current branch: ${GREEN}$total_commits${NC}"
        echo -e "Main branch not found - cannot calculate distance from main"
        echo -e "Maximum commits that can be squashed: ${GREEN}$total_commits${NC}"
    fi
}

# 显示最近的提交历史并获取压缩数量
show_recent_commits() {
    echo -e "\n${YELLOW}Recent commits:${NC}"
    git --no-pager log --oneline -n 5
    
    # 计算与main分支的距离
    commits_ahead=$(git rev-list --count main..HEAD)
    
    echo -e "\n${YELLOW}Valid squash range:${NC}"
    echo -e "Minimum commits: ${GREEN}2${NC}"
    echo -e "Maximum commits: ${GREEN}$commits_ahead${NC} (number of commits ahead of main)"
    
    while true; do
        echo -e "\n${YELLOW}How many commits do you want to squash? (${GREEN}2${NC} to ${GREEN}$commits_ahead${NC})${NC}"
        read -r commits_count
        
        # 验证输入是否在有效范围内
        if [[ "$commits_count" =~ ^[0-9]+$ ]] && [ "$commits_count" -ge 2 ] && [ "$commits_count" -le "$commits_ahead" ]; then
            COMMITS_TO_SQUASH=$commits_count
            break
        else
            echo -e "${RED}Please provide a number between 2 and $commits_ahead${NC}"
        fi
    done
}

# 创建备份分支
create_backup() {
    current_branch=$(git branch --show-current)
    backup_branch="${current_branch}_backup_$(date +%Y%m%d_%H%M%S)"
    git branch $backup_branch || handle_error "Failed to create backup branch"
    echo -e "${GREEN}Created backup branch: $backup_branch${NC}"
}

# 执行squash操作
do_squash() {
    local commits_count=$1
    
    echo -e "\n${YELLOW}Will squash last $commits_count commits:${NC}"
    git --no-pager log --oneline -n "$commits_count"
    
    echo -e "\n${YELLOW}Do you want to continue? (y/n)${NC}"
    read -r response
    if [[ ! "$response" =~ ^[Yy]$ ]]; then
        echo "Operation cancelled"
        exit 0
    fi
    
    # 创建备份
    create_backup
    
    # 执行交互式rebase
    echo -e "\n${YELLOW}Starting interactive rebase...${NC}"
    echo -e "${YELLOW}In the editor:${NC}"
    echo -e "1. Leave the first 'pick' as is"
    echo -e "2. Change 'pick' to 's' or 'squash' for all other commits"
    echo -e "3. Save and close the editor"
    echo -e "4. In the next editor, write your combined commit message"
    
    if ! git rebase -i HEAD~"$commits_count"; then
        echo -e "${RED}Rebase failed. Restoring from backup...${NC}"
        git rebase --abort
        handle_error "Rebase failed"
    fi
}

# 推送更改
push_changes() {
    echo -e "\n${YELLOW}Do you want to push changes to remote? (y/n)${NC}"
    read -r response
    if [[ "$response" =~ ^[Yy]$ ]]; then
        current_branch=$(git branch --show-current)
        echo -e "${YELLOW}Using force push with lease for safety...${NC}"
        if git push origin "$current_branch" --force-with-lease; then
            echo -e "${GREEN}Successfully pushed changes${NC}"
        else
            handle_error "Push failed"
        fi
    fi
}

# 主函数
main() {
    # 检查是否在git仓库中
    git rev-parse --git-dir > /dev/null 2>&1 || handle_error "Not in a git repository"
    
    # 检查是否有改动需要提交
    if git diff-index --quiet HEAD -- && [ -z "$(git ls-files --others --exclude-standard)" ]; then
        echo -e "\n${YELLOW}No changes to stage or commit, skipping...${NC}"
    else
        # 添加新的暂存和提交步骤
        echo -e "\n${YELLOW}Staging all changes...${NC}"
        git add . || handle_error "Failed to stage changes"
        
        echo -e "${GREEN}Successfully staged all changes${NC}"
        
        echo -e "\n${YELLOW}Creating stage commit...${NC}"
        git commit -m "stage commit" || handle_error "Failed to create commit"
        
        echo -e "${GREEN}Successfully created stage commit${NC}"
    fi
    
    # 显示提交信息
    get_commit_info
    
    # 显示当前提交历史并获取要压缩的提交数
    show_recent_commits
    
    # 执行squash操作
    do_squash "$COMMITS_TO_SQUASH"
    
    # 推送更改
    push_changes
    
    echo -e "\n${GREEN}All operations completed successfully${NC}"
}

# 执行主函数
main
相关推荐
m0_7493175232 分钟前
vscode里如何用git
ide·git·vscode
黑客笔记44 分钟前
攻防世界-XCTF-Web安全最佳刷题路线
大数据·安全·web安全
软件测试小仙女1 小时前
鸿蒙APP测试实战:从HDC命令到专项测试
大数据·软件测试·数据库·人工智能·测试工具·华为·harmonyos
Hello.Reader1 小时前
Git 安装全攻略Linux、macOS、Windows 与源码编译
linux·git·macos
Elastic 中国社区官方博客2 小时前
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
大数据·人工智能·elasticsearch·搜索引擎·云计算·全文检索·aws
王景程2 小时前
SELinux是什么以及如何编写SELinux策略
git·github
反向跟单策略2 小时前
期货反向跟单运营逻辑推导思路
大数据·人工智能·数据分析·区块链
Chuncheng's blog2 小时前
如何基于Mihomo Party http端口配置git与bash命令行代理
git·http·bash
Tom Boom2 小时前
Git常用命令完全指南:从入门到精通
大数据·git·elasticsearch·docker·自动化测试框架
不吃饭的猪3 小时前
记一次spark在docker本地启动报错
大数据·docker·spark