当前位置:首页 > 英文周记 > 正文内容

包含revertcommit的词条

更新时间:2026-07-18 07:01:17 周记网3年前 (2023-03-23)英文周记94

Git撤销与合并

1. git init

包含revertcommit的词条

创建一个空的git repo,也就是创建一个.git的子目录,这个目录包含了几乎所有git存储和操作的东西。新初始化的.git目录的典型结构如下:

description文件仅供git web程序使用,平常无需关心。

config文件包含项目特有的配置选项。

info目录包含一个全局性排除文件,用以放置那些不希望被记录在.gitignore文件中的忽略模式。

hooks目录包含客户端或服务端的钩子脚本。

HEAD文件指向目前被检出的分支。

index文件(尚待创建)保存暂存区信息。

objects目录存储所有数据内容。

refs目录存储指向数据的提交对象的指针。

git的默认分支名字是master,git init时默认创建它。

2. git的三种状态,以及工作区(Working directory),暂存区(Index),HEAD

Git 有三种状态,你的文件可能处于其中之一:已修改(modified)、已暂存(staged)和已提交(committed)

基于刚才init的git project,做一些改动。

会看到在git add之后,.git下面多了一个index文件。

这时候,所做的改动就处于已暂存状态,体现在index文件中。

可以利用以下命令查看git缓存了的内容。

同时,.git/objects下面多了一个子文件夹,并生成了一个新文件。这个新文件就对应了刚才所做的改动。这就是git存储内容的方式--一个文件对应一条内容,以该内容加上特定头部信息一起的SHA-1校验和作为文件名。校验和的前两个字符用于命名子目录,余下的38个字符则作为文件名。后面会详叙。

可以通过cat-file命令从git那里查看存储的内容。

git cat-file -p e69de29bb2d1d6434b8b29ae775ad8c2e48c5391

由于file1.txt的内容为空,所以这里显示为空。

这时候可以往file1.txt里添加一些内容,并git add。可以看到.git/objects又多了一个object。

查看这个新的对象的内容以及类型。会发现它是一个blob对象。

接下来commit这个change。

myProject $ git commit -m "first commit"

查看这个commit 对象的类型以及内容,commit的tree对象所指向的内容, 我们会发现,这个tree指向的是一个blob,而这个blob的内容,就是我们刚刚做过改动的文件。

同时,我们查看一下暂存区的内容:

会发现,暂存区指向的也是同样的blob对象。

至此,一个commit就提交了,工作区,暂存区,以及head又指向了同样的内容。

它们更新内容的顺序为,工作区-暂存区-head

3. git reset

将做过的change撤销掉,就像没有发生过一样。

git reset 应用的顺序为 head-暂存区-工作区。

(1) git reset --soft

当前,git的状态如下。

head指向的内容为:

(head是当前分支引用的指针,总是指向该分支上的最后一次提交。)

index指向的内容为:

(索引是你的预期的下一个提交)

我们来进行一次reset。(移动HEAD, --soft)

--soft将仅仅移动HEAD的指向,而并不会移动index以及工作区。

HEAD 指的是HEAD的父节点。HEAD 是父节点的父节点,也可以写成HEAD 2.

所以这个命令本质上是撤销了上一次git commit命令。

(2) git reset --mixed

接下来,再通过reset来更新索引。(--mixed,默认行为)

(3) git reset --hard

reset更新工作目录(--hard)

git reset --hard HEAD~

--hard标记是reset命令的危险用法,它也是git会真正销毁数据的几个操作之一。

如果这个commit已经被推送到远端,可以用这个命令使远端也回退到相应的版本。

git push origin branch --force

4. git revert

将做过的change撤销掉,通过“反做”某一个版本,用一个新的commit来消除做过的change。

当前git的状态:

revert其中一个commit:

再来看,多了一个commit,也就是用来revert的commit:

而若是想要revert某个版本,但是在这个版本后又做过change,则在revert的过程中可能出现冲突,则需要解决冲突之后再提交。

5. git merge 与git rebase

先来讲讲git merge。

当前master 和 dev branch:

接下来打算将dev的工作并入master分支。

另外,还想将master的工作也并入dev。

git merge之后,会发现dev branch指向了与master相同的commit:

