git 还原到本地初始状态_如何在Git中重置,还原和返回以前的状态

git 还原到本地初始状态

与Git一起使用时,鲜为人知的方面之一就是回到原先的位置很容易,也就是说,即使撤消存储库中的重大更改也很容易。 在本文中,我们将快速查看如何重置,还原以及完全返回到以前的状态,所有这些都具有单个Git命令的简单性和优雅性。

重启

让我们从Git命令reset 。 实际上,您可以将其视为“回滚”,它会将您的本地环境指向上一次提交。 “本地环境”是指您的本地存储库,暂存区域和工作目录。

看一下图1。这里我们展示了Git中的一系列提交。 Git中的分支只是一个指向特定提交的命名可移动指针。 在这种情况下,我们的分支主机是指向链中最新提交的指针。

Local Git environment with repository, staging area, and working directory

图1:具有存储库,暂存区和工作目录的本地Git环境

如果我们现在查看master分支中的内容,那么可以看到到目前为止所做的提交链。


   
   
$ git log --oneline
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line
reset命令为我们做到这一点。 例如,如果我们想将master重置为指向当前提交两次返回的提交,则可以使用以下方法之一:

$ git reset 9ef9173 (使用绝对提交SHA1值9ef9173)

要么

$ git reset current~2 (在“当前”标签之前使用相对值-2)

图2显示了此操作的结果。 此后,如果我们在当前分支( master )上执行git log命令,则只会看到一个提交。


   
   
$ git log --oneline
9ef9173 File with one line
After reset

图2: reset

git reset命令还包括一些选项,这些选项可以使用最终的提交内容来更新本地环境的其他部分。 这些选项包括: hard重置存储库中指向的提交,使用提交的内容填充工作目录,以及重置登台区域; soft ,仅重置存储库中的指针; 并mixed (默认)以重置指针和临时区域。

在目标情况下,例如git reset --hard <commit sha1 | reference>使用这些选项可能很有用。 git reset --hard <commit sha1 | reference> . 这将覆盖您尚未提交的所有本地更改。 实际上,它会重置(清除)暂存区域,并使用您重置为提交的内容覆盖工作目录中的内容。 在使用hard选项之前,请确保这是您真正想要做的,因为该命令会覆盖所有未提交的更改。

还原

git revert命令的最终效果类似于reset,但其方法不同。 在reset命令将分支指针移回链中(通常)以“撤消”更改的情况下, revert命令在链末尾添加新的提交以“取消”更改。 再次查看图1,最容易看出效果。 如果我们在链中的每个提交中向文件添加一行,则仅返回两行即可返回该版本的一种方法是重置为该提交,即git reset HEAD~1

结束于两行版本的另一种方法是添加一个删除了第三行的新提交,从而有效地取消了该更改。 这可以通过git revert命令完成,例如:

 $ git revert HEAD 

因为这会添加一个新的提交,所以Git将提示您输入提交消息:


   
   
Revert "File with three lines"

This reverts commit b764644bad524b804577684bf74e7bca3117f554.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#       modified:   file1.txt
#

图3(下图)显示了revert操作完成后的结果。

如果现在执行git log ,我们将看到一个新的提交,它反映了上一次提交之前的内容。


   
   
$ git log --oneline
11b7712 Revert "File with three lines"
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line

以下是工作目录中文件的当前内容:


   
   
$ cat <filename>
Line 1
Line 2

还原还是重置?

您为什么选择通过reset操作进行revert ? 如果您已经将提交链推送到远程存储库(其他人可能已经在其中提交了代码并开始使用它),那么还原是一种取消它们的更改的更好方法。 这是因为Git工作流程非常适合在分支的末尾拾取其他提交,但是当有人重置分支指针时,如果在链中不再看到一组提交,则可能会有挑战。

当以这种方式使用Git时,这使我们遵循了一条基本规则:在本地存储库中进行此类更改以编写尚未推送的代码就可以了。 但是,如果提交已被推送到远程存储库,并且其他人可能正在使用它们,则请避免进行更改以重写历史记录的更改。

简而言之,如果您回滚,撤消或重写其他人正在使用的提交链的历史记录,则当您的同事尝试根据他们拉出的原始链合并更改时,他们可能需要做更多的工作。 如果必须对已经推送的代码和他人正在使用的代码进行更改,请在进行更改之前考虑进行交流,并让人们有机会首先合并他们的更改。 然后,他们可以在侵权操作之后提取新副本,而无需合并。

