Git 暂存文件。 stash 是否将暂存文件转换为未暂存文件?

Git stash with staged files. Does stash convert staged files to unstaged?

我正在对代码库进行大量更改。有些变化已经上演,有些还没有。我需要切换到另一个 b运行ch,但还没有准备好提交,所以我使用 git stash.

隐藏了我的当前状态

后来,我去申请我的藏品,git stash apply。那我运行git status。我注意到我的暂存更改不再显示为 'staged',而是显示为 'Changes not staged for commit'。我的理解是否正确,实际上没有数据丢失,而是 'staged' 数据现在简单地转换为 'unstaged' 数据?

编辑:我应该补充一点,一些有问题的文件在存储时有暂存版本和未暂存版本。例如,文件 A 进行了一些更改,这些更改已暂存。然后,对尚未上演的文件A进行了一些更改。然后,藏起来了。

是的,你的想法是正确的。 man git-stash 的以下部分对此进行了描述:

Use git stash when you want to record the current state of the working
directory and the index, but want to go back to a clean working
directory. The command saves your local modifications away and reverts
the working directory to match the HEAD commit.

(...)

pop [--index] [-q|--quiet] [<stash>] Remove a single stashed
           state from the stash list and apply it on top of the
           current working tree state, i.e., do the inverse operation
           of git stash save. The working directory must match the
           index.

           (...)

           If the --index option is used, then tries to reinstate not
           only the working tree’s changes, but also the index’s
           ones.

(...)

apply [--index] [-q|--quiet] [<stash>]
           Like pop, but do not remove the state from the stash list.

不,没有丢失任何更改。

累积到 documentation:

Git re-modifies the files you uncommitted when you saved the stash. In this case, you had a clean working directory when you tried to apply the stash, and you tried to apply it on the same branch you saved it from; but having a clean working directory and applying it on the same branch aren’t necessary to successfully apply a stash. You can save a stash on one branch, switch to another branch later, and try to reapply the changes. You can also have modified and uncommitted files in your working directory when you apply a stash — Git gives you merge conflicts if anything no longer applies cleanly.

The changes to your files were reapplied, but the file you staged before wasn’t restaged. To do that, you must run the git stash apply command with a --index option to tell the command to try to reapply the staged changes. If you had run that instead, you’d have gotten back to your original position:

$ git stash apply --index
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#      modified:   index.html
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#

所问问题(“是否将暂存文件转换为未暂存文件”)的答案是肯定和否。

如果您申请了 git stash apply(相对于 git stash pop),您的状态很好,因为藏品仍然存在。但是让我们回顾一下,看看底层机制,因为它在这里很重要。

当你 运行 git stash push(新动词)或 git stash save(旧动词)(或简单的 git stashpush/ save), git 进行两次 1 次提交,这些提交不在任何分支上。一次提交保存索引的状态,即,无论你上演什么。第二次提交保存工作树的状态,即其他所有内容。

稍后,当您使用 git stash apply 时,git 会将更改混合在一起,这样就不会暂存任何内容,除非 您添加 --index2apply 操作,在这种情况下,它会恢复(如果可以的话)您之前对分阶段和非分阶段的安排。

当您使用 apply 时,存储脚本也会保留存储提交,因此如果应用没有按照您想要的方式进行——包括您忘记 --index 或拼写错误 (参见脚注 2)—您可以 git reset --hard(无论如何,假设您在开始时一切都处于干净状态)并重新执行 apply.

不过,如果您使用过 pop,并且 git 认为应用有效,那么它会删除存储。出于这个原因,我通常建议使用单独的应用和删除。

(旁注:我实际上建议尽可能避免 git stash。对于粗心的人来说,它有太多的陷阱,而且历史上有很多错误。但是如果你已经使用过它但现在后悔了,请考虑 git stash branch,它将保存的存储 变成 一个分支。请参见下面的 。你可以使用已经弹出的存储的原始哈希 ID 执行此操作,尽管您通常需要一个“干净”状态。新分支从您创建存储时所在的提交中分支出来。)


1使用 -u-a,它不仅保存暂存文件和未暂存文件,而且还忽略 and/or 所有文件,隐藏脚本进行 三次 次提交。但是,如果没有这些标志,这些文件就不会进入存储的任何一部分。

2令人困惑的是,隐藏脚本还有一个 --keep-index 标志,它允许您为 apply 操作指定,但在那里没有任何意义。相反,--keep-index 会影响 stash 在进行特殊存储提交后所做的事情。有时我不小心做了 git stash apply --keep-index 而不是 git stash apply --index,混淆了两个选项。