用脚本实现简易版本控制可行吗

wen 实用脚本 1

本文目录导读:

用脚本实现简易版本控制可行吗

  1. 核心设计思路
  2. 核心功能模块
  3. Bash 脚本实现
  4. 使用示例
  5. 进阶优化建议
  6. 注意事项
  7. Python 版本(更灵活)

可以的,用脚本实现简易版本控制完全可行,而且是一个非常有趣且实用的学习项目。

对于个人项目或小型文件管理,有时并不需要 Git 那样完整的功能,一个轻量脚本往往更直接、更容易理解。

核心设计思路

简易版本控制本质上是保存文件在不同时间点的快照,基于这个思路,我们可以采用两种不同的策略。

快照备份(简单直观)

文件当前状态 → 复制到版本目录 → 生成带时间戳的副本

差异备份(节约空间)

保存当前文件与上次版本的差异 → 记录变更记录

这里我推荐策略一,因为它更简单、可靠,且易于实现和恢复。

核心功能模块

一个基础的版本控制系统至少需要4个操作:

功能 说明
init 初始化版本仓库
save 保存当前版本快照
list 列出所有版本
restore 恢复到指定版本

Bash 脚本实现

下面给出一份完整可用的 Bash 脚本,它实现了上述功能,并且每一步都有详细注释。

#!/usr/bin/env bash
### 文件名:version.sh
### 用法:./version.sh [init|save|list|restore]
set -euo pipefail
# 配置
VERSION_DIR=".myversions"          # 版本存储目录
FILES_TO_TRACK=("note.txt")        # 监控的文件列表,可按需扩展
MAX_VERSIONS=10                    # 保留的最大版本数
# 颜色输出(便于阅读)
GREEN='\033[0;32m'; RED='\033[0;31m'
YELLOW='\033[1;33m'; NC='\033[0m'
version_init() {
    # 创建版本目录结构
    mkdir -p "$VERSION_DIR/logs"
    echo "✅ 已初始化版本仓库: $VERSION_DIR/"
}
version_save() {
    # 检查文件是否存在
    for file in "${FILES_TO_TRACK[@]}"; do
        if [ ! -f "$file" ]; then
            echo -e "${RED}❌ 文件 $file 不存在,跳过${NC}"
            continue
        fi
        # 生成唯一版本号(时间戳+随机数)
        TIMESTAMP=$(date +%Y%m%d%H%M%S)
        RANDOM_SUFFIX=$RANDOM
        VERSION_FILE="$VERSION_DIR/${file}_${TIMESTAMP}_${RANDOM_SUFFIX}"
        # 复制当前版本
        cp "$file" "$VERSION_FILE"
        # 记录版本信息
        echo "$TIMESTAMP $(md5sum "$file")" >> "$VERSION_DIR/logs/${file}.log"
        echo -e "${GREEN}✅ 已保存版本: ${file}_${TIMESTAMP}${NC}"
        # 自动清理旧版本(超过MAX_VERSIONS)
        clean_old_versions "$file"
    done
}
version_list() {
    echo -e "${YELLOW}📋 版本列表:${NC}"
    for file in "${FILES_TO_TRACK[@]}"; do
        echo -e "\n${YELLOW}文件: $file${NC}"
        # 匹配该文件的版本
        if compgen -G "$VERSION_DIR/${file}_*" > /dev/null; then
            for version in "$VERSION_DIR/${file}_"*; do
                # 提取时间戳
                TIMESTAMP=$(echo "$version" | grep -o '[0-9]\{14\}')
                echo "  📌 $TIMESTAMP"
            done
        else
            echo "  (暂无版本)"
        fi
    done
}
version_restore() {
    if [ $# -lt 2 ]; then
        echo -e "${RED}❌ 用法: restore <文件名> <时间戳>${NC}"
        return 1
    fi
    FILE=$1
    TIMESTAMP=$2
    # 查找匹配的版本文件
    VERSION_FILE=$(ls "$VERSION_DIR/${FILE}_${TIMESTAMP}_"* 2>/dev/null | head -1)
    if [ -f "$VERSION_FILE" ]; then
        cp "$VERSION_FILE" "$FILE"
        echo -e "${GREEN}✅ 已恢复到 $TIMESTAMP 版本${NC}"
    else
        echo -e "${RED}❌ 找不到版本 $TIMESTAMP${NC}"
    fi
}
clean_old_versions() {
    FILE=$1
    # 统计该文件的版本数量(排除日志)
    COUNT=$(ls "$VERSION_DIR/${FILE}_"* 2>/dev/null | wc -l)
    if [ "$COUNT" -gt "$MAX_VERSIONS" ]; then
        # 按时间排序,删除最旧的
        TO_DELETE=$((COUNT - MAX_VERSIONS))
        ls -t "$VERSION_DIR/${FILE}_"* | tail -n "$TO_DELETE" | xargs rm -f
        echo -e "${YELLOW}🧹 已清理 $TO_DELETE 个旧版本${NC}"
    fi
}
# 主逻辑
case "${1:-}" in
    init)
        version_init
        ;;
    save)
        version_save
        ;;
    list)
        version_list
        ;;
    restore)
        # 支持两种调用方式:restore [文件] [时间戳] 或 直接交互
        if [ $# -eq 3 ]; then
            version_restore "$2" "$3"
        else
            # 交互式恢复
            version_list
            echo -e "\n请输入要恢复的文件名:"
            read -r RESTORE_FILE
            echo "请输入时间戳:"
            read -r RESTORE_TIME
            version_restore "$RESTORE_FILE" "$RESTORE_TIME"
        fi
        ;;
    *)
        echo -e "${YELLOW}简易版本控制脚本 v1.0${NC}"
        echo -e "用法: $0 {init|save|list|restore}"
        echo ""
        echo "   init      — 初始化版本仓库"
        echo "   save      — 保存当前文件快照"
        echo "   list      — 查看所有版本"
        echo "   restore   — 恢复指定版本"
        exit 1
        ;;
