【问题标题】:How to drop file in a stash without applying it?如何在不应用的情况下将文件放入存储中?
【发布时间】:2017-05-03 08:55:18
【问题描述】:

我很惊讶没有找到对这个问题的回复,但基本上说我有一个包含几个文件的存储区(例如,我可以通过 git 扩展来探索它)。看它的内容,我想在应用之前先删除一些文件,可以吗?

我能想到的唯一解决方法是:

  1. 将存储签出到新分支
  2. 签出目标文件
  3. 再次藏匿
  4. 删除分支

还有更好的吗?

【问题讨论】:

    标签: git git-stash


    【解决方案1】:

    您可以直接使用stash(或stash@{0})作为提交参考。

    如果你的工作树是干净的(没有修改过的文件),你可以签出你想要的文件:

    git checkout stash -- file1 file2 file3
    

    然后手动检查差异以保留您想要的。


    如果您想要更接近git stash apply 的行为,您可以创建一个补丁并应用它:

    git show -p stash -- file1 file2 file3 | git apply -
    

    [编辑] 列出在stash 中修改的文件:

    git diff --name-only stash^ stash
    

    如果你想获取除一个以外的所有文件:

    git show -p stash -- $(git diff --name-only stash^ stash | grep -v "thefile")
    

    【讨论】:

    • git 太棒了,谢谢。这对它的作用很好,但不会修改存储。假设我想应用除一个文件以外的所有文件,我必须将它们全部列出。是否有某种相反的命令?
    • 我无法使git show -p stash@{0} -- file1 file2 file3 | git apply - 工作,我得到“错误:无法识别的输入”,而它在没有| git apply - 的情况下工作
    • “有效”:你的意思是 git show -p ... > patch && git apply patch 有效吗?
    【解决方案2】:

    是的,有更好的方法来做到这一点。

    首先,您可以将存储列表检查为

    git stash list
    

    然后您可以执行以下操作来检查隐藏提交的内容。

    git stash show -p stash@{1}
    

    然后你可以申请使用

    git stash apply stash@{1}
    

    【讨论】:

    • 谢谢,但这并不能回答我的问题。我知道如何查看存储的内容并在全球范围内应用它。我正在寻找某种隐藏的部分应用,请参阅@LeGEC 答案
    【解决方案3】:

    这个问题的棘手部分似乎围绕着您希望完成后的存储外观。由于git stash {pop|apply} 仅影响工作树(有时影响索引),因此很容易有选择地从存储中获取更改(足以让我最初认为您过度思考问题):

    git stash pop
    # maybe a 'git reset head' if the index was changed
    git checkout -- file.with.unwanted.changes.in.stash
    

    但是这些命令完全删除了存储;相比之下,如果我说git stash apply 而不是pop,那么存储不会改变。听起来您希望存储区保留您选择的更改(以防您需要再次应用它们)。

    (我想有时您可能希望完全相反 - 将那些您未应用的更改留在隐藏中,以便以后应用它们。)

    所以退后一步:修改存储涉及什么?

    实际上,一个 stash 包含两个或三个临时提交。特殊的 ref stash 指向这些提交,并使用 reflog 维护多个存储的“堆栈”(这可能有点小技巧,但通常是有效的)。

    所以修改 stash 就是创建新的提交(因为提交是不可变的)并相应地重新排列 stash ref 和 reflog。

    这就是 LeGEC 提到的符号会起作用的原因,并且可以为您在阅读存储时提供额外的灵活性。但是由于 reflog 的使用与非存储 refs 的用法不同,因此利用这一事实来设计一种 write 到存储的方法可能会产生意想不到的结果。我并不是说结果会很糟糕,或者无法预测/控制;但我认为最终你会创造出比你避免的更多的复杂性。

    因此,如果我们将自己局限于实际记录的git-stash 子命令,那么存储或多或少是原子的。当您创建一个存储时,有一个 patch 模式,可让您选择要放入堆栈的工作更改,但我知道弹出/应用没有相应的功能。不过,还是有这样的:

    如果您有一个干净的工作树和一个要拆分的存储,您可以尝试以下操作:

    应用一些更改,并将这些相同的更改保留在存储中

    git stash pop
    git stash -p
    # select the "good" changes
    git checkout -- .
    git stash apply
    

    应用一些更改,并将剩余的更改保留在存储中

    git stash pop
    git stash -p
    # select the "unwanted" changes
    

    将存储分成两部分,稍后决定如何处理它们

    git stash pop
    git stash -p
    # select the "good" changes
    git stash
    # now the "good" changes are stash@{1} and the "unwanted" are stash@{0}
    

    【讨论】:

    • 次要技术说明:每个存储总是至少有两个提交(索引状态加上工作树状态),有时三个:索引、工作树和“附加”。 “附加”部分存在于git stash -ugit stash -a stashes 中,并包含“untracked-sans-ignored”或“untracked-including-ignored”文件(仅;这与索引和工作树状态不同,它们都保存所有跟踪的文件)。
    • @torek - 嗯......出于某种原因,我认为如果其中一个为空,它将被省略。会更新。谢谢。
    【解决方案4】:

    删除隐藏条目而不应用它的简单解决方案是删除它:

    git stash drop stash@{1}
    

    这里1 是您通过运行获得的隐藏条目:

    git stash list
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-20
      • 2011-10-23
      • 2016-05-17
      • 2021-12-25
      • 1970-01-01
      • 2021-11-15
      • 2012-06-12
      • 1970-01-01
      相关资源
      最近更新 更多