所以,git merge是把两个分支的最新快照,以及两者最近的共同祖先进行三方合并,合并的结果是生成一个新的快照。

接下来,用git rebase来合并分支。

当前的git状态

此时,采用git rebase,将dev的工作并入到master。

当在master branch上执行git rebase dev的时候,实际发生的事情是,找到master和dev两个分支的最近共同祖先,对比当前分支(master分支)相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将master分支指向目标基底(dev的head指向的commit),最后以此将之前另存为临时文件的修改依序应用。

可以看到,rebase使得提交历史更加整洁。尽管实际的开发工作是并行在不同branch上进行的,但是它们看上去就像是串行的一样,提交历史是一条直线没有分叉。

因此,变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。这两种方式,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同。

Git新手教程-撤销更改(七)

在前面的文章中,我们学习了标签、分支、和合并。现在我们将学习Git中另外的三个命令 git commit --amend , git revert , git reset 。下面简单的介绍中几个命令的功能:

在平时的项目开发中,有时候我们可能提交完相应文件后,才发现漏掉了几个文件没有添加,或者我们 commit 消息并没有书写完整或有错别字。那这个时候我们该整么办呢?或许我们会执行一个新的提交来添加我们遗漏的内容,但是这样一点都不优雅!!在Git中为我们提供了带有 --amend 选项的提交来修改我们 最近 的提交:

这里大家可能还是不是很明白,我们看下面这个简单的例子:

在上述例仓库中我们创建了一个 commit ,该 commit 消息并没有书写完整。这个时候我们想修改它,那么我们就可以使用命令 git commit --amend ,当输入该命令后,我们能得到如下弹窗:

这个时候,我们就可以完善该 commit 信息,然后保存并离开。这里我改成了 删除了多余的语句 ,这时我们再使用 git log 命令,我们会发现我们的 commit 消息已经被更改了。如下所示:

当然在上述例子中,我们只是简单的修改了 commit 信息,并没有修改或添加一些新的文件,如果你修改或添加了新的文件,并想将这些修改的文件添加到最近的 commit 中去的话,那么你可能要经历以下步骤:

在实际的项目中,如果你想修改最近的 commit ,那么你需要使用 git commit --amend 来更新最近的 commit ,而不是创建新的 commit 。

在上述例子中,我们知道了如何修改最近的 commit ,但是如果我们想还原这个 commit 。那这个时候,我们又该怎么办呢?我们可以使用 git revert 命令来告诉 Git 还原之前创建的commit,该命令使用的方式如下:

还是以上述例子来进行讲解,比如我们想还原下图中红色框中的 commit :

我们可以使用 git revert b71b40 ,需要注意的是使用该命令,默认会创建一个新的提交。如下图所示:

一般情况下,我们可以使用Git系统默认的 revert 信息。当我们保存并退出后,再使用 git log 命令查看我们的日志提交记录,我们能得到下图:

在上述例子中,我们学会了如何还原一个提交,但是如果我们本是这个提交就是错误的,我们并不想要这个提交,也不想仓库记录中包含 revert 的提交记录。这个时候我们又该怎么办呢?我们可以使用 git reset 命令来告诉 Git 重置 commit 。

重置(reset) 似乎和 还原(revert) 相似,但它们实际上差别很大。还原会创建一个新的 commit,并还原或撤消之前的 commit。但是重置会清除 commit!

git reset 命令相比其他 Git 命令功能要多一点,可以用来:

git reset 并不直接使用 commit 的 SHA ,而是使用特殊的 "祖先引用" 来告诉 Git 将 HEAD 指针移动到哪个commit。我们来看看这些特殊的符号。

我们可以通过以下方式引用之前的 commit:

^ 和 ~ 的区别主要体现在通过合并而创建的 commit 中。合并 commit 具有两个父级。对于合并 commit, ^ 引用用来表示第一个父 commit,而 ^2 表示第二个父 commit。第一个父 commit 是当你运行 git merge 时所处的分支,而第二个父 commit 是被合并的分支。

我们看下面的例子,来一起来理解:

因为 HEAD 指向 b71b405 commmit。

了解了祖先引用,现在我们来了解 git reset 命令的使用:

一般情况下,使用该命令,我们会添加如下选项:

