How to unstage all files since branching

时间:2018-09-18 20:18:06

标签: git

Lets say I branch off master and make a branch called xo-wip, make 30 commits and stage all the files/changes. Now I want to unstage every single edit I did in the xo-wip branch but not get rid of it. How would I do that?

Currently I have to make a new branch off master say xo-wip-release, and then git merge --squash xo-wip into xo-wip-release

1 个答案:

答案 0 :(得分:0)

TL; DR

要暂存文件,请使用git add。要取消暂存文件,请使用git reset。但是,直到您正确了解Git的 index ,这一切都无济于事。

这个问题似乎没有任何意义,这使我相信您可能对Git的索引有错误的认识。索引,也称为暂存区或有时称为 cache ,是一种有点隐蔽的数据结构,对于使用Git来说至关重要,但是对于许多Git来说解释不力文档,甚至是一些Git书籍。

Git提交和Git的工作树

您可能已经很熟悉提交和Git关于工作树的想法,但是让我们再次简要地回顾一下它们。 Git中的 commit 包含整个源代码(或您要进行版本控制的任何内容)的完整快照。每个提交都通过其哈希ID 进行唯一标识,这很丑陋:git log打印提交ID,运行git log时,您可能会看到,例如:

commit c05048d43925ab8edcb36663752c2b4541911231
Author: Junio C Hamano ...

除了保存源快照外,每个提交还保存上一个或提交的哈希ID。 Git使用这些链接以反向方式将提交链接在一起,从 last 提交开始并向后工作。像masterxo-wip这样的分支名称只是保留了该分支中 last 提交的哈希ID。如果我们使用大写字母来表示较大的丑陋哈希ID,则可以得出这种情况:

          I   <-- master
         /
...--G--H
         \
          J--K--L   <-- xo-wip

此处,名称master标识提交I,名称xo-wip标识提交L。从L开始,Git向后依次到K,然后依次到JH。从I开始,Git向后退回到H。 (因此,哪个分支是提交HH之前的任何东西,例如G,在吗?在Git中,它们同时在两个分支上。与大多数其他版本控制系统相比,这是使Git彻底变得奇怪的几件事之一。)

由于每个提交都拥有每个文件的完整快照,因此您可能想知道Git如何避免用完所有磁盘空间。答案是,在 提交中存储的文件以特殊的,压缩的,仅Git的格式存储。而且,一旦存储在Git中,文件的每个版本都会被冻结(只读,永久保存),因此共享文件的相同版本的每次提交都可以重新使用压缩的,仅Git的冻结文件。

工作树只是Git将这些文件扩展为正常的日常形式的地方。这使您可以对它们进行操作,因此命名为“工作树”或“工作树”。 git checkout选择一个提交-您说您想要的哪个提交,Git将该提交提取到您的工作树中。那么该提交就是您的当前提交。当前提交具有​​特殊名称@HEAD。通常,Git将单词HEAD附加到分支名称,然后@是分支名称指向的提交:

          I   <-- master
         /
...--G--H
         \
          J--K--L   <-- xo-wip (HEAD)

当前提交-HEAD@-现在是提交L

您还可以将没有存储在Git中的文件放入工作树中。这些文件是未跟踪的,如果文件未跟踪,Git通常会抱怨该文件,因此您可以将特定的未跟踪文件标记为忽略。 (您不能忽略跟踪的文件,只能忽略未跟踪的文件。)

索引,也就是暂存区域

上面的文字图片(和提交的字面图片)不包含称为索引或暂存区的任何内容。这是因为Git的索引至少在很大程度上是不可见的-您不能直接查看它。 1 实际上,一旦知道索引是什么,您就可以想知道为什么Git有一个。其他版本控制系统无处可逃。不过,Git拥有它,并且(如果有任何意义)将其隐喻地推到您的脸上,同时将其隐藏起来。 :-)您必须使用它。

关于索引的最简单的解释是,它是您构建下一个提交的地方。它位于当前提交和工作树之间。它保存当前提交的每个文件 的副本,格式与Git在提交内部使用的特殊,仅Git的压缩格式相同。至关重要的是,与冻结的提交版本不同,文件的索引副本是可写


1 您实际上可以使用git ls-files --stage直接查看索引。但是,这在许多存储库中是不切实际的,因为它会找到每个文件 ,这不是我们关心的。


因此,当您git checkout mastergit checkout xo-lib时,Git实际上是通过使用最新masterxo-lib提交的所有文件填充索引来开始的。换句话说,它会将文件的冻结副本存储到索引中。顺便说一句,它还填充了工作树,将冻结的副本扩展为可用的形式。完成此操作后,您的工作树将拥有所有可供使用的文件。

一旦您对工作树进行了更改,索引和工作树就会有所不同。这是您对文件进行暂存的时间,使用git add。这一切都是将工作树版本复制到索引中。 Git将文件压缩为特殊的,仅Git的格式,并用新副本替换索引中的所有 。如果文件是全新文件(如果没有索引副本),则将文件放入索引。

如果文件的工作树版本与该文件的索引版本不同,则Git表示该文件不是暂存的。。如果工作树文件与索引版本匹配,但是索引版本与HEAD版本不匹配,则Git表示该文件已被暂存以进行提交。 所有三个版本的文件可能会有所不同,在这种情况下,文件都已暂存!不过,您不会用git add来得到它,因为add意味着将工作树版本复制到索引,然后它们将匹配。

git commit的工作方式,包括冻结索引

Git速度的秘密在于,索引已准备好进行下一次提交。 git commit命令只需要收集您的日志消息,然后冻结所有索引文件并将它们链接到新提交中。完成后,新的提交和索引匹配,因为新的提交是从 索引进行的。

新提交的父提交就是当时的提交。假设我们正在执行如上所述的提交L,我们将进行新的提交M

...--L   <-- xo-wip (HEAD)
      \
       M

,然后Git将更新当前的分支名称,在这种情况下,xo-wip附加了HEAD,因此它指向我们的新提交{{1} }:

M

由于...--L--M <-- xo-wip (HEAD) 是根据索引创建的,因此M的冻结文件与索引匹配。根据定义,没有什么可以取消登台的,因为Git所谓的所有“登台”(某些文件的索引副本与冻结到M的副本不同的所有内容)现在都冻结在当前提交L中。 ML匹配的所有其他文件也被冻结到M中:它们只是共享的。索引已经准备好进行更多的工作和更多的提交。

相关问题