您可能已经注意到,在进行重置后,原始的提交链仍然存在。 我们移动了指针,并将代码重置为上一次提交,但是它没有删除任何提交。 这意味着,只要我们知道所指向的原始提交,就可以通过简单地重置为分支的原始头来“恢复”到先前的点:

 git reset <sha1 of commit> 

当替换提交时,我们在Git中执行的大多数其他操作中也会发生类似的情况。 创建新的提交,并将适当的指针移至新链。 但是旧的提交链仍然存在。

变基

现在,让我们来看一个分支的基础。 考虑我们有两个branches- 主站特征 -附下面的图4中所示的提交的链。 链具有链C4->C2->C1->C0功能链具有C5->C3->C2->C1->C0

Chain of commits for branches master and feature

图4:分支母版要素的提交链

如果我们查看分支中的提交日志,它们可能如下所示。 (使用提交消息的C指示符可以使此操作更容易理解。)


   
   
$ git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0

$ git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0

我告诉人们,在Git中将重新构建视为“与历史的融合”。 本质上,Git所做的是将一个分支中的每个不同提交提交并尝试将差异“重播”到另一个分支上。

因此,我们可以将要素重新建立到主要素上,以提取C4 (例如,将其插入要素链中)。 使用基本的Git命令,它看起来可能像这样:


   
   
$ git checkout feature
$ git rebase master

First, rewinding head to replay your work on top of it...
Applying: C3
Applying: C5

之后,我们的提交链将如图5所示。

Chain of commits after the rebase command

图5: rebase命令后的提交链

同样,查看提交日志,我们可以看到更改。


   
   
$ git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0

$ git log --oneline feature
c4533a5 C5
64f2047 C3
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0

请注意,我们有C3'C5' -新提交的‘之上’,在掌握现有链使得从原稿的变化而创建的。 但也请注意,“原始” C3C5仍然存在-它们不再具有指向它们的分支。

如果我们进行了这种变基,那么就决定我们不喜欢结果并想要撤消它,它就像下面这样简单:

 $ git reset 79768b8 

通过这一简单的更改,我们的分支现在将指向与rebase操作之前相同的提交集-有效地撤消了该提交(图6)。

After undoing rebase

图6:撤消rebase操作后

如果您不记得操作前提交的分支指向什么,该怎么办? 幸运的是,Git再次帮助了我们。 对于大多数以此方式修改指针的操作,Git都会为您记住原始的提交。 实际上,它将其存储在.git存储库目录中名为ORIG_HEAD的特殊引用中。 该路径是一个文件,其中包含修改前的最新参考。 如果我们cat的文件中,我们可以看到它的内容。


   
   
$ cat .git/ORIG_HEAD
79768b891f47ce06f13456a7e222536ee47ad2fe

我们可以像以前一样使用reset命令来指向原始链。 然后日志将显示以下内容:


   
   
$ git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0

获取此信息的另一个地方是reflog。 reflog是按播放列表,列出了本地存储库中的开关或对引用的更改。 要查看它,可以使用git reflog命令:


   
   
$ git reflog
79768b8 HEAD@{0}: reset: moving to 79768b
c4533a5 HEAD@{1}: rebase finished: returning to refs/heads/feature
c4533a5 HEAD@{2}: rebase: C5
64f2047 HEAD@{3}: rebase: C3
6a92e7a HEAD@{4}: rebase: checkout master
79768b8 HEAD@{5}: checkout: moving from feature to feature
79768b8 HEAD@{6}: commit: C5
000f9ae HEAD@{7}: checkout: moving from master to feature
6a92e7a HEAD@{8}: commit: C4
259bf36 HEAD@{9}: checkout: moving from feature to master
000f9ae HEAD@{10}: commit: C3
259bf36 HEAD@{11}: checkout: moving from master to feature
259bf36 HEAD@{12}: commit: C2
f33ae68 HEAD@{13}: commit: C1
5043e79 HEAD@{14}: commit (initial): C0

然后,您可以使用在日志中看到的特殊相对命名格式,重置为该列表中的任何项目:

 $ git reset HEAD@{1} 

一旦您了解到Git会在操作“修改”链时保持原始的提交链,那么在Git中进行更改的恐惧就会大大减少。 这是Git的核心优势之一:能够快速轻松地尝试并在不起作用的情况下撤消它们。


Brent Laster将于7月16日至19日在俄勒冈州波特兰举行的第20届年度OSCON活动中展示Power Git:Rerere,Bisect,子树,Filter分支,工作树,子模块等 。有关在任何级别使用Git的更多提示和解释,结帐Brent的书“ Professional Git ”,可在亚马逊上找到。

翻译自: https://opensource.com/article/18/6/git-reset-revert-rebase-commands

git 还原到本地初始状态

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值