直接理解这些选项比较困难,下面我们将结合图片与实际例子来进行讲解。

在下图中,假如我们的仓库中已经有了如下提交 D、E、F、G、H ,其中 master 指向最近的提交 H , HEAD 指向 master 。

这个时候我们如果使用 git reset --mixed HEAD~1 那么会将 master 与 HEAD 将会指向前一个提交 G 。同时 G 提交会移动到工作目录中。如下图所示:

当 H 提交修改的文件被移动到到工作目录后,文件的状态都为 modifed ,也就是我们需要重新添加到暂存区,然后进行 commit 。我们继续看下面的例子:

在上述仓库中有3个提交,其中 HEAD 指向 bb780f9 上的 master , 这个时候如果我们运行 git reset HEAD~ 命令,会将 commit bb780f9 中的文件移动到工作目录中,如下所示:

调用 git status 来查看我们的仓库状态,我们会发现使用 --mixed 选项,是不会暂存我们的更改的,也就是不会将相应提交的文件放入暂存区中。

当使用 --soft 选项时,不仅会移动 master 与 HEAD 指针,还会将相应修改添加到暂存区中,如下所示:

我们继续查看下面的例子:

最后我们再来看看 --hard 选项:

使用 --hard 将清除对应 commit 所作的更改,继续查看下面的?的例子:

当使用了 --hard 选项后,发现仓库中对应的提交消失了。

当我们直接使用 git reset 或 git reset HEAD 时,表示清除暂存区中的 commit 。下面我们来看这个例子:

那么如果我们只想将 B.java 文件从暂存区中移除,那我们又该怎么办呢?我们可以使用如下命令:

当然在Git中支持多个文件的取消暂存,具体命令如下:

在上述命令中 file... 代表一个或多个文件。

最后还是回到我们熟悉的图形化界面的使用流程中。我们来看看IDEA为我们提供了哪些便利吧。

在创建相应 commmit 时,我们可以勾选下图中的

Amend commit 选项。如下所示:

上述操作与使用 git commit --amend 命令的效果一样。

通过依次点击编译器底部的 Version Control - Log ,然后选择想要 revert 的 commit ,点击鼠标 右键 ,选择 Revert Commit 就可以啦~

通过依次点击编译器底部的 Version Control - Log ,然后选择想要 reset 的 commit ,点击鼠标 右键 ,选择 Reset Current Branch to Here.. 就完成第一步啦~

当然在第二步中,我们需要选择 git reset 中的选项,在 IDEA 中提供了四种选项 Soft、Mixed、Hard、Keep ,如下所示:

在上图中,我们不熟悉的只有 --keep 选项,因为该选项在平时中的项目并不常用,所以这里就不做更多介绍了,有兴趣的小伙伴,可以查看官方文档中 git reset 中对其的介绍。

站在巨人的肩膀上,才能看的更远~

Git 不要只会 pull 和 push,试试这 5 条提高效率的命令

使用 Git 作为代码版本管理,早已是现在开发工程师必备的技能。可大多数工程师还是只会最基本的保存、拉取、推送,遇到一些commit管理的问题就束手无策,或者用一些不优雅的方式解决。

本文分享我在开发工作中实践过的实用命令。这些都能够大大提高工作效率,还能解决不少疑难场景。下面会介绍命令,列出应用场景,手摸手教学使用,让同学们看完即学会。

官方解释:当您想记录工作目录和索引的当前状态,但又想返回一个干净的工作目录时,请使用git stash。该命令将保存本地修改,并恢复工作目录以匹配头部提交。

stash 命令能够将还未 commit 的代码存起来,让你的工作目录变得干净。

我猜你心里一定在想:为什么要变干净?

应用场景:某一天你正在 feature 分支开发新需求,突然产品经理跑过来说线上有bug,必须马上修复。而此时你的功能开发到一半,于是你急忙想切到 master 分支,然后你就会看到以下报错:

因为当前有文件更改了,需要提交commit保持工作区干净才能切分支。由于情况紧急,你只有急忙 commit 上去,commit 信息也随便写了个“暂存代码”,于是该分支提交记录就留了一条黑 历史 …(真人真事,看过这种提交)

如果你学会 stash,就不用那么狼狈了。你只需要:

