Git高级操作:reset,checkout,revert

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Git高级操作:reset,checkout,revert相关的知识,希望对你有一定的参考价值。

参考技术A git reset , git checkout ,和 git revert 命令是Git工具箱中最有用的几个工具之一。他们都用来撤销仓库中的某种修改,其中前两个命令可以用来撤销针对提交或者单个文件的修改。

因为如此相似,在特定开发场景下很容易出现不知道该使用那个命令的情况。在本文中我们会比较 git reset , git checkout 和 git revert 命令最常见的使用方式。希望在本文结束时读者能够在自己的项目中胸有成竹地使用对应的命令。

checkout操作会将当前 HEAD 指针指向指定的提交。请参见下图:

revert操作撤销指定提交并创建一个新的提交,其内容为指定提交的所有逆向修改。 git revert 只能运行在提交层面,不能对指定文件操作。

reset操作接受一次commit作为参数,并将git的三棵树状态重置到指定的这次commit的相同状态。reset操作可以在三棵树的不同状态下执行。

checkout和reset通常用于本地或者私有分支的撤销操作。修改之后的提交历史,在推送到共享的远程仓库时会引发冲突。反之revert操作的“公共撤销”通常被认为是安全的。因为revert操作会为撤销动作创建一次提交,而这个撤销历史也会被其他人得到,并且revert操作也不会覆盖团队其他成员可能依赖的提交历史。

下表总结了这些命令的常用场景。

向 git reset 和 git checkout 命令传递的参数决定了其影响范围。使用命令时不含文件路径则会让操作作用于整个提交。接下来这部分我们会主要讨论相关内容。注意 git revert 没有文件层面的操作。

在提交层面,重置可以移动分支顶端到其他提交。基于这一特性,重置可以用于删除分支中的提交。比如,下面的命令将 hotfix 分支的顶端向前移动了两个提交。

hotfix 分支的最后两个提交现在称为孤立的提交。这意味着下次Git执行垃圾回收时会删除他们。换句话说,如此操作意味着你要丢弃这些提交。这一过程可以通过下图表示:

除了移动当前分支以外,你还可以传递以下选项,用 git reset 来变更暂存快照或者工作目录:

git checkout 命令用于更新仓库状态到指定的项目提交历史。当传递的参数是一个分支名称,则用于切换分支。

在命令内部,以上所有命令都是移动 HEAD 指针到不同分支,并相应的更新工作目录。由于这一操作具有潜在的覆盖本地变更的可能性,因此Git会强制你在checkout操作之前执行commit或者stash命令,以便存储可能由于checkout丢失的变更。与 git reset 不同, git checkout 不会移动分支本身的指针。

revert命令通过新建一个提交来撤销之前的一个提交。因为这一操作不会重写提交历史所以被认为是一种安全的撤销操作。比如下面的例子中,Git会搞清楚倒数第二次提交的内容,然后创建一个新的提交用于撤销这些内容,并且将新提交的撤销动作提交到当前的项目中。

此过程图示如下:

你也可以理解为 git revert 用于撤销已提交的变更, git reset 用于撤销未提交的变更。

与 git checkout 一样, git revert 操作也会导致潜在的文件覆盖,所以Git也会要求在revert之前先进行commit或者stash操作。

git reset 和 git checkout 命令也接受文件路径作为可选参数。这也让其行为与上面所介绍的功能完全不一样。相比于操作整个快照,附加的文件路径参数限制相应操作的影响范围到单个文件。

当附加了文件路径作为参数时, git reset 会根据指定提交更新暂存快照。比如下面的命令会获取 foo.py 文件在倒数第二次提交时的快照,根据快照内容变更文件,并暂存它,等待下一次提交:

相比于针对提交的 git reset 命令,上面的命令更多地用于 HEAD 。执行 git reset HEAD foo.py 会取消 foo.py 的暂存,但其中的改变仍然在工作目录中。

checkout一个文件与使用 git reset 命令传递文件路径类似,除了checkout更新的是工作目录,而不是更新暂存快照。另外,与执行checkout命令关于提交的操作不同,checkout一个提交会改变 HEAD 的指向,而checkout文件不改变 HEAD ,仅改变文件内容。也就意味着执行这个命令不会切换分支。

