回滚提交单个文件git reset

时间:2017-05-31 00:45:36

标签: git

我在终端上使用git。我在文件夹中有很少的HTML文件。我使用git init创建了一个存储库。

我使用以下方法将index.html添加到暂存区域:

git add index.html

现在,我想从暂存区域中删除index.html。我尝试了git reset --HEAD index.html等,但似乎没有任何东西将文件从暂存区域中取出。

我想简单地从暂存区域中删除index.html文件。

这是运行git reset HEAD后的输出。如您所见,缺少index.html。

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    landscape.css
    max-640px.css
    min-640px.css
    portrait.css
    result.html
    styles.css

这是git log输出:

$ git log
commit d70e697ed08fbe6709ba3f13d202bade793e7b1a
Author: johnson 
Date:   Tue May 30 19:36:12 2017 -0500

1 个答案:

答案 0 :(得分:1)

在我开始之前,请注意第一次提交是特殊的。原因是,在您进行第一次提交之前,没有当前提交。对于Git自己的内部目的,Git有时会假装当前提交 仍然存在,并且它确实是空的:它根本没有文件。 (In fact, there's a special semi-secret Git thing in every repository, for just such purposes.

暂存区 1 位于 当前提交(HEAD)和工作树之间

current commit:        staging area:         work-tree:
  file1                  file1                 file1
  file2                  file2                 file2
   ...                    ...                   ...
  fileN                  fileN                 fileN

暂存区域(始终)保存所有将进入 next 提交的文件。如果你有一个当前的提交 - 你做了/做了;你在上面显示 - 暂存区域开始充满该提交中的所有文件。 (工作树也是如此:正如您所看到的,每个文件都有三个副本!通常其中两个 - 当前提交和暂存区域副本 - 被秘密压缩和/或秘密共享。 Git可以执行此操作,因为这两个副本都在Git的控制下。它只是工作树副本,具有您计算机上任何文件的正常形式; Git可以&# 39;将它们保存在花哨,压缩,重复的形式中。)

换句话说,只要您有当前HEAD@)提交,就可以保证暂存区域加载了大量文件。它只是存储在那里的文件与当前提交中存储的文件相同!因此git status比较HEAD - vs-stage,对它们一无所知。

(注意:git status然后将暂存区域与工作树进行比较。我们将在下面看到一个示例,其中git status --short打印两个问号表示未跟踪的文件。这是因为该文件将在工作树中,但不在 当前提交临时区域。)

当您运行git reset --mixed commit path(并且--mixed是默认值)时, 2 会告诉Git:请制作 {{的分阶段副本1}} 匹配 path 副本。由于这是commit,这意味着:如果文件不是<\ n> / {>在git reset HEAD index.html提交中,将其从暂存区域中删除;如果HEAD提交中 ,则将其从HEAD提交复制回到暂存区域。

由于HEAD提交中的index.html ,您仍然坚持 永久提交 < / em>的。但是您在暂存区域内没有坚持使用它:您可以使用HEAD删除它。当然,git rm index.html也会将它从您的工作树中删除!幸运的是,可以选择告诉git rm index.html从暂存区域删除它,但不要触摸工作树。拼写为git rm

--cached

现在暂存区没有git rm --cached index.html 的副本:

index.html

这不是你所做的 - 使用current commit: staging area: work-tree: foo.css foo.css foo.css index.html --- index.html README README README 进行新的提交撤消之前的提交 - 但这里仍然是重​​要的一点,那就是如果已经完成此操作,请申请。 git revert命令将git status提交与暂存区域进行比较。 HEAD提交中的文件index.html (或者在恢复之前)。在HEAD之后,暂存区域中的不是。因此该文件变为git rm --cached

1 仅仅因为它的Git,临时区域还有两个名字:它也被称为缓存,最常见的是索引。当然,名称​​ index deleted容易混淆。 :-)所以对于这个答案的其余部分,我试着坚持使用短语 staging area

2 原因是index.html--mixedgit reset的程度较低,不会触及临时区域。还有一个更高的学位--soft,它在临时区域工作树上写入。

当您还原时,您进行了新的提交

如果您使用--hard来&#34;撤消&#34;一个提交,它只是创建一个与恢复的提交相反的新提交。您还原的提交是首次提交,根据定义,第一次提交包含添加该提交中的所有文件。因此,恢复第一个提交意味着:删除所有文件

Git的提交实际上并不存储更改,而是快照。现在您有两次提交,git revert(或当前)提交是第二次提交,与第一次提交相比 - 删除所有文件:

HEAD

到目前为止,非常好:我们有一个初始提交,(与初始提交之前的虚无相比)添加了所有文件。

$ mkdir tt
$ cd tt
$ git init
Initialized empty Git repository in ...
$ echo test revert of first commit > README
$ echo la la la > file
$ git add README file
$ git commit -m initial
[master (root-commit) 2cff9aa] initial
 2 files changed, 2 insertions(+)
 create mode 100644 README
 create mode 100644 file

恢复撤消了初始提交的效果,因此删除所有文件。 Git比较&#34;之前的提交&#34;到&#34;当前提交&#34;并看到$ git revert HEAD [editor session, snipped] [master 92f4eea] Revert "initial" 2 files changed, 2 deletions(-) delete mode 100644 README delete mode 100644 file README被删除。

file

工作树现在为空。所有文件都不见了!这是因为我们还原了

不过不用担心!所有的文件都还在那里!他们是第一次提交。我们只需要让他们回来。我们现在就这样做:

$ ls
$ 

(这里只有$ git log --all --decorate --oneline --graph * 92f4eea (HEAD -> master) Revert "initial" * 2cff9aa initial 选项做了很多,但其余的通常都是个好主意。我实际上将它作为Git别名。记住这个:使用--oneline时,得到来自A DOG的帮助:All Decorate Oneline Graph 。)

我们需要从第一次提交(git log)回来的所有文件,所以:

2cff9aa

美中不足:两个文件现在在暂存区,因此将进入下一个 commit:

$ git checkout 2cff9aa -- .
$ ls
README  file

(这是因为$ git status git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: README new file: file 将文件从指定的提交复制到暂存区域,然后再从 >暂存区工作树。)

我们希望摆脱其中一个(在这种情况下为git checkout)。 现在我们可以使用 <{em> file git rm --cached。名为git reset HEAD fileHEAD@当前提交中包含文件92f4eea。实际上,当前提交中包含 no files !它是一个真正的空提交:检查它会使你的工作树变空。

现在重置(或file):

rm --cached

$ git reset file $ git status --short A README ?? file $ ls README file 状态表示&#34;已添加&#34;,两个问号表示文件A未跟踪(我们在更长的默认值中明确说明了这一点file输出)。所以现在我们可以提交:

git status

现在这里有点问题,也许最好通过插图来说明。请注意,我们现在在工作树中安全地拥有文件$ git commit -m 'this should have been the first commit' [master 0945e1d] this should have been the first commit 1 file changed, 1 insertion(+) create mode 100644 README $ git log --oneline 0945e1d (HEAD -> master) this should have been the first commit 92f4eea Revert "initial" 2cff9aa initial 。让我们再次查看初始提交,看看其中包含的内容:

file

假设我们设法检查了提交,例如,使用$ git checkout 2cff9aa error: The following untracked working tree files would be overwritten by checkout: file Please move or remove them before you switch branches. Aborting

--force

现在让我们回到$ git checkout --force 2cff9aa Note: checking out '2cff9aa'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at 2cff9aa... initial $ ls README file 的提示提交,回到分支master并退出这个&#34;分离的HEAD&#34;模式。

master

等等,我们的文件名为$ git checkout master Previous HEAD position was 2cff9aa... initial Switched to branch 'master' $ ls README 在哪里?

这是我们创建的陷阱:有一个提交,file,其中包含已提交的文件。如果我们以某种方式设法使当前提交,我们在暂存区域和工作树中也会有2cff9aa的版本。然后,当我们离开那个提交时 - 回到file - Git将删除文件,这两个文件都来自工作树的暂存区域

没有办法解决这个问题。如果提交中的文件 ,那么 将在您签出时进入暂存区域(和工作树)。当您将该提交移至拥有该文件的提交时,它将被删除(来自这两个相同的地方)。

正如我们上面所见,Git会在您将移动到提交时警告您。这使您有机会保存数据。您需要知道必须这样做(保存数据),或者避免检查特定的提交。

唯一的另一个选择是重写您的存储库以完全摆脱该提交。在大多数情况下 - 大多数存储库,其中有很多历史记录,也许还有许多克隆等等 - 这不值得。在只有一次提交的 new 存储库中,它可能是值得的!