就这么简单,代码就被存起来了。

当你修复完线上问题,切回 feature 分支,想恢复代码也只需要:

当有多条 stash,可以指定操作stash,首先使用stash list 列出所有记录:

应用第二条记录:

pop,drop 同理。

stash 代码

填写备注内容,也可以不填直接Enter

在STASHES菜单中可以看到保存的stash

先点击stash记录旁的小箭头,再点击 apply 或者 pop 都可恢复 stash

完全不接触索引文件或工作树(但会像所有模式一样,将头部重置为)。这使您的所有更改的文件更改为“要提交的更改”。

回退你已提交的 commit,并将 commit 的修改内容放回到暂存区。

一般我们在使用 reset 命令时, git reset --hard 会被提及的比较多,它能让 commit 记录强制回溯到某一个节点。而 git reset --soft 的作用正如其名, --soft (柔软的) 除了回溯节点外,还会保留节点的修改内容。

回溯节点,为什么要保留修改内容?

应用场景1:有时候手滑不小心把不该提交的内容 commit 了,这时想改回来,只能再 commit 一次,又多一条“黑 历史 ”。

应用场景2:规范些的团队,一般对于 commit 的内容要求职责明确,颗粒度要细,便于后续出现问题排查。本来属于两块不同功能的修改,一起 commit 上去,这种就属于不规范。这次恰好又手滑了,一次性 commit 上去。

学会 reset --soft 之后,你只需要:

reset --soft 相当于后悔药,给你重新改过的机会。对于上面的场景,就可以再次修改重新提交,保持干净的 commit 记录。

以上说的是还未 push 的commit。对于已经 push 的 commit,也可以使用该命令,不过再次 push 时,由于远程分支和本地分支有差异,需要强制推送 git push -f 来覆盖被 reset 的 commit。

还有一点需要注意,在 reset --soft 指定 commit 号时,会将该 commit 到最近一次 commit 的所有修改内容全部恢复,而不是只针对该 commit。

举个例子:

commit 记录有 c、b、a。

reset 到 a。

此时的 HEAD 到了 a,而 b、c 的修改内容都回到了暂存区。

给定一个或多个现有提交,应用每个提交引入的更改,为每个提交记录一个新的提交。这需要您的工作树清洁(没有从头提交的修改)。

将已经提交的 commit,**出新的 commit 应用到分支里

commit 都提交了,为什么还要**新的出来?

应用场景1:有时候版本的一些优化需求开发到一半,可能其中某一个开发完的需求要临时上,或者某些原因导致待开发的需求卡住了已开发完成的需求上线。这时候就需要把 commit 抽出来,单独处理。

应用场景2:有时候开发分支中的代码记录被污染了,导致开发分支合到线上分支有问题,这时就需要拉一条干净的开发分支,再从旧的开发分支中,把 commit **到新分支。

**单个

现在有一条feature分支,commit 记录如下:

需要把 b **到另一个分支,首先把 commitHash **下来,然后切到 master 分支。

当前 master 最新的记录是 a,使用 cherry-pick 把 b 应用到当前分支。

完成后看下最新的 log,b 已经应用到 master,作为最新的 commit 了。可以看到 commitHash 和之前的不一样,但是提交时间还是保留之前的。微信搜索公众号:Java后端编程,回复:java 领取资料 。

**多个

以上是单个 commit 的**,下面再来看看 cherry-pick 多个 commit 要如何操作。

上面的命令将 commit1 和 commit2 两个提交应用到当前分支。

上面的命令将 commit1 到 commit2 这个区间的 commit 都应用到当前分支(包含commit1、commit2),commit1 是最早的提交。

在 cherry-pick 多个commit时,可能会遇到代码冲突,这时 cherry-pick 会停下来,让用户决定如何继续操作。下面看看怎么解决这种场景。

还是 feature 分支,现在需要把 c、d、e 都**到 master 分支上。先把起点c和终点e的 commitHash 记下来。

切到 master 分支,使用区间的 cherry-pick 。可以看到 c 被成功**,当进行到 d 时,发现代码冲突, cherry-pick 中断了。这时需要解决代码冲突,重新提交到暂存区。

