社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Git

【第1119期】Git的4个阶段的撤销更改

前端早读课 • 7 年前 • 928 次点击  

前言

工作中会遇到需要撤销更改的情况,知道有一个git reset --hard的指令能回退,由于用的不频繁所以总忘记在什么情况具体结合什么指令使用。这篇文章从基本概念检查修改撤销修改循序渐进地介绍了在各种情况下的需要用到的git指令。今日早读文章由企办@张京授权分享。

本文由@仙人掌编辑分享。

正文从这里开始

虽然 git 诞生距今已有 12 年之久,网上各种关于 git 的介绍文章数不胜数,但是依然有很多人(包括我自己在内)对于它的功能不能完全掌握。以下的介绍只是基于我个人对于 git 的理解,并且可能生编硬造了一些不完全符合 git 说法的词语。目的只是为了让 git 通俗化,使初学者也能大概了解如何快速上手 git 。同时,下面所有讨论,我们都假设只使用一个分支,也就是主分支 master 的情况,虽然这种作法并不符合 git 规范,但是现实情况中绝大部分用户是直接在 master 分支上进行工作的,所以在这里我们不去引入更加复杂的各种分支的情况,也不涉及标签 tag 的操作,只讲在最简单的主分支上如何回退。

基本概念

3个步骤

正常情况下,我们的工作流就是 3 个步骤,对应上图中的 3 个箭头线:

git add .   把所有文件放入 暂存区;
git commit
-m "comment"  把所有文件从 暂存区 提交进 本地仓库;
git push
把所有文件从 本地仓库 推送进 远程仓库。

4个区

git 之所以令人费解,主要是它相比于 svn 等等传统的版本管理工具,多引入了一个 暂存区 ( Stage )的概念,就因为多了这一个概念,而使很多人疑惑。其实,在初学者来说,每个区具体怎么工作的,我们完全不需要关心,而只要知道有这么 4 个区就够了:

  • 工作区( Working Area )

  • 暂存区( Stage )

  • 本地仓库( Local Repository )

  • 远程仓库( Remote Repository )

5种状态

以上 4 个区,进入每一个区成功之后会产生一个状态,再加上最初始的一个状态,一共是 5 种状态。以下我们把这 5 种状态分别命名为:

  • 未修改( Origin )

  • 已修改( Modified )

  • 已暂存( Staged )

  • 已提交( Committed )

  • 已推送( Pushed )

检查修改

了解了基本概念之后,我们来谈一谈犯错误之后如何撤销的问题。首先,我们要了解如何检查这 3 个步骤当中每一个步骤修改了什么,然后才好判断有没有修改成功。检查修改的二级命令都相同,都是 diff ,只是参数有所不同。

已修改,未暂存

git diff

首先,我们来看一下,如果我们只是简单地在浏览器里保存了一下文件,但是还没有做 git add . 之前,我们如何检查有哪些修改。我们先随便拿一个文件来做一下实验:


我们在文件开头的第 2 行胡乱加了 4 个数字 1234 ,存盘,这时文件进入了 已修改 状态,但是还没有进入 暂存区 ,我们运行 git diff ,结果如下:

diff --git a/index.md b/index.md
index
73ff1ba..1066758 100644
--- a/index.md
+++ b/index.md
@@ -1,5 +1,5 @@
---
-layout: main
+1234layout: main
color
: black
---

git diff 的结果告诉我们哪些文件已经做了哪些修改。

已暂存,未提交

git diff --cached

现在我们把修改放入 暂存区 看一下。先执行 git add . ,然后执行 git diff ,你会发现没有任何结果:

这说明 git diff 这个命令只检查我们的 工作区 和 暂存区 之间的差异,如果我们想看到 暂存区 和 本地仓库 之间的差异,就需要加一个参数 git diff —cached :

diff --git a/index.md b/index.md
index
73ff1ba..1066758 100644
--- a/ index.md
+++ b/index.md
@@ -1,5 +1,5 @@
---
-layout: main
+1234layout: main
color
: black
---

这时候我们看到的差异是 暂存区 和 本地仓库 之间的差异。

已提交,未推送

git diff master origin/master

现在,我们把修改从 暂存区 提交到 本地仓库 ,再看一下差异。先执行 git commit ,然后再执行 git diff —cached ,没有差异,执行 git diff master origin/master ,可以看到差异:

在这里, master 就是你的 本地仓库 ,而 origin/master 就是你的 远程仓库 , master 是主分支的意思,因为我们都在主分支上工作,所以这里两边都是 master ,而 origin 就代表远程。

撤销修改

了解清楚如何检查各种修改之后,我们开始尝试各种撤销操作。

已修改,未暂存

如果我们只是在编辑器里修改了文件,但还没有执行 git add . ,这时候我们的文件还在 工作区 ,并没有进入 暂存区 ,我们可以用:

git checkout .

或者

git reset --hard

来进行撤销操作。

可以看到,在执行完 git checkout . 之后,修改已被撤销, git diff 没有任何内容了。

git add . 的反义词是 git checkout . 做完修改之后,如果你想向前走一步,让修改进入 暂存区 ,就执行 git add . ,如果你想向后退一步,撤销刚才的修改,就执行 git checkout . 。

已暂存,未提交

你已经执行了 git add . ,但还没有执行 git commit -m “comment” 。这时候你意识到了错误,想要撤销,你可以执行:

git reset
git checkout
.

或者

git reset --hard

git reset 只是把修改退回到了 git add . 之前的状态,也就是说文件本身还处于 已修改未暂存 状态,你如果想退回 未修改 状态,还需要执行 git checkout . 。

或许你已经注意到了,以上两个步骤都可以用同一个命令 git reset —hard 来完成。是的,就是这个强大的命令,可以一步到位地把你的修改完全恢复到 未修改 的状态。

已提交,未推送

你的手太快,你既执行了 git add . ,又执行了 git commit ,这时候你的代码已经进入了你的 本地仓库 ,然而你后悔了,怎么办?不要着急,还有办法。

git reset --hard origin/master

还是这个 git reset —hard 命令,只不过这次多了一个参数 origin/master ,正如我们上面讲过的, origin/master 代表 远程仓库 ,既然你已经污染了你的 本地仓库 ,那么就从 远程仓库 把代码取回来吧。

已推送

很不幸,你的手实在是太快了,你既 git add 了,又 git commit 了,并且还 git push 了,这时你的代码已经进入 远程仓库 。如果你想恢复的话,还好,由于你的 本地仓库 和 远程仓库 是等价的,你只需要先恢复 本地仓库 ,再强制 push 到 远程仓库 就好了:

git reset --hard HEAD^
git push
-f

总结

以上 4 种状态的撤销我们都用到了同一个命令 git reset —hard ,前 2 种状态的用法甚至完全一样,所以只要掌握了 git reset —hard 这个命令的用法,从此你再也不用担心提交错误了。

最后,为你推荐

【第1083期】git commit 时使用 Emoji

【第471期】闯过这 54 关,点亮你的 Git 技能树

关于本文
作者:@张京
原文:https://segmentfault.com/a/1190000011969554

招聘

【招聘】阿里大数据诚邀你加入

【招聘】美团点评技术工程部 - 前端技术中心招聘啦


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/oP6yLSIWrx
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/4279
 
928 次点击