git reset的用法是什么

49次阅读
没有评论

共计 4540 个字符,预计需要花费 12 分钟才能阅读完成。

这篇文章主要讲解了“git reset 的用法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“git reset 的用法是什么”吧!

一、可以将 git 简单的分为三个区域  
  1、工作区(working directory) 
  2、暂缓区(stage index) 
  3、历史记录区(history) 

  其中 git add files 把当前工作目录中的文件放入暂存区域,这其实做了两件事: 

  1、将本地文件的时间戳、长度,当前文档对象的 id 等信息保存到一个树形目录中去(index,即平时说的暂存区) 
  2、将本地文件的内容做快照并保存到 Git 的对象库  。
   

        综上 2 点来说,暂存区实际上就是一个包含文件索引的目录树,像是一个虚拟的工作区。在这个虚拟工作区的目录树中,记录了文件名、文件的状态信息(时间戳、文件长度等),文件的内容并不存储其中,而是保存在 Git 对象库(.git/objects)中,文件索引建立了文件和对象库中对象实体之间的对应。 
    我们可以看到部分 Git 命令是如何影响工作区和暂存区(stage, index)的: 

    左侧为工作区,右侧为版本库。在版本库中标记为 index 的区域是暂存区(stage, index),标记为 master 的是 master 分支所代表的目录树。 
    我们可以看出此时 HEAD 实际是指向 master 分支的一个“游标”。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。 
 objects 标识的区域为 Git 的对象库,实际位于 .git/objects 目录下  
  当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的 ID 被记录在暂存区的文件索引中
  当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树  。

    当执行 git status 命令扫描工作区改动的时候,先依据 .git/index 文件中记录的(工作区跟踪文件的)时间戳、长度等信息判断工作区文件是否改变。如果工作区的文件时间戳改变,说明文件的内容可能被改变了,需要打开文件,读取文件内容,和更改前的原始文件相比较(本地文件和与之对应的 object 库中的文件的内容进行对比),判断文件内容是否被更改。如果文件内容没有改变,则将该文件新的时间戳记录到 .git/index 文件中。因为判断文件是否更改,使用时间戳、文件长度等信息进行比较要比通过文件内容比较要快的多,所以 Git 这样的实现方式可以让工作区状态扫描更快速的执行,这也是 Git 高效的因素之一。 

     git diff files 用来进行具体文件的变动对比,通常用来进行工作区与暂存区之间的对比,实质上是用 git objects 库中的快照与工作区文件的内容的对比。 

另外,Git 中提供了几个相关的撤销操作的命令,如 git reset、git revert、git checkout,这几者之间的用法各有不同。

二、git reset 的用法

从上图可知:git reset — files 用来撤销最后一次的 git add files(因为每 git add file 一次,暂存区的文件都会被更改一次),你也可以用 git reset 撤销所有暂存区域文件。 

另外:

  一、git reset 的用法:git reset + commit 号

1、git reset 命令后面需要加 2 种参数:–hard 和 –soft,如果不加,默认情况下是 –soft。

2、–soft 表示该条 commit 号之后(时间作为参考点)的所有 commit 的修改都会退回到 git 缓冲区中。所以使用 git status 命令可以在缓冲区中看到这些修改。

3、–hard 则表示缓冲区中不会存储这些修改,git 会直接丢弃这部分内容,但需要注意的一个问题是:这样的重置是直接在本地的修改,无法提交到远程服务器,如果直接丢弃的内容已经被推到远程服务器上了,则会造成本地和服务器无法同步的问题,即 git reset –hard 只能针对本地操作,不能针对远程服务器进行同样操作。如果从本地删掉的内容没有推到服务器上,则不会有副作用,如果被推到服务器,则下次本地和服务器进行同步时,这

部分删掉的内容仍然会回来。

(其实这个问题则可以很好的被 git revert 命令解决,使用 git revert + commit 号,该命令撤销对某个 commit 的提交,这一撤销动作会作为一个新的修改存储起来,这样,当你和服务器同步时,就不会产生什么副作用。)

其实在 merge 的时候,也有可能会用到 git reset.

如果我们当前使用 git pull 的时候,可能会出现 merge 冲突,在冲突状态下,需要解决冲突的文件会从 index 暂存区打回到工作区。

如果有冲突的时候,一般用如下步骤解决冲突:

1、用工具或者手工解决冲突  

2、git add 命令来表明冲突已经解决。 

3、再次 commit 已解决冲突的文件。

这当中,可以使用 git reset –hard ORIG_HEAD 用来撤销已经 commit 的 merge. 

