GitHub-暂存区与版本回退
参考博文:廖雪峰Git教程
1. 工作区和暂存区
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
1.1. 工作区(Working Directory)
就是你在电脑里能看到的目录.比如:zhangtest
1 [root@mini05 zhangtest]# pwd
2 /opt/git_repository/zhangtest
3 [root@mini05 zhangtest]# ll
4 total 8
5 -rw-r--r-- 1 root root 96 Sep 23 20:54 README.md
6 -rw-r--r-- 1 root root 12 Sep 17 23:27 test.info
1.2. 版本库(Repository)
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
测试实践
对README.md追加一些内容;新建LICENSE并添加内容。
1 [root@mini05 zhangtest]# ll
2 total 12
3 -rw-r--r-- 1 root root 16 Sep 29 19:17 LICENSE
4 -rw-r--r-- 1 root root 104 Sep 29 19:18 README.md
5 -rw-r--r-- 1 root root 12 Sep 17 23:27 test.info
6 [root@mini05 zhangtest]#
7 [root@mini05 zhangtest]# git status
8 # On branch master
9 # Your branch is ahead of 'origin/master' by 2 commits.
10 # (use "git push" to publish your local commits)
11 #
12 # Changes not staged for commit:
13 # (use "git add <file>..." to update what will be committed)
14 # (use "git checkout -- <file>..." to discard changes in working directory)
15 #
16 # modified: README.md
17 #
18 # Untracked files:
19 # (use "git add <file>..." to include in what will be committed)
20 #
21 # LICENSE
22 no changes added to commit (use "git add" and/or "git commit -a")
由上可知:Git非常清楚地告诉我们,README.txt
被修改了,而LICENSE
还从来没有被添加过,所以它的状态是Untracked
。
现在,使用两次命令git add
,把readme.txt
和LICENSE
都添加后,用git status
再查看一下:
1 [root@mini05 zhangtest]# git add README.md
2 [root@mini05 zhangtest]# git add LICENSE
3 [root@mini05 zhangtest]#
4 [root@mini05 zhangtest]# git status
5 # On branch master
6 # Your branch is ahead of 'origin/master' by 2 commits.
7 # (use "git push" to publish your local commits)
8 #
9 # Changes to be committed:
10 # (use "git reset HEAD <file>..." to unstage)
11 #
12 # new file: LICENSE
13 # modified: README.md
14 #
现在,暂存区的状态就变成这样了:
所以,git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
1 [root@mini05 zhangtest]# git commit -m "understand how stage works"
2 [master 53f0f2e] understand how stage works
3 2 files changed, 6 insertions(+)
4 create mode 100644 LICENSE
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
1 [root@mini05 zhangtest]# git status
2 # On branch master
3 # Your branch is ahead of 'origin/master' by 3 commits.
4 # (use "git push" to publish your local commits)
5 #
6 nothing to commit, working directory clean
现在版本库变成了这样,暂存区就没有任何内容了:
2. 版本回退
在README.md追加了如下内容,并进行了提交。
1 Git is a distributed version control system.
2 Git is free software distributed under the GPL.
提交
1 [root@mini05 zhangtest]# vim README.md
2 # zhangtest
3 zhangtest
4 张三
5 Git is a distributed version control system.
6 Git is free software.
7 Git is a distributed version control system.
8 Git is free software distributed under the GPL.
9 [root@mini05 zhangtest]# git add . # 添加到暂存区
10 [root@mini05 zhangtest]# git commit -m "append GPL" # 提交到仓库
2.1. 查看版本日志信息
1 # 使用 git add . 就是针对当前目录
2 [root@mini05 zhangtest]# git log README.md # 针对README.md文件
3 commit 9f27dce0f57cf811a8e3bdab545e8b98ca9bd41f
4 Author: Zhang San <zhanglianghhh@163.com>
5 Date: Sun Sep 23 20:38:53 2018 +0800
6
7 append GPL
8
9 commit 65a58f2661c4d73dc0dc9c2e5bff4c350c42c98e
10 Author: Zhang San <zhanglianghhh@163.com>
11 Date: Mon Sep 17 23:31:25 2018 +0800
12
13 add info
14
15 commit d4fb57e8a892060db07fe862058a1a8477be49aa
16 Author: 张亮 <zhanglianghhh@163.com>
17 Date: Mon Sep 17 23:10:57 2018 +0800
18
19 Update README.md
20
21 commit e7306765445375e4c1b52ebde07a666da5517b22
22 Author: 张亮 <zhanglianghhh@163.com>
23 Date: Mon Sep 17 22:34:57 2018 +0800
24
25 Initial commit
2.2. 简化版本日志
1 [root@mini05 zhangtest]# git log --pretty=oneline README.md
2 9f27dce0f57cf811a8e3bdab545e8b98ca9bd41f append GPL
3 65a58f2661c4d73dc0dc9c2e5bff4c350c42c98e add info
4 d4fb57e8a892060db07fe862058a1a8477be49aa Update README.md
5 e7306765445375e4c1b52ebde07a666da5517b22 Initial commit
2.3. 版本回退到65a58f2661
在Git中,用HEAD
表示当前版本,也就是最新的提交9f27dce...
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
1 # git reset --hard 65a58f2661 回退到指定版本,好处就是不用计算到底回退几个版本
2 [root@mini05 zhangtest]# git reset --hard HEAD^ # 回退到上一个版本
3 HEAD is now at 65a58f2 add info
4 [root@mini05 zhangtest]# cat README.md # 查看内容,可见以回退到上一个版本
5 # zhangtest
6 zhangtest
7 张三
8 Git is a distributed version control system.
9 Git is free software.
10 [root@mini05 zhangtest]# git log --pretty=oneline README.md # 根据提交日志,也可知已回退
11 65a58f2661c4d73dc0dc9c2e5bff4c350c42c98e add info
12 d4fb57e8a892060db07fe862058a1a8477be49aa Update README.md
13 e7306765445375e4c1b52ebde07a666da5517b22 Initial commit
2.4. 回退原理
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD
指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL
:
改为指向add info
:
然后顺便把工作区的文件更新了。所以你让HEAD
指向哪个版本号,你就把当前版本定位在哪。
2.5. 记录每一次命令
回退到了某个版本,想恢复到新版本怎么办?找不到新版本的commit id
怎么办?
Git提供了一个命令git reflog
用来记录你的每一次命令:
用git reflog
查看命令历史,以便确定要回到未来的哪个版本。
1 [root@mini05 zhangtest]# git reflog
2 65a58f2 HEAD@{0}: reset: moving to 65a58f2661
3 9f27dce HEAD@{1}: reset: moving to 9f27dce0f57cf
4 65a58f2 HEAD@{2}: reset: moving to HEAD^
5 9f27dce HEAD@{3}: commit: append GPL
6 65a58f2 HEAD@{4}: commit: add info
7 d4fb57e HEAD@{5}: pull git@github.com:zhanglianghhh/zhangtest.git: Fast-forward
8 e730676 HEAD@{6}: clone: from git@github.com:zhanglianghhh/zhangtest.git
- SQL Server 深入解析索引存储(上)
- 1475: 方格取数
- python3 将字典,列表等转换成字符串形式存入mysql数据库并复原成字典,列表(处理稍复杂的格式)
- 1441: Min
- 2429: [HAOI2006]聪明的猴子
- 使用apt-get 安装后的mysql 登录问题
- SQL Server 深入解析索引存储(中)
- 1789: [Ahoi2008]Necklace Y型项链
- 3399: [Usaco2009 Mar]Sand Castle城堡
- 遗传算法(1)
- LOJ#6284. 数列分块入门 8
- 3713: [PA2014]Iloczyn
- 洛谷P3195 [HNOI2008]玩具装箱TOY(单调队列优化DP)
- SQL Server 深入解析索引存储(下)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- CNS图表复现04—单细胞聚类分群的resolution参数问题
- 学习Vue3.0,先从搭建环境开始
- AIM Tech Round 5 (rated, Div. 1 + Div. 2)C. Rectangles
- PAT (Basic Level) Practice (中文)1006 换个格式输出整数 (15 分)
- 编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(二)语法分析
- PAT (Basic Level) Practice (中文)1023 组个最小数 (20 分)
- Angular里使用createEmbeddedView动态加入新的模板元素
- PAT (Basic Level) Practice (中文)1002 写出这个数 (20 分)
- [笔记整理]几个有点重要的知识点
- PAT (Basic Level) Practice (中文)1005 继续(3n+1)猜想 (25 分)
- PAT (Basic Level) Practice (中文)1033 旧键盘打字 (20 分)
- SAP电商云CCV2 Restful API enablement
- PAT (Basic Level) Practice (中文)1007 素数对猜想 (20 分)
- 两种方式解决子集问题
- PAT (Basic Level) Practice (中文)1035 插入与归并 (25 分)