【问题标题】:git-stash changes without revertinggit-stash 更改而不还原
【发布时间】:2016-09-09 13:12:48
【问题描述】:

我使用 Git 处理一个项目。每隔一段时间,我就会发现自己想要保存我的更改,而不是提交它们,只是作为备份,然后继续工作。我通常做的是git stash 然后立即git stash apply 使代码恢复到与存储之前相同的状态。我遇到的问题是 git stash 恢复了我的工作目录,所以即使我立即应用 stash 文件和项目也必须重建,因为它们似乎已经改变。这很烦人,因为我们的一些项目需要很长时间才能构建。

所以我的问题是,有没有办法在不恢复的情况下隐藏我的更改?如果 stash 不这样做,那么 git 中是否还有其他命令可以做到这一点?谢谢。

【问题讨论】:

  • 作为替代方案,您也可以git add 更改而不提交它们。这会将更改的文件放入暂存区域。要恢复到暂存版本,请使用 git checkout -- <filename>
  • @Phillip 我试试看,谢谢!
  • 绝对没有完美的解决方案。在这种情况下,我倾向于做的就是继续进行许多提交,然后稍后将它们压缩在一起。 (通常这也意味着创建一个新分支——我有时会得到很多 很多 分支 :-)。)

标签: git git-stash


【解决方案1】:

当我发布这个问题时,我是 git 的新手,并不完全了解它的功能。现在我意识到存储不是我需要的,而且 git 的本地分支做得更好。

假设您在 main_branch 上,您希望避免实验性更改。

只需创建一个新分支来存储您的实验性更改。

git checkout -b temp_branch

假设您进行了一些更改并希望保存您的进度。只需提交,无需担心,一切都在 temp_branch 上:

git commit -a -m "first change"

假设您进行了更多更改并想再次存储:

git commit -a -m "second change"

最后,假设您对实验性更改感到满意并希望将它们合并到主分支。有两种情况:

1) 如果要合并所有更改,请执行以下操作:

git fetch . temp_branch:main_branch

这会将 temp_branch 的所有更改带入 main_branch,而无需切换到主分支,这意味着您的文件不会被修改,也不需要重新编译。请注意,只有在此期间您没有对 main_branch 进行任何其他更改时才有可能。如果 main_branch 发生了变化,您需要使用 git mergegit rebase,但这种情况超出了问题的范围。

2) 假设您只想将 temp_branch 的一些提交合并到 main_branch。您可以使用git cherry-pick 执行此操作。首先执行git checkout main_branch 切换到main_branch(这会修改文件,但这是不可避免的,因为您要删除一些更改),然后执行git cherry-pick <SHA>(其中<SHA> 是您要合并的提交的哈希) .你可以通过git log temp_branch 查看提交列表。请注意,仅合并部分更改可能会产生您需要解决的冲突。

【讨论】:

  • 我和你有同样的问题。感谢您发布此答案。我不认为这种方法真的等同于git stash 加上git stash apply,因为它不会将索引中的更改与工作目录中的更改分开保存。如果您不使用commit -a,也许它会等效...我不记得checkout -b 是如何处理脏工作目录和索引的。
【解决方案2】:

这可以通过手动创建一个 stash 提交对象,然后将其存储在 stash 中来实现。

git stash store $(git stash create) -m "Stash commit message"

说明

我也喜欢在进行我认为可能不会成功的更改或重构之前将东西放入存储库中作为回滚点。我发现用简短的描述把它扔到存储区比使用分支更快、更容易,并且需要更少的心理上下文切换。使用分支涉及创建分支,记住分支名称,然后删除临时分支提交和恢复时它自己的分支。

Git 有一些命令可以在不从工作目录中删除文件的情况下将内容存储到存储中,如 https://stackoverflow.com/a/44330944/1108305 中所述。可以使用git stash create 创建一个存储提交对象,然后使用git stash store 将其保存到存储中:

git stash store $(git stash create) -m "Stash commit message"

这可以保存到一个 Git 别名中,这样更方便:

git config --global alias.stash-keep '!git stash store $(git stash create)'

git stash-keep -m "Stash commit message"

请注意,这并不是git stash push 所做的所有操作。一方面,它不会将分支名称附加到提交中,例如“stash@{0}: On myBranch: Stash commit message”。其次,当没有对存储进行更改时,上面的简单别名将使用“"git stash store" requires one <commit> argument”而不是“No local changes to save”出错。这些限制可以通过更复杂的别名或脚本来解决,尽管此处提供的最小版本可能就足够了。

【讨论】:

  • 这完美地回答了原来的问题。
【解决方案3】:

您似乎想要一种方法来临时存储您的更改,这样您就不会意外删除它们,可以回滚。

最好的方法是在本地实际提交您的更改。

典型的工作流程是这样的:

vim myfile # make some changes
git add myfile
git commit -m "temp changes 1"
vim myfile # make more changes
git commit --amend
git diff HEAD~1 # See the changes you've made compared to last HEAD.

这样做的缺点是您的“本地更改”没有被修订。

另一种选择是继续将您的本地工作保存为不同的提交,然后在发送补丁/PR之前简单地压缩它们以进行润色。

这看起来像这样:

vim myfile2 # make changes
git add myfile2
git commit -m "temp changes dated X"
vim myfile2 # more changes
git add myfile2
git commit -m "temp changes dated Y"

然后简单地做这样的事情,然后再将它们送走。

git rebase -i HEAD~N # Where N is the number of local commits you made
# Squash them, by changing 'pick' to 'squash' in your editor.
# Send them away
git push origin dev 

【讨论】:

  • 似乎没有做我想做的事。我的本地文件仍在还原。
  • 我认为您误解了 OP 的问题。他的问题是 git stash/git apply 更改了文件的 mtime,而不是取消了已添加到索引中的更改。
  • 我认为他的问题理解正确,我不知道git stash save --keep index仍然修改了c/mtime
  • OP 可以做的替代方法(我承认这是一个可怕的 hack)是无论如何提交文件,然后使用 git commit --amend 进行后续“保存”,然后使用最终的 git commit --amend 或 @ 987654330@ 在发送提交/补丁/PR 之前添加一些收尾工作。但理想情况下,它应该可以完成工作。这是 iirc 中 mercurial queues 做得很好的事情:/
  • 还有一个问题,--keep-index 仅适用于已经 git add'ed 的更改。
【解决方案4】:
git stash && git stash apply

如果您更喜欢带有评论的存储:

git stash save “stash comment” && git stash apply

【讨论】:

  • 感谢您的回复。从我所做的快速测试来看,看起来更改已被隐藏并重新应用,在此过程中修改了文件并导致重新编译。我这样做的动机是避免文件修改和重新编译。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 2013-09-15
相关资源
最近更新 更多