使用 git reset –hard HEAD 用来撤销还没 commit 的 merge, 其实原理就是放弃 index 和工作区的改动。

也可以使用 git reset –merge ORIG_HEAD,注意其中的 –hard 换成了 –merge,这样就可以避免在回滚时清除 working tree。

三、git checkout 的用法

        从上图可知,git checkout — files 把文件从暂存区域复制到工作目录,用来丢弃本地修改。需要另外注意的是:

       1、当执行 git rm –cached file 命令时,会直接从暂存区删除文件,工作区则不做出改变。
       2、当执行 git checkout . 或者 git checkout — file 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动  

       3、当执行 git checkout HEAD . 或者 git checkout HEAD file 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动  。

四、git revert 的用法

        git revert 也是撤销命令,区别在于 reset 是指向原地或者向前移动指针,git revert 是创建一个 commit 来覆盖当前的 commit,指针向后移动。

  那么两者的具体区别有:

1)git revert 是撤销某次操作,此次操作之前的 commit 都会被保留,而 git reset 是撤销某次提交,但是此次之后的修改都会被退回到暂存区中。

具体一个例子,假设有三个 commit(commit1,commit2,commit3),使用 git status:

commit3: add test3.c

commit2: add test2.c

commit1: add test1.c

当执行 git revert HEAD~1 时(撤销倒数第二个操作),第二个操作即 commit2 这个操作被撤销了,使用 git log 可以看到:

commit1:add test1.c

commit3:add test3.c

由于 git revert 不会回退到暂存区中,所以使用 git status 没有任何变化

如果换做执行 git reset –soft(默认) HEAD~1 后,运行 git log 可以看到

commit2: add test2.c

commit1: add test1.c

运行 git status,可以看到 test3.c 处于暂存区了,准备提交。

但如果换做执行 git revert 后,

显示:HEAD is now at commit2,运行 git log 可以看到

commit2: add test2.c

commit1: add test1.c

运行 git status,则没有任何变化

所以,git revert 与 git reset 最大的不同是,git revert 仅仅是撤销某次提交,而 git reset 会将撤销点之后的操作

都回退到暂存区中。

1、git revert 是用一次新的 commit 来回滚之前的 commit,git reset 是直接删除指定的 commit。 

2、在回滚这一操作上看,效果差不多。但是在日后继续 merge 以前的老版本时有区别。

因为 git revert 是用一次逆向的 commit“中和”之前的提交,因此日后合并老的 branch 时,导致这部分改变不会再次出现,但是 git reset 是之间把某些 commit 在某个 branch 上删除,因而和老的 branch 再次 merge 时,这些被回滚的 commit 应该还会被引入。 

3、git reset 是把 HEAD 向后移动了一下,而 git revert 是 HEAD 继续前进,只是新的 commit 的内容和要 revert 的内容正好相反,能够抵消要被 revert 的内容。

六、不得不提的 git 的其它删除命令(类似于 Linux 的命令):

git rm –cached readme.txt 只从缓存区中删除 readme.txt,保留物理文件

git rm readme.txt 不但从缓存区中删除,同时删除物理文件

git mv a.txt b.txt 把 a.txt 改名为 b.txt

综上所以我们有时如果是想撤销对单个文件的更改:

–、如果已经用 add 命令把文件加入 stage 暂存区了:

1、就先需要从 stage 暂存区中撤销:

git reset HEAD file …  

2、然后再从工作区撤销,即将暂存区的文件替换工作区当前的文件

git checkout — file … to discard changes in working directory

如:git checkout a.txt   撤销 a.txt 的变动(工作区上的文件) 

如果是多个文件:git chenkout .

二、如果已经 commit 了,则需要  

1、使用 git commit –amend 来进行修改,这个只能修改最近一次的, 也就是用一个新的提交来覆盖上一次的提交。因此如果 push 以后再做这个动作就会有危险。

2、git reset –hard HEAD 放弃工作区和 index 的改动,HEAD 指针仍然指向当前的 commit.(参照第一幅图)

这条命令同时还可以用来撤销还没 commit 的 merge, 其实原理就是放弃 index 暂存区和工作区的改动,因为没 commit 的改动只存在于 index 暂存区和工作区中。

而 git reset –hard HEAD^ 用来撤销已经 commit 的内容 (等价于 git reset –hard HEAD~1)。原理就是放弃工作区和 index 的改动,同时 HEAD 指针指向前一个 commit 对象。

感谢各位的阅读,以上就是“git reset 的用法是什么”的内容了,经过本文的学习后,相信大家对 git reset 的用法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计4540字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)