当你可以进行新的提交时,git stash的目的是什么?

时间:2016-05-23 23:07:15

标签: git

我正在学习git stash here,但在切换到其他分支和工作之前只能进行提交时,却无法理解它的用途。它更方便吗?或者更干净,不必为你的提交日志添加额外的条目只是因为你必须切换到另一个分支来做一些非常快的事情?

此外,当您使用git stash pop时,它会自动将您跳回到您藏匿的分支吗?如果我想为每个分支创建不同的存储怎么办?

3 个答案:

答案 0 :(得分:3)

如果您在项目中独自工作并且不记得脏日志,那么请继续并提交。

但是如果你在一个团队中工作,那么提交一份非工作或非编译的改变将会被贬低。当然,你可以提交而不是推动它,但它仍然是一个坏习惯:它混淆了各种工作流程,合并/重组冲突,一分为二等。

如果你藏匿你的更改,那么你就不会打扰任何人了。

关于分支问题:不,当您git stash pop在当前分支中应用存储时,无论您将其存储在哪个分支中。您可以根据需要制作尽可能多的藏匿处,只需继续堆叠,您可以使用git stash pop stash@{N}弹出任何人,而不仅仅是以相反的顺序。 (但请参阅git stash branch以获取替代方案)。

如果您觉得每个分支都需要不同的存储列表,那么您可能会更好地使用遵循公共分支的私有分支。

答案 1 :(得分:3)

您可能希望使用git stash的官方git文档lists a few situations(请参阅示例部分)。就像你说的那样,它主要用于在某些情况下提供的方便/速度,而不是提交。

git stash pop尝试在当前分支的顶部应用隐藏的更改(确切地说,在当前工作树状态之上)。

存储是全局创建的,而不是基于每个分支。但是,您可以使用git stash save <label>保存带有与您的分支对应的标签的藏匿处。

答案 2 :(得分:3)

你是正确的,你可以提交(然后再回来git reset --soft取消提交,稍后),我有时会在重新定位时这样做。

  

此外,当您使用git stash pop时,它会自动将您跳回到您藏匿的分支吗?如果我想为每个分支创建不同的存储怎么办?

没有。 (我看到有人已经提到了stash@{N}符号,所以除了添加使用Git的reflog之外,我将把它留在这个答案之外。)应用stash主要是,尽管不完全,如使用git showgit log -p将提交转换为修补程序,然后将修补程序应用于git apply

存储存储为两个或三个 1 提交,这些提交不在任何分支上。我喜欢将这些提交称为&#34;存储包&#34;,原因有几个,其中一个原因是该包挂起了当你藏匿时当前的特定提交。

如果我们绘制一系列普通(非合并)提交作为一行节点o,每个节点都指向其父节点,然后在分支名称中绘制一个指针,用于标识提示的提示我们得到了一个很好的紧凑表示部分提交图:

... <- o <-o <- o   <-- branch

通常我们只省略内部箭头,因为我们知道每个提交指向其父级:

...--o--o--o   <-- branch

在这一点上存储会在提示提交中挂起两个 2 提交。其中一个,我标记为i的是索引状态(你有git add ed),另一个是w,是< em> work-tree 状态(工作树中您可以git add编辑的所有跟踪文件):

...--o--o--o   <-- branch
           |\
           i-w <-- stash

这个藏匿袋只挂在那里,高高兴兴地摇晃着,并通过特殊的stash参考找到。因为 是通过stash找到的,如果您运行git log --allgitk --all或类似内容,您会看到它。

如果你然后 rebase 你的分支,Git通过复制分支上的提交,回到任何一点来做到这一点。也就是说,&#34;之前&#34;图更准确地绘制成这样:

...--o--o--o--o--o--o  <-- feature
      \
       \
        \
         o--o--o       <-- branch
               |\
               i-w     <-- stash

branch上重新feature制作旧提交的新副本,并移动标签:

...--o--o--o--o--o--o  <-- feature
      \              \
       \              o--o--o   <-- branch
        \
         o--o--o       [abandoned: previous branch]
               |\
               i-w     <-- stash

请注意,如果您运行git log --allgitk --all,您通常不会再看到原始分支及其三次提交,但由于stash仍悬而未决,因此指向w 1}},现在显示的不仅是藏匿,而且还有原始的三次提交。

正在运行git stash pop - 我实际上建议坚持使用git stash apply 3 ,直到您对Stashes和Git感到非常满意,因为apply给了你一个机会改变主意,但让我们继续考虑pop - 让Git将存储应用于您当前的新提交(可能是复制的branch的新提示),然后删除{ {1}}参考:

stash

现在所有这些旧提交以及藏匿不再显示。

如果您进行常规提交而不是存储,然后进行rebase,则rebase会复制常规提交。使用...--o--o--o--o--o--o <-- feature \ \ \ o--o--o <-- branch \ o--o--o [abandoned: previous branch] |\ i-w [abandoned] 丢弃它,放弃它就像你通过弹出放弃存储一样,所以最终这两个做的几乎完全相同(除了因为{{1}而需要进行的任何更改} git reset --soft步骤期间发生,而不是rebase步骤。

请注意,应用存储分两步完成,如果有三次提交则应用三次:首先Git应用索引更改,然后应用工作树更改(如果需要,还应用未跟踪的文件)。如果您在应用时使用rebase标记,Git会尝试将更改恢复为暂存和非暂存,就像您执行git stash apply && git stash drop创建存储包时一样。否则,它只是将它们一起组合到工作树中。

(这种混合在一起是分别使用--index的另一个原因,因为您可以重置它们并git stash save如果您意味着做什么......但是,只有你还没有放下藏匿处。)

1 如果您使用git stash applygit stash apply --index来存储未分段或所有文件,则存储脚本会进行第三次提交。在这种情况下,-u仍指向提交-a,但stash具有包含这些额外文件的第三个父提交。第三次提交没有自己的父级,与w提交不同,后者与w具有相同的父级。换句话说,隐藏包仍然像往常一样挂起相同的提交,但现在它有一个额外的root提交作为第三个父提交,这很难描述。

2 或三,与前一个脚注一样。

3 使用i只运行w,虽然效率稍高,因为它在一个脚本中完成,而不是两个单独的命令。如果git stash pop完全失败,则git stash apply && git stash drop不会发生,但如果apply有效且出错,则drop 会发生。所以,如果您发现应用程序产生了混乱,并且您希望稍后将其转换为apply,则为时已晚。

drop代码将存储转换为新分支。如果存储袋挂起的提交已被放弃,这将有效地恢复在新分支名称下提交(及其所有父项)。