就像操作提交时使用 git checkout ,这也可以用于查看项目的旧版本——不过这次是查看指定文件的旧版本。

如果你暂存并提交了checkout出来的旧版本文件,其执行结果也含有将指定文件 revert 到旧版本的效果。不过请注意这一操作也同时移除了该文件从旧版本之后的所有后续变更历史,然而 revert 命令仅撤销指定提交的变更。

就像 git reset ,这种情况也通常与 HEAD 搭配使用。比如, git checkout HEAD foo.py 执行的结果就含有丢弃 foo.py 文件未暂存的变更的效果。这个行为类似于 git reset HEAD --hard ,只不过影响范围仅限于指定文件。

到现在为止,你应该已经拥有用于在Git仓库中撤销变更所需的所有知识了。 git reset , git checkout ,和 git revert 命令容易混淆,但是当你考虑到他们分别在工作目录,暂存快照和提交历史上的可能产生的影响,就不难在开发中分辨出应该使用哪个命令。

原文地址:https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting

git中的撤销删除操作总结(git cleangit checkout和git reset)

文章目录

1. 删除未跟踪的文件-git clean

如下所示,test.cpp为新建文件,它属于未跟踪的文件。使用git clean从你的工作目录中删除所有没有tracked,没有被管理过的文件。删除了就找不回了,一定要慎用。

使用git clean -h查看参数意义:

    -q, --quiet           不打印删除文件的名称
    -n, --dry-run         演习
    -f, --force           强制
    -i, --interactive     交互式清除
    -d                    删除整个目录
    -e, --exclude <模式>  添加 <模式> 到忽略规则
    -x                    也删除忽略的文件
    -X                    只删除忽略的文件

这里的忽略文件指的是gitignore。如果担心误删,建议每次使用git clean时候,最好加上交互式参数i,避免误删

2. 已修改,未暂存-git checkout/git reset

下列master.txt是被修改过的文件,但是还没有加入暂存区,也就是没有使用git add操作,此时如果不想要这个修改,可以使用git checkout删除此次修改,恢复到修改之前的状态。

使用方式:

#方法一:删除master.txt的修改
git checkout master.txt

#方法二:删除所有修改
git checkout .

#方法三:回退
git reset --hard

3. 已暂存,未提交-git reset

下列master.txt,已经提交git add,但是没有git commit


此时如果想要删除此次已经提交的修改,也就是说暂存区的内容不想要了,或者只是想要把暂存区的内容还原至修改的状态。可以使用下列的一些命令:

#方法一:删除暂存区和修改的工作区
git reset --hard

#方法二:只是把暂存区回退至修改的状态
git reset HEAD

#方法三:只是把暂存区回退至修改的状态
git reset HEAD file.txt

4. 已提交,未推送-git reset

如果已经进行至git commit,但是还没有push至远程,这种情况直接回退版本就可以了。

#方法一:回退至上一版本
git reset HEAD^
#注意 HEAD 就是回退到当前版本,git reset HEAD^ 回退到上一版本

#方法二:回退至指定版本 
git reset <版本号> #git log 去查版本号

# 方法三:只是撤销commit,但是修改还会在
git reset --soft HEAD^

# 方法四:使用远程仓库覆盖本地仓库
git reset --hard origin/master 

5. 已推送的修改

如果把本地的代码push至远程,此时可以采用回滚的形式回退版本,然后强制推送覆盖远程仓库。

以此执行下列代码:

git reset --hard HEAD^ #回退至上一版本
git push origin HEAD --force #强制提交一次,之前错误的提交就从远程仓库删除

如果还想要找回之前的修改,可以使用git reflog,或者结合第四步一起使用。

以上是关于Git高级操作:reset,checkout,revert的主要内容,如果未能解决你的问题,请参考以下文章

git中的撤销删除操作总结(git cleangit checkout和git reset)

GIT checkout 和 reset 区别

git中reset和checkout的总结整理

Git之深入解析reset命令原理以及与checkout命令的区别

git checkout与git reset有什么区别吗

Git重置(reset)