Git教程3——撤销更改
2015-09-22 09:26
411 查看
上一节中,我们学习了如何在代码仓库中记录版本。我们之所以不辞辛苦的记录,那只是为了,如果某一天项目进展失败至少还有可用的版本,并且我们还可以由此确定麻烦代码被引入的位置。
不过,保存下来的”安全可用”版本如果不能恢复那就一文不值了。接下来将要学习的是如何查看项目的先前状态,并恢复之,最后重置未提交的更改。
![](https://img-blog.csdn.net/20150909174819289)
点击下载本节的代码仓库
如果你学习过前面的章节,那就不需要下载上面的代码仓库了。如果没有,直接下载并解压就可以继续了。
输出类似如下的信息:
Git仅仅输出了校验和的前7个字符(查看完整的校验和使用git log)。不过起始的几个字符足以用来唯一标识一次提交了。
执行命令后,会输出很多关于
使用编辑器或者浏览器打开HTML文件验证我们在第三次提交时添加的链接已经消失了。此时
![](https://img-blog.csdn.net/20150921161509615)
现在,
![](https://img-blog.csdn.net/20150921162014530)
在上一章中,我说过Git被设计为从不舍弃任何提交记录。那么,我们的第二次和第三次提交哪儿去了?简单的
将之与上一章的输出相比较:
上一章中我们所有的操作都发生在master分支,第二次和第三次提交也存在于该分支上。要获取我们所有的历史记录,仅仅需要检出该分支。现在仅仅只是对分支做简要的说明,然而有这些知识就足以让我们在各个提交之间切换了。下一章我们会详细讨论分支。
该命令使得Git更新我们的工作目录来反映master分支的快照状态。它重新生成了
![](https://img-blog.csdn.net/20150921163600284)
标记是软件项目的正式发本版本和一些重大的里程碑。方便开发者浏览和检出重要的版本。例如,现在我们可以使用v1.0标签替代随机ID来标识第三次提交。查看标记列表,不带参数执行
上面的命令中,
在通过
不出意料的话该次提交会出现在仓库的提交历史中。如果输出的信息太多,你可以通过Space键滚动查看或者键入q退出到命令行。
在查看稳定版本后,我们决定舍弃该次的疯狂实验。但是,在我们撤销更改之前,我们需要回到主分支。如果不这样,那么所有的更新都将发生在一个不存在的分支上。正如下一章将要介绍的那样,绝不要在老版本上直接更改。
此时我们的仓库历史记录类似如下:
该操作会弹出一个默认的提交信息
值得注意的是,Git没有删掉
![](https://img-blog.csdn.net/20150921173254598)
在使用
在接下来的小节中,我们准备放弃该实验。由于
我们有一个已跟踪的和一个未跟踪的文件需要更改。首先处理
该命令将所有已跟踪文件恢复到最近提交的状态。注意
接下来,我们删除
这将删除掉所有未跟踪文件。在删除掉
注意
![](https://img-blog.csdn.net/20150921181107656)
我提到过,
本章同样介绍了如何使用
不过,保存下来的”安全可用”版本如果不能恢复那就一文不值了。接下来将要学习的是如何查看项目的先前状态,并恢复之,最后重置未提交的更改。
点击下载本节的代码仓库
如果你学习过前面的章节,那就不需要下载上面的代码仓库了。如果没有,直接下载并解压就可以继续了。
显示提交校验和(Display Commit Checksums)
首先快速预览一下仓库的提交历史。在命令行界面(或Git Bash中)切换到my-git-repo目录中,然后执行
git log --oneline
输出类似如下的信息:
1c310d2 Add navigation links 54650a3 Create blue and orange pages b650e4b Create index page
Git仅仅输出了校验和的前7个字符(查看完整的校验和使用git log)。不过起始的几个字符足以用来唯一标识一次提交了。
查看老版本
使用git checkout命令,可以查看以前的快照内容。请确保将以下命令中的
54650a3替换为你的第二次提交ID。
git checkout 54650a3
执行命令后,会输出很多关于
detached HEAD状态的信息,暂时忽略这些。你只需要知道上面的命令将
my-git-repo目录中内容变成了第二次快照的内容(参看上一章的基础知识)。
使用编辑器或者浏览器打开HTML文件验证我们在第三次提交时添加的链接已经消失了。此时
git log命令不再显示第三次提交的信息了。在检出第二次提交后,我们的仓库历史看起来如下图(红色的圆圈代表当前的提交)。
查看更老的版本
让我们回溯到更久远的历史。注意将b650e4b替换成你的第一次提交ID。
git checkout b650e4b
现在,
blue.html和
orange.html文件都消失了,下面是git log的历史记录。
在上一章中,我说过Git被设计为从不舍弃任何提交记录。那么,我们的第二次和第三次提交哪儿去了?简单的
git status命令可以告诉我们。它应该输出以下信息:
# Not currently on any branch. nothing to commit (working directory clean)
将之与上一章的输出相比较:
# On branch master nothing to commit (working directory clean)
上一章中我们所有的操作都发生在master分支,第二次和第三次提交也存在于该分支上。要获取我们所有的历史记录,仅仅需要检出该分支。现在仅仅只是对分支做简要的说明,然而有这些知识就足以让我们在各个提交之间切换了。下一章我们会详细讨论分支。
返回当前的版本
我们使用相同的git checkout命令来返回master分支。
git checkout master
该命令使得Git更新我们的工作目录来反映master分支的快照状态。它重新生成了
blue.html和
orange.html文件,并且更新了
index.html的内容。我们已经回到了项目的当前状态,此时提交历史记录如下:
标记一个发布版本
假如现在这个实例网站项目是一个稳定版本。我们可以给最近的提交标记一个版本数字。git tag -a v1.0 -m "Stable version of the website"
标记是软件项目的正式发本版本和一些重大的里程碑。方便开发者浏览和检出重要的版本。例如,现在我们可以使用v1.0标签替代随机ID来标识第三次提交。查看标记列表,不带参数执行
git tag命令。
上面的命令中,
-a选项使得Git创建一个带注释的标记,意味着我们可以记录我们的名字,日期,以及一个描述性的文字(通过
-m选项指定)。使用这个标记,在我们进行一些疯狂的实验之后还能找到稳定的版本。
疯狂实验
现在我们可以随意的向示例网站中添加一些试验性的更改。创建文件crazy.html添加如下HTML.
<!DOCTYPE html> <html lang="en"> <head> <title>A Crazy Experiment</title> <meta charset="utf-8" /> </head> <body> <h1>A Crazy Experiment</h1> <p>We're trying out a <span style="color: #F0F">crazy</span> <span style="color: #06C">experiment</span>! <p><a href="index.html">Return to home page</a></p> </body> </html>
暂存并提交快照
照旧执行如下命令git add crazy.html git status git commit -m "Add a crazzzy experiment" git log
在通过
git commit -m提交前,最好是使用
git status确认你要提交的内容。这样可以防止无意中提交了不属于该快照的文件。
不出意料的话该次提交会出现在仓库的提交历史中。如果输出的信息太多,你可以通过Space键滚动查看或者键入q退出到命令行。
查看稳定的提交
让我们回到稳定版本。现在v1.0标记可以代替第三次的提交ID使用。
git checkout v1.0
在查看稳定版本后,我们决定舍弃该次的疯狂实验。但是,在我们撤销更改之前,我们需要回到主分支。如果不这样,那么所有的更新都将发生在一个不存在的分支上。正如下一章将要介绍的那样,绝不要在老版本上直接更改。
git checkout master git log --oneline
此时我们的仓库历史记录类似如下:
514fbe7 Add a crazzzy experiment
1c310d2 Add navigation links 54650a3 Create blue and orange pages b650e4b Create index page
撤销已提交的更改
我们准备通过删除最近的提交来恢复到稳定的版本。在执行以下命令前,请确保将514fbe7替换成为你的疯狂实验提交ID。
git revert 514fbe7
该操作会弹出一个默认的提交信息
Revert "Add a crazy experiment"…保持默认然后关闭文件即可。此时
crazy.html文件已经消失,执行
git log --oneline查看历史记录
506bb9b Revert "Add a crazzzy experiment"
514fbe7 Add a crazzzy experiment
1c310d2 Add navigation links 54650a3 Create blue and orange pages b650e4b Create index page
值得注意的是,Git没有删掉
crazzzy experiment这次提交,而是根据此次提交进行相应的撤销,然后使用撤销后的内容进行一次新的提交。因此,我们的第五次提交和第三次提交代表了相同的快照内容,如下图。重申一次,Git不会丢失历史:第四次快照仍然可以访问,以备我们需要继续开发。
在使用
git revert命令时,记得指定你需要撤销的提交——而不是你想要恢复到的稳定提交。最好是将该命令理解为”撤销该提交”而不是“恢复该版本”。
进行一次小型实验
接下来尝试一次小型的实验。创建dummy.html空白文件。然后在
index.html中的“Navigation”中添加一个链接,如下:
<h2>Navigation</h2> <ul> <li style="color: #F90"> <a href="orange.html">The Orange Page</a> </li> <li style="color: #00F"> <a href="blue.html">The Blue Page</a> </li> <li> <a href="dummy.html">The Dummy Page</a> </li> </ul>
在接下来的小节中,我们准备放弃该实验。由于
git revert命令需要指定一个提交ID,因此我们不能使用前面讨论的方法。
撤销未提交的更改
在撤销之前,首先查看仓库的状态。git status
我们有一个已跟踪的和一个未跟踪的文件需要更改。首先处理
index.html:
git reset --hard
该命令将所有已跟踪文件恢复到最近提交的状态。注意
--hard选项是必需的,否则
git reset命令仅仅将index.html置为未跟踪状态,保留其中的内容。不过在两种情况下,
git reset命令仅仅作用于工作目录和暂存区,因此我们的
git log历史记录不变。
接下来,我们删除
dummy.html。我们当然可以手动删除掉它,但是借助于Git来重置(reset)可以消除掉大型团队处理多个文件时可能会有的错误。运行以下命令:
git clean -f
这将删除掉所有未跟踪文件。在删除掉
dummy.html后,
git status会显示工作目录为
clean状态,意味着我们的工作目录跟最近的提交匹配。
注意
git reset和
git clean命令都是作用于工作目录,而不是已提交的快照。跟
git revert不同的是,这些命令会永久的撤销更改,所以使用之前请三思。
总结
正如我们在上一章中提到的,大部分的Git命令都是作用于Git仓库的三个主要组成部分:工作目录,暂存快照区,提交快照区。git reset的撤销动作作用于工作目录和暂存区,
git revert则作用于已提交的快照。同理,
git status和
git log也是如此(
git status作用于工作目录和暂存区,
git log作用于提交区)。
我提到过,
git revert不会删除一次提交,以备你再次访问。当然这只是git保留提交快照的一个原因,我们会看到,在多个开发者协同工作时删除一个提交会造成严重的后果。
本章同样介绍了如何使用
git checkout在不同的提交和分支之间切换。加上分支,我们就完成了对git核心组件的讨论,并且分支的概念使得我们的工作流程更加优雅。下一章中,我们将会讨论分支的基本命令。
快速参考
git checkout <commit-id> View a previous commit. git tag -a <tag-name> -m "<description>" Create an annotated tag pointing to the most recent commit. git revert <commit-id> Undo the specified commit by applying a new commit. git reset --hard Reset tracked files to match the most recent commit. git clean -f Remove untracked files. git reset --hard / git clean -f Permanently undo uncommitted changes.
相关文章推荐
- Oracle 11g 的PL/SQL函数结果缓存
- (转载)iOS 极光推送SDK 集成指南
- 在C++中怎么输入反斜杠“ \ ”
- Linux系统下git系列笔记(一)
- Linux学习记录(12)ACL基本概念及基础操作
- Thinkphp修改默认模板引擎为smarty如何操作
- vi和vim编辑器
- Co-variant array conversion from x to y may cause run-time exception
- datagridview连接数据库的简单实现
- 使用消息系统避免分布式事务
- 修改高通linux内核的配置文件
- 谷歌为什么从WebKit中建立一个Blink分支
- Android 墙纸设置代码 详细说明
- lvs DR模式
- LeetCode算法第6篇:237 Delete Node in a Linked List
- 接口测试及httpclient深入
- cuda创建dll工程
- java接口理解(转载)
- 个人项目终极博客——四则运算题目生成程序分析
- Nginx 在安装入门