然后使用 cherry-pick --continue 让 cherry-pick 继续进行下去。最后 e 也被**进来,整个流程就完成了。

以上是完整的流程,但有时候可能需要在代码冲突后,放弃或者退出流程:

回到操作前的样子,就像什么都没发生过。

不回到操作前的样子。即保留已经 cherry-pick 成功的 commit,并退出 cherry-pick 流程。

给定一个或多个现有提交,恢复相关提交引入的更改,并记录一些这些更改的新提交。这就要求你的工作树是干净的(没有来自头部的修改)。

将现有的提交还原,恢复提交的内容,并生成一条还原记录。

应用场景:有一天测试突然跟你说,你开发上线的功能有问题,需要马上撤回,否则会影响到系统使用。这时可能会想到用 reset 回退,可是你看了看分支上最新的提交还有其他同事的代码,用 reset 会把这部分代码也撤回了。由于情况紧急,又想不到好方法,还是任性的使用 reset,然后再让同事把他的代码合一遍(同事听到想**),于是你的技术形象在同事眼里一落千丈。

revert 普通提交

学会 revert 之后,立马就可以拯救这种尴尬的情况。

现在 master 记录如下:

revert 掉自己提交的 commit。

因为 revert 会生成一条新的提交记录,这时会让你编辑提交信息,编辑完后 :wq 保存退出就好了。

再来看下最新的 log,生成了一条 revert 记录,虽然自己之前的提交记录还是会保留着,但你修改的代码内容已经被撤回了。

在 git 的 commit 记录里,还有一种类型是合并提交,想要 revert 合并提交,使用上会有些不一样。

现在的 master 分支里多了条合并提交。

使用刚刚同样的 revert 方法,会发现命令行报错了。为什么会这样?在官方文档中有解释。

通常无法 revert 合并,因为您不知道合并的哪一侧应被视为主线。此选项指定主线的父编号(从1开始),并允许 revert 反转相对于指定父编号的更改

我的理解是因为合并提交是两条分支的交集节点,而 git 不知道需要撤销的哪一条分支,需要添加参数 -m 指定主线分支,保留主线分支的代码,另一条则被撤销。

-m 后面要跟一个 parent number 标识出"主线",一般使用 1 保留主分支代码。

还是上面的场景,在 master 分支 revert 合并提交后,然后切到 feature 分支修复好 bug,再合并到 master 分支时,会发现之前被 revert 的修改内容没有重新合并进来。

因为使用 revert 后, feature 分支的 commit 还是会保留在 master 分支的记录中,当你再次合并进去时,git 判断有相同的 commitHash,就忽略了相关 commit 修改的内容。

这时就需要 revert 掉之前 revert 的合并提交,有点拗口,接下来看操作吧。

现在 master 的记录是这样的。

再次使用 revert,之前被 revert 的修改内容就又回来了。

此命令管理重录中记录的信息。

如果说 reset --soft 是后悔药,那 reflog 就是强力后悔药。它记录了所有的 commit 操作记录,便于错误操作后找回记录。

应用场景:某天你眼花,发现自己在其他人分支提交了代码还推到远程分支,这时因为分支只有你的最新提交,就想着使用 reset --hard ,结果紧张不小心记错了 commitHash,reset 过头,把同事的 commit 搞没了。没办法, reset --hard 是强制回退的,找不到 commitHash 了,只能让同事从本地分支再推一次(同事瞬间拳头就硬了,怎么又是你)。于是,你的技术形象又一落千丈。

分支记录如上,想要 reset 到 b。

误操作 reset 过头,b 没了,最新的只剩下 a。

这时用 git reflog 查看 历史 记录,把错误提交的那次 commitHash 记下。

再次 reset 回去,就会发现 b 回来了。

对我这种喜欢敲命令而不用图形化工具的爱好者来说,设置短命令可以很好的提高效率。下面介绍两种设置短命令的方式。

打开全局配置文件

写入内容

本文主要分享了5个在开发中实用的 Git 命令和设置短命令的方式。

文中列举的应用场景有部分不太恰当,只是想便于同学们理解,最重要的是要理解命令的作用是什么,活学活用才能发挥最大功效。

好啦,今天的分享就到这儿啦,我们下次见啦~

