repo回退当前分支下所有仓库到指定日期前的最新代码版本

本文介绍如何使用Repo命令将项目中所有子仓库批量回退到指定时间点的代码版本,通过执行特定命令实现快速版本回退。

使用repo管理的代码,同一个项目的每个子文件夹都可能是一个单独的仓库,这时怎么把整个项目回退到同一个时间点呢(更新到最新版本用repo sync):

执行下面这样的repo命令就行了:

repo forall -c 'commitID=`git log --before "2017-03-17 07:00" -1 --pretty=format:"%H"`; git reset --hard $commitID'
   
  • 1

参数说明:

forall  操作分支中的所有仓库
-c  只操作当前分支
--before  早于指定时间点的提交记录
-1  只显示最近的1条记录(注意这是数字 1 ,如果要显示 2 条就写 2,以此类推)
"2017-03-17 07:00"  希望回退到的日期(时间点)
--pretty  以指定格式显示提交记录
%H  提交记录的hash值,即commit id(其它格式及更详细的信息可以使用命令git log --help打印帮助信息并查看“PRETTY FORMATS”小节)  
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

命令含义: 
这条repo命令的实质就是在当前分支的每个仓库下执行git log命令,找出该仓库下符合时间条件的第一个提交记录,然后对该仓库执行git reset --hard操作。就这么简单。

本文转载自: repo回退当前分支下所有仓库到指定日期前的最新代码版本


<think>我们被要求编写一个shell脚本,该脚本包含以下功能: 1. 创建/拉取repo仓库 2. 切换本地关联的git分支 3. 推送代码 4. 回退代码(选择项) 根据引用[2]和[3]中关于Git和Repo的知识,我们需要注意: - 对于单个Git仓库,我们可以使用Git命令。 - 对于多个仓库Repo),我们使用Repo命令(但题目中同时提到了repo仓库和git分支,所以我们需要区分场景)。 但是,用户要求在一个脚本中同时包含这些功能,并且有选择项。因此,我们可以设计一个菜单驱动的脚本,让用户选择要执行的操作。 由于创建/拉取repo仓库通常涉及多个仓库(使用Repo),而其他操作(切换分支、推送代码回退代码)可以是针对单个Git仓库也可以是多个仓库(通过Repo),这里我们考虑两种场景: 1. 使用Repo管理多个仓库(适用于大型项目,如Android) 2. 使用Git管理单个仓库 但是,用户没有明确是单个仓库还是多个仓库。因此,我们可以让用户选择是操作单个Git仓库还是多个仓库Repo)。 然而,题目中同时出现了“repo仓库”和“git分支”,所以我们需要同时支持Git和Repo。但为了简化,我们可以这样设计: - 如果用户选择“创建拉取repo仓库”,则使用Repo命令(需要先初始化Repo项目)。 - 其他操作(切换分支、推送、回退)可以分别实现为Git版本(针对当前目录的单个仓库)和Repo版本(针对整个项目所有仓库)。 但是,一个脚本同时支持两种模式可能会很复杂。因此,我们可能需要用户先选择模式(Repo项目模式或单个Git仓库模式),然后再执行操作。 考虑到复杂度,我们这里先按照单个Git仓库来设计,因为引用[3][5]中提供了很多Git操作。同时,我们也提供Repo同步的选项(但需要用户已经配置好Repo环境)。 设计思路: 1. 显示菜单,让用户选择操作。 2. 操作包括: a. 克隆/拉取仓库(可以是Git克隆,也可以是Repo同步) b. 切换分支(Git checkout 或 Repo forall -c git checkout) c. 推送代码(Git push) d. 回退代码(Git reset 或 Git revert) 对于Repo操作,我们假设用户已经在Repo管理的项目中(即当前目录是Repo项目的根目录,并且已经初始化过Repo)。 具体功能: 1. 创建/拉取仓库: - 对于Git:提供克隆仓库(如果还没有)或者拉取(如果已有)。 - 对于Repo:执行`repo sync`(需要用户已经初始化Repo,并且有manifest.xml) 2. 切换分支: - 对于Git:让用户输入分支名,然后执行`git checkout 分支名` - 对于Repo:执行`repo forall -c git checkout 分支名`(切换所有仓库到同一分支) 3. 推送代码: - 对于Git:执行`git push origin 分支名` - 对于Repo:可能需要遍历所有仓库并推送,但通常不推荐直接全部推送,所以这里我们只实现单个仓库的推送(即当前目录的仓库) 4. 回退代码: - 提供两种回退方式:重置(reset)和还原(revert) - 重置:可以回退到某个提交(需要指定提交哈希) - 还原:撤销某个提交(创建一个新的提交来抵消之的提交) 由于脚本需要通用性,我们主要实现Git操作,同时对于Repo同步,我们单独作为一个选项(即拉取Repo项目)。 因此,我们设计菜单如下: 主菜单: 1. 克隆/拉取仓库 1.1 Git克隆 1.2 Git拉取(当前仓库) 1.3 Repo同步(整个项目) 2. 切换分支 2.1 当前Git仓库切换分支 2.2 整个Repo项目切换分支(需要当前Repo项目中) 3. 推送代码当前Git仓库) 4. 回退代码当前Git仓库) 4.1 重置(reset) 4.2 还原(revert) 但是,为了避免菜单嵌套太深,我们可以简化: 主菜单: 1. Git克隆 2. Git拉取(当前仓库) 3. Repo同步(整个项目) 4. 切换分支当前Git仓库) 5. 切换整个Repo项目的分支 6. 推送代码当前Git仓库) 7. 回退代码当前Git仓库) 7.1 重置到某个提交(git reset --hard <commit>) 7.2 还原某个提交(git revert <commit>) 另外,我们也可以让用户输入仓库地址、分支名称等。 由于是shell脚本,我们使用简单的read和case语句。 注意:在每一步操作,我们需要检查当前目录是否是一个Git仓库(除了克隆和Repo同步操作)。 实现步骤: 1. 显示菜单 2. 读取用户输入 3. 根据输入执行操作 注意:对于Repo操作,需要确保已经安装了Repo工具。 我们开始编写脚本。 注意:回退操作需要谨慎,特别是重置操作会丢弃工作,所以需要提醒用户。 另外,对于切换分支操作,如果当前有未提交的修改,可能会失败,所以我们可以先检查状态。 由于时间有限,我们不会做非常完善的错误处理,但会给出基本的检查。 脚本结构: ```shell #!/bin/bash # 主菜单函数 main_menu() { clear echo "=============== Git/Repo 操作脚本 ===============" echo "1. 克隆Git仓库" echo "2. 拉取当前Git仓库的更新" echo "3. Repo同步整个项目" echo "4. 切换当前Git仓库分支" echo "5. 切换整个Repo项目的分支" echo "6. 推送当前Git仓库代码" echo "7. 回退当前Git仓库代码" echo "0. 退出" echo "================================================" read -p "请输入选项: " option case $option in 1) git_clone ;; 2) git_pull ;; 3) repo_sync ;; 4) git_switch_branch ;; 5) repo_switch_branch ;; 6) git_push ;; 7) git_rollback ;; 0) exit 0 ;; *) echo "无效选项,请重新输入!" ; sleep 1; main_menu ;; esac } # 克隆Git仓库 git_clone() { read -p "请输入要克隆的仓库地址: " repo_url git clone "$repo_url" if [ $? -eq 0 ]; then echo "克隆成功!" else echo "克隆失败!" fi sleep 1 main_menu } # 拉取当前Git仓库的更新 git_pull() { # 检查当前目录是否是git仓库 if [ ! -d .git ]; then echo "当前目录不是Git仓库!" sleep 1 main_menu return fi git pull if [ $? -eq 0 ]; then echo "拉取成功!" else echo "拉取失败!" fi sleep 1 main_menu } # Repo同步整个项目 repo_sync() { # 检查是否在repo项目中(即当前目录或上级目录是否有.repo目录) if [ ! -d .repo ] && [ ! -d ../.repo ]; then echo "当前目录不是Repo项目目录!" sleep 1 main_menu return fi repo sync if [ $? -eq 0 ]; then echo "Repo同步成功!" else echo "Repo同步失败!" fi sleep 1 main_menu } # 切换当前Git仓库分支 git_switch_branch() { if [ ! -d .git ]; then echo "当前目录不是Git仓库!" sleep 1 main_menu return fi read -p "请输入要切换的分支名称: " branch_name git checkout "$branch_name" if [ $? -eq 0 ]; then echo "切换分支成功!" else echo "切换分支失败!" fi sleep 1 main_menu } # 切换整个Repo项目的分支(所有仓库切换到同一分支repo_switch_branch() { if [ ! -d .repo ] && [ ! -d ../.repo ]; then echo "当前目录不是Repo项目目录!" sleep 1 main_menu return fi read -p "请输入要切换的分支名称: " branch_name repo forall -c git checkout "$branch_name" if [ $? -eq 0 ]; then echo "Repo项目切换分支成功!" else echo "Repo项目切换分支失败!" fi sleep 1 main_menu } # 推送当前Git仓库代码 git_push() { if [ ! -d .git ]; then echo "当前目录不是Git仓库!" sleep 1 main_menu return fi # 获取当前分支名 branch_name=$(git symbolic-ref --short HEAD) if [ -z "$branch_name" ]; then echo "获取当前分支失败!" sleep 1 main_menu return fi echo "当前分支: $branch_name" read -p "是否推送到远程分支? (y/n) [默认y]: " confirm if [ "$confirm" != "n" ] && [ "$confirm" != "N" ]; then git push origin "$branch_name" if [ $? -eq 0 ]; then echo "推送成功!" else echo "推送失败!" fi else echo "已取消推送。" fi sleep 1 main_menu } # 回退当前Git仓库代码 git_rollback() { if [ ! -d .git ]; then echo "当前目录不是Git仓库!" sleep 1 main_menu return fi echo "请选择回退方式:" echo "1. 重置 (git reset --hard)" echo "2. 还原 (git revert)" read -p "请输入选项: " method case $method in 1) # 显示最近5次提交 echo "最近5次提交:" git log -5 --oneline read -p "请输入要重置到的提交哈希: " commit_hash read -p "重置将丢失未提交的修改,是否继续? (y/n) [默认n]: " confirm if [ "$confirm" == "y" ] || [ "$confirm" == "Y" ]; then git reset --hard "$commit_hash" if [ $? -eq 0 ]; then echo "重置成功!" else echo "重置失败!" fi else echo "已取消重置。" fi ;; 2) # 显示最近5次提交 echo "最近5次提交:" git log -5 --oneline read -p "请输入要还原的提交哈希: " commit_hash git revert "$commit_hash" if [ $? -eq 0 ]; then echo "还原成功!" else echo "还原失败!" fi ;; *) echo "无效选项!" ;; esac sleep 1 main_menu } # 启动主菜单 main_menu ``` 注意:这个脚本是一个简单的示例,实际使用中可能需要更完善的错误处理。 由于Repo命令的使用场景相对较少,且需要先初始化Repo项目(通常通过`repo init`),所以我们的脚本中没有包含初始化Repo项目的步骤,因为初始化需要manifest仓库地址等,比较复杂。用户需要先手动初始化Repo项目。 另外,对于Repo同步,我们假设用户已经在Repo项目根目录下。 对于回退操作,重置(reset)是强制回退,会丢失工作目录和暂存区的修改,所以需要用户确认。 这个脚本可以作为一个基础版本,用户可以根据需要扩展。 最后,我们输出脚本到文件,并提醒用户赋予执行权限。 但是,用户要求是“包含创建拉取repo仓库、切换本地关联git分支、推送代码回退代码选择项的shell脚本”,我们已经覆盖了这些功能。 注意:在Repo项目中,切换分支操作我们使用`repo forall -c git checkout`,这要求所有仓库都有这个分支,否则会失败。 我们编写完毕。</think>以下是一个包含创建/拉取仓库、切换分支、推送代码回退代码功能的Shell脚本实现: ```bash #!/bin/bash # 仓库操作脚本 function repo_operations() { while true; do clear echo "=============== Git/Repo 操作菜单 ===============" echo "1. 克隆/拉取仓库" echo "2. 切换分支" echo "3. 推送代码" echo "4. 回退代码" echo "0. 退出" echo "================================================" read -p "请选择操作: " choice case $choice in 1) clone_or_pull ;; 2) switch_branch ;; 3) push_code ;; 4) rollback_code ;; 0) echo "已退出脚本"; exit 0 ;; *) echo "无效选择,请重新输入"; sleep 1 ;; esac done } # 克隆或拉取仓库 function clone_or_pull() { echo "----------------------------------------" echo "1. 使用Git克隆/拉取" echo "2. 使用Repo同步" read -p "请选择操作类型: " op_type case $op_type in 1) read -p "请输入仓库地址: " repo_url if [ -d .git ]; then echo "执行 git pull..." git pull else echo "执行 git clone $repo_url" git clone "$repo_url" fi ;; 2) if [ ! -f .repo/manifest.xml ]; then echo "当前目录不是Repo项目,请先初始化Repo" return fi echo "执行 repo sync..." repo sync ;; *) echo "无效选择"; return ;; esac read -n 1 -s -r -p "操作完成,按任意键继续..." } # 切换分支 function switch_branch() { echo "----------------------------------------" echo "1. 切换本地分支" echo "2. 创建并切换新分支" echo "3. 切换Repo项目分支" read -p "请选择操作类型: " op_type case $op_type in 1) git branch -a read -p "请输入分支名称: " branch_name git checkout "$branch_name" ;; 2) read -p "请输入新分支名称: " new_branch git checkout -b "$new_branch" ;; 3) if [ ! -f .repo/manifest.xml ]; then echo "当前目录不是Repo项目" return fi read -p "请输入分支名称: " repo_branch repo forall -c "git checkout $repo_branch" ;; *) echo "无效选择"; return ;; esac read -n 1 -s -r -p "操作完成,按任意键继续..." } # 推送代码 function push_code() { echo "----------------------------------------" git status read -p "是否添加所有修改? (y/n): " add_all if [[ $add_all =~ ^[Yy]$ ]]; then git add . else read -p "请输入要添加的文件路径: " file_path git add "$file_path" fi read -p "请输入提交信息: " commit_msg git commit -m "$commit_msg" current_branch=$(git symbolic-ref --short HEAD) echo "当前分支: $current_branch" read -p "是否推送到远程分支? (y/n): " push_confirm if [[ $push_confirm =~ ^[Yy]$ ]]; then git push origin "$current_branch" fi read -n 1 -s -r -p "操作完成,按任意键继续..." } # 回退代码 function rollback_code() { echo "----------------------------------------" echo "1. 重置工作区修改" echo "2. 重置暂存区修改" echo "3. 回退到历史提交" echo "4. 还原特定提交" read -p "请选择回退类型: " rollback_type case $rollback_type in 1) git status read -p "确定重置所有工作区修改? (y/n): " confirm [[ $confirm =~ ^[Yy]$ ]] && git restore . ;; 2) git status read -p "确定重置暂存区修改? (y/n): " confirm [[ $confirm =~ ^[Yy]$ ]] && git restore --staged . ;; 3) git log --oneline -10 read -p "请输入目标提交ID: " commit_id git reset --hard "$commit_id" ;; 4) git log --oneline -10 read -p "请输入要还原的提交ID: " revert_id git revert "$revert_id" ;; *) echo "无效选择"; return ;; esac read -n 1 -s -r -p "操作完成,按任意键继续..." } # 启动脚本 repo_operations ``` ### 功能说明: 1. **克隆/拉取仓库**: - 支持Git克隆新仓库或拉取现有仓库更新 - 支持Repo同步多仓库项目[^2] 2. **切换分支**: - 切换本地分支(`git checkout`) - 创建并切换新分支(`git checkout -b`) - 切换整个Repo项目的分支(`repo forall -c`)[^2] 3. **推送代码**: - 添加修改到暂存区(`git add`) - 提交更改(`git commit`) - 推送到远程仓库(`git push`)[^3][^5] 4. **回退代码**: - 重置工作区修改(`git restore .`) - 重置暂存区修改(`git restore --staged .`) - 硬重置到历史提交(`git reset --hard`) - 还原特定提交(`git revert`)[^3] ### 使用说明: 1. 保存为 `git_operations.sh` 2. 添加执行权限:`chmod +x git_operations.sh` 3. 运行脚本:`./git_operations.sh` 4. 按菜单提示操作 ### 注意事项: 1. Repo操作需要预先配置Repo环境 2. 分支切换建议提交或暂存当前修改 3. 回退操作会修改历史记录,团队协作时需谨慎 4. 首次使用需配置Git用户信息: ```bash git config --global user.name "您的姓名" git config --global user.email "您的邮箱" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值