esac

使用示例

# 1. 初始化
./version.sh init
# 2. 修改文件后保存版本
./version.sh save
# 3. 查看所有版本
./version.sh list
# 4. 恢复到指定时间戳的版本
./version.sh restore note.txt 20250101120000

进阶优化建议

如果你想要更完善的功能,可以考虑以下方向:

增强方向 实现思路
中文兼容 使用 while IFS= read -r line 处理含空格文件名
分支支持 增加分支目录隔离
版本对比 使用 diff 实现差异查看
加密存储 使用 openssl 加密版本文件
远程备份 增加 rsync 到远程服务器
跨平台支持 改用 Python 增强兼容性

注意事项

  • 备份策略:即使有版本控制,也建议定期异地备份
  • 性能优化:对超大文件,Python 可能比 Bash 更适合
  • 安全考量:敏感文件应加密存储
  • 扩展性:如果需求变复杂,建议转向 Python/Node.js 实现

Python 版本(更灵活)

如果觉得 Bash 不够灵活,这里也提供一个更简洁的 Python 版本思路:

import os, shutil, hashlib, json
from datetime import datetime
class MiniGit:
    def __init__(self, repo_dir=".minigit"):
        self.repo_dir = repo_dir
        self.versions_dir = os.path.join(repo_dir, "versions")
        self.logs_file = os.path.join(repo_dir, "logs.json")
    def init(self):
        os.makedirs(self.versions_dir, exist_ok=True)
        if not os.path.exists(self.logs_file):
            with open(self.logs_file, 'w') as f:
                json.dump([], f)
    def save(self, filepath):
        if not os.path.exists(filepath):
            raise FileNotFoundError(filepath)
        content = open(filepath, 'rb').read()
        hash_val = hashlib.md5(content).hexdigest()
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        # 保存版本文件
        filename = os.path.basename(filepath)
        snapshot = f"{filename}_{timestamp}_{hash_val[:8]}.snap"
        with open(os.path.join(self.versions_dir, snapshot), 'wb') as f:
            f.write(content)
        # 记录日志
        with open(self.logs_file) as f:
            logs = json.load(f)
        logs.append({
            "file": filepath,
            "timestamp": timestamp,
            "hash": hash_val,
            "snapshot": snapshot
        })
        with open(self.logs_file, 'w') as f:
            json.dump(logs, f, indent=2)

用脚本实现简易版本控制绝可行,而且是一个很好的学习实践,它不仅解决了实际问题(文件备份),还能帮你深入理解 Git 等现代版本控制工具的核心原理,为将来使用真正的 VCS 打下坚实基础。

抱歉,评论功能暂时关闭!