Git高级操作:reset,checkout,revert

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 命令容易混淆,但是当你考虑到他们分别在工作目录,暂存快照和提交历史上的可能产生的影响,就不难在开发中分辨出应该使用哪个命令。

原文地址:

git revert 和reset的区别

git revert 是生成一个新的提交来撤销某次提交,此次提交之前的commit都会被保留

git reset 是回到某次提交,提交及之前的commit都会被保留,但是此次之后的修改都会被退回到暂存区

具体一个例子,假设有三个commit, git st:

commit3: add test3.c

commit2: add test2.c

commit1: add test1.c

当执行git revert HEAD~1时, commit2被撤销了

git log可以看到:

revert "commit2":this reverts commit 5fe21s2...

commit3: add test3.c

commit2: add test2.c

commit1: add test1.c

git status 没有任何变化

如果换做执行git reset --soft(默认) HEAD~1后,运行git log

commit2: add test2.c

commit1: add test1.c

运行git status, 则test3.c处于暂存区,准备提交。

如果换做执行git reset --hard HEAD~1后,

显示:HEAD is now at commit2,运行git log

commit2: add test2.c

commit1: add test1.c

运行git st, 没有任何变化

另外:

git revert commit log string是撤消该commit,作为一个新的commit。

【学了就忘】Git后悔药 — 38.revert撤销(二)

上面的演示中,只有两个提交需要 revert ,我们可以一个个回退。但如果有几十个呢?一个个回退肯定效率太低而且容易出错。

(接上面示例)

我们可以使用以下方法进行批量回退:

命令: git revert commit6 commit5 commit4 …

示例:

说明:

我们应该先写 commit-6 ,在写 commit-5 。

我们可以看到,每撤销一个commit提交,都会生成一个新的提交。上面撤销了两个commit,就让你编写两次提交说明信息。

这时,错误的提交 commit-5 和 commit-6 依然保留,将来进行甩锅的时候也有依可循。而且,这样操作的话 HEAD 指针是往后移动的,可以直接使用 git push 命令推送到远程仓库里, 而这种做法,正是企业所鼓励的 。

命令: git revert commit新...commit旧

(这里就不做演示了,同上)

注意:

(1) -n 参数

作用: git revert 命令移除某几次的提交的修改,但是不要使用还原的更改创建任何提交,还原只是修改工作树和索引。简写 -n ,全称 --no-commit 。

命令: git revert -n commit新...commit旧

(2) -m 参数

作用: git revert 移除merge(合并)的修改内容。

简写: -m parent-number ,全称: --mainline parent-number 。

命令: git revert [-m parent-number] commit 。

说明:

如果我们需要还原的提交的是merge的操作,直接使用 git revert commit 的方式是不行的,会提示我们:

因为merge操作有两个分支,而revert不知道要还原哪个分支的提交,就没法进行还原\移除那些提交记录的修改的操作了,所以我们用 -m 1 来告诉 git revert 命令哪个是主线,哪个是非主线。(选择主线就还原非主线,选择非主线就还原主线)

另外,这个主线是1还是2是从哪里看出来的呢?

我们可以使用 git show 命令查看,如果是普通的commit提交,通常会显示这个commit的id、作者、日期、备注、更改文件内容等;如果是merge的记录,则会显示merge 的commit-id,备注、日期和merge的主线和合并过来的id。

例如:

如上第二行, Merge: bc64f61 72032b7 , bc64f61 就是主线的id,编号就是1; 72032b7 就是非主线的id,编号就是2。

此时,我们要把合并过来的分支的修改给还原掉,那么就可以指定1为主线,还原掉2的提交了。

通过以上对比可以发现, git reset 命令与 git revert 命令最大的差别就在于, git reset 命令会失去后面的提交,而 git revert 命令是通过反做的方式重新创建一个新的提交,而保留原有的提交。在企业里,应尽量使用 git revert 命令,能不用 git reset 命令尽量不用。

标签: revertcommit

“包含revertcommit的词条” 的相关文章

revertcommit的简单介绍

revertcommit的简单介绍

Git撤销与合并 1. git init 创建一个空的git repo,也就是创建一个.git的子目录,这个目录包含了几乎所有git存储和操作的东西。新初始化的.git目录的典型结构如下:...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。