Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
git如何在不接触索引文件的情况下重置--软重置上次提交?_Git_Git Reset_Git Add - Fatal编程技术网

git如何在不接触索引文件的情况下重置--软重置上次提交?

git如何在不接触索引文件的情况下重置--软重置上次提交?,git,git-reset,git-add,Git,Git Reset,Git Add,这可能是一个很难回答的问题 假设我有一个Git repo,它已经使用Git add在staged区域中拥有一些文件。然后我做了一个git重置--soft@~ 我很高兴看到我上次提交的一些文件现在被放进了暂存区 但是怎么做呢?我检查.git文件夹。唯一更改的是当前分支的ref。还有一个我认为不相关的“始祖”。最可疑的索引文件根本不被触及。还有谁能告诉我如何查看它的内容 那么git怎么能做到这一点呢?谢谢。以最简单的形式,1git reset有两个功能: 移动当前分支,和/或 撤消索引中的内容

这可能是一个很难回答的问题

假设我有一个Git repo,它已经使用Git add在staged区域中拥有一些文件。然后我做了一个git重置--soft@~

我很高兴看到我上次提交的一些文件现在被放进了暂存区

但是怎么做呢?我检查
.git
文件夹。唯一更改的是当前分支的ref。还有一个我认为不相关的“始祖”。最可疑的索引文件根本不被触及。还有谁能告诉我如何查看它的内容

那么git怎么能做到这一点呢?谢谢。

以最简单的形式,1
git reset
有两个功能:

  • 移动当前分支,和/或
  • 撤消索引中的内容
要理解它是如何工作的、为什么工作的以及它是做什么的,您需要知道提交是如何工作的以及索引是如何工作的,至少在相对较高的层次上是这样。无论如何,这些都是紧密联系在一起的

提交、树和blob 首先,提交只是一个类型为“提交”的存储库对象,它的数据包括提交消息和一些其他信息(树、父级、作者和提交者):

这些
blob
条目是构成git源的所有文件(以及每个
树的子目录;它们有更多的
blob
s)。每个
blob
都有一个基于文件内容的唯一SHA-1 ID。
保存了文件的“模式”(实际上只是它的
x
位,这些模式都是
100644
100755
)和文件名以及存储库中blob对象的SHA-1名。(其他模式,如上文所示的
040000
,跟踪子树、符号链接和子模块。仅限于
100644
100755
的blob)

每个git存储库对象都是只读的。ID为
5f95c9f…
的提交将永远不会更改。它将始终将ID
972825c…
作为其(单个)
树。ID为
536e555…
的文件始终是文件
复制的特定版本。如果文件被更新,则会出现一个新的、不同的blob,其中包含新的、不同的SHA-1

索引 Git的“索引”(也称为“暂存区”,有时称为“缓存”)是一个文档记录不完整的文件,本质上表示“下一次提交时会发生什么”

与存储库对象不同,索引是完全可写的。为了使“下一次提交”有所不同,git从索引中添加或删除条目。例如,要更新名为
COPYING
的文件,您需要在编辑后运行
git add COPYING
。这将获取文件的新内容
复制
,并将其复制到存储库中(它们最终将永远存在),2计算结果的SHA-1“真实名称”。然后,这个新的SHA-1进入索引(以及模式和名称
复制
——基本上是提交所需的一切)

作出承诺 因为索引已经像这样准备好了一切,所以很容易进行新的提交。存储库中已存在所有正确的
blob
s。Git只需将索引转换为一些
对象,将它们写入存储库,获得最新顶级
的最终SHA-1,然后编写一个新的
提交
对象。新提交将具有以下属性:

  • 树是根据索引写入的内容
  • parent
    现在是
    HEAD
    中的任何内容(在进行合并提交时,或多或少会有一些与多个父项的关系)
  • author
    committer
    以及这些日期取自当前时间和您的git配置
    user.name
    user.email
    ,或者取自参数(
    --author
    )或环境变量(如果这些参数被设置为覆盖)
  • 该消息是您作为提交消息编辑的内容,或作为
    -m
    参数给出的内容
所以git编写了提交,它生成了一个新的、唯一的SHA-1。然后它写到SHA-1本身的某个地方

分支机构和
HEAD
如果您是“在分支
master
”,正如
git status
所说,这意味着文件
.git/HEAD
包含文本字符串
ref:refs/heads/master
。这就是git所称的“间接引用”:一个只说“找到另一个引用,这是名称”的引用。通常你在某个分支上,
HEAD
是对该分支的间接引用

分支本身可以以几种不同的方式存储,但最简单的是
.git
中的另一个文件,在本例中是
.git/refs/heads/master
。如果该文件存在并且您读取了它,它将包含一个类似于SHA-1的
5F95C9F850B19B368C43AE39CC831B17A26A5AC
。这就是当前的提交,也是git知道您“在”哪个提交的方式,就像git知道您在分支
master
上的
ref:refs/heads/master
一样

为了进行新的提交,git如上所述编写提交,从而生成一个新的唯一SHA-1。然后,由于您在分支
master
,git只需将新的提交ID写入
.git/refs/heads/master
,现在您就进入了新提交,这是分支
master
的提示

你也可以有一个“超脱的头”,尽管听起来像法国大革命时期的东西,但这意味着
HEAD
不是一个间接的参照物。相反,
HEAD
包含一个原始SHA-1。在本例中,为了进行新的提交,git以与以前相同的方式进行提交,但它没有更新
.git/refs/heads/master
,而是将新的提交ID直接写入
HEAD$ git cat-file -p 5f95c9f850b19b368c43ae399cc831b17a26a5ac
tree 972825cf23ba10bc49e81289f628e06ad44044ff
parent 9c8ce7397bac108f83d77dfd96786edb28937511
author Junio C Hamano <gitster@pobox.com> 1392406504 -0800
committer Junio C Hamano <gitster@pobox.com> 1392406504 -0800

Git 1.9.0

Signed-off-by: Junio C Hamano <gitster@pobox.com>
100644 blob 5e98806c6cc246acef5f539ae191710a0c06ad3f    .gitattributes
100644 blob b5f9defed37c43b2c6075d7065c8cbae2b1797e1    .gitignore
100644 blob 11057cbcdf4c9f814189bdbf0a17980825da194c    .mailmap
100644 blob 536e55524db72bd2acf175208aef4f3dfc148d42    COPYING
040000 tree 47fca99809b19aeac94aed024d64e6e6d759207d    Documentation
100755 blob 2b97352dd3b113b46bbd53248315ab91f0a9356b    GIT-VERSION-GEN
git reset --soft @~   # @~ means @~1, which means HEAD~1, aka HEAD^
$ git rev-parse @~
9c8ce7397bac108f83d77dfd96786edb28937511
$ git reset --mixed HEAD -- COPYING
A <- B <- C   <-- HEAD=master
$ git reset --hard HEAD^
A - B - D   <-- HEAD=master
      \
        C   [abandoned]