Git系列:常见场景问题处理
Git系列博客:
本文小结Git使用过程中典型场景问题处理。
版本代码如何快速回退?
A:首先分为两种回退情况,本地回退和远端回退
- 本地回退
- 工作区内修改回退
- 暂存区内修改回退
- 本地版本库回退
- 远端回退
- 涉及到远端库的回退
本地回退
本地工作区内修改回退
即还未进行add操作,此时可以用 git status
,查看本地修改文件,未add前显示红色,add后显示为绿色。采用指令抛弃现有文件或文件夹修改:git restore <file>
。
本地暂存区内修改回退
即add后,还未进行commit时,回退add的操作,指令:git rm --cached <file>
本地版本库回退
- 指令:
git reset --hard HEAD^
,硬回退到上一版本 - 指令:
git reset --soft HEAD^
,软回退到上一个版本 - 指令:
git reset --hard <commit_id>
,回到指定commit版本- 实例:
git reset --hard 1094a1094a
,commitId可以不必写全,只要足够区分版本就行
- 实例:
- 细节说明:
- 软回退和硬回退的区别:硬回退会将本地回退前版本内容删除后回退(同时撤销并删除之前本地工作区所有修改及提交内容),而软回退一下仅head指针后移,回退前的那个版本并没有删除。
- N个
^
,表示往后回退N个版本,如HEAD^^
上上一个版本 - 往后回退大于3个版本时,采用
HEAD~<数字>
,比如HEAD~100
,表示回退到前100个版本 - commitid可以通过
git reflog
查看,以及查看当前版本回退记录
实战演示:本地版本回退实现,并下载指定分支指定版本?
- 需求:如何实现拉取指定commit版本的代码,取走后并恢复到最新commit?
- 实现:git 下载指定分支指定的commit版本
- 第一步,克隆远端仓库并切换到相应分支:
git clone [git-url] -b [branch-name]
- 第二步,回退分支到指定commit版本:
git reset --soft [commit-number]
- 第三步,
git reflog
查看回滚前的commit id,利用git reset --soft
强制回到最新版本
- 第一步,克隆远端仓库并切换到相应分支:
- 示例
git clone ssh:xxxx -b dev
git reset --soft cmtid2
git reset --soft cmtidlatest
远端回退
- 基本流程
- 本地仓库回退
- 强制将回退后的本地版本推送到远端仓库
太长不看版:
git reset --soft <commitid> # 软回退
git reset --hard <commitid> # 硬回退
# 软回退硬回退选其1即可,然后推送到远端指定分支
git push origin branch -f
原理详解
- 本地仓库回退
- 软回退流程
- 功能:本地代码不变,仅分支commit指针回退,推送后本地代码比远端代码新
- 指令举例
git reset --soft e3a34cffj
- 释义:
soft
表示软回退,e3a34cffj
表示回退到指定commitid版本,可简写一部分。
- 释义:
- 硬回退流程
- 功能:本地代码变化,强制推到远端则版本回退,回退后的版本与本地代码一致
- 指令举例
git reset --hard e3a34cffj
- 释义:
soft
表示硬回退,e3a34cffj
表示回退到指定commitid版本,可简写一部分。
- 释义:
- 软硬回退对比
- git reflog
- 软硬回退都有指针移动的记录日志,两者一致
- git log
- 本地仓库已经回退到指定版本状态,两者一致
- git status
- 软回退:本地代码不变,之前修改文件都变化为add之后的状态,本地代码依然是未回退时的。可恢复到之前版本。
- 硬回退:之前的修改文件已全被抛弃,本地代码同步回退,且无法再恢复到之前版本。
- git reflog
- 推送到远端
git push origin master -f
- 释义:将回退后的版本强制推送到origin远端的master分支。其中,master可省略则默认推送到与本地分支同名远端分支,
-f
为--force
的简写,两者均可使用,表示强制推送。
- 释义:将回退后的版本强制推送到origin远端的master分支。其中,master可省略则默认推送到与本地分支同名远端分支,
- 软回退流程
可能问题
- 报错提示:You are not allowed to force push code to a protected branch on this project.
- 可能原因与解决
- 未使用
-f
参数强制推送到远端,push时需增加-f
参数。 - 可能远端仓库做了分支保护。需在远端仓库设置中,删除保护分支策略,允许master等分支的强制合入。
- 未使用
已push提交到远端,但未merge的代码,如何下载查看?
流程:
- fetch最新的修改,然后cherry-pick(中文译为:单方验证)到最新的FECTH_HEAD节点
- 指令:
git fetch [仓地址] refs/changes/[提交变动id] && git cherry-pick FETCH_HEAD
- 拉取下来后基于未合入的最新进展,继续修改,再commit提交
参考:git cherry-pick详解,link
Gerrit平台如何通过git push产生MR评审链接?
HEAD:refs/for/
是git推送分支合入时生成MR关键,例如:git push origin HEAD:refs/for/dev_branch
- 如果是用
HEAD:refs/head/
则是强推合入,一般不被允许
TBD
- 已push提交到远端仓库,但未merge的代码,如何下载查看?
- 方法:cherrypick指令,具体细节待补充。