如果我将更改藏在一个分支中,然后删除该分支会发生什么?

39

如果我在一个分支中隐藏了更改,然后删除该分支,会发生什么?

(1) 我会失去隐藏的更改吗?

示例:

git stash
git checkout other_branch
git branch -D previous_branch

(2) 另外,上述的存储和删除步骤是否等同于在分支中提交更改,然后删除该分支(就最终状态而言)?即:

git commit -m "Dummy commit, I am terminating this branch"
git checkout other_branch
git branch -D previous_branch

@torek 提供了一个很好的答案,但简单来说,stash 条目不属于任何分支,任何分支操作都不会影响 stash - 它是一个完全正交的概念。 - kostix
2个回答

27

(1)不。通过git stash保存的更改将作为一对(或有时是三个)提交进行保存。这些提交由名称stash引用。如果您将分支名称和标签视为提交的标签(这就是它们所代表的),那么您可以画出一个图像,例如:

(1) No. 通过git stash保存的更改将被保存成一对(或有时是三个)提交。这些提交会被命名为stash。如果您把分支名称和标签看作是提交记录的标签(实际上就是这样),那么您可以画出下面这张图片:

          O1 - O2             <-- other_branch
        /
M1 - M2 - M3 - M4             <-- master
   \
     B1 - B2 - B3             <-- branch
      .
       .......................<-- tag

(如果我可以以不同的颜色标记标签,可能会更有效果;我使用点号来表示标签tag指向提交B1,该提交“在分支branch上”)。

如果你在分支branch上有一些未保存的更改,并运行git stash,它会执行以下操作:

        /
M1 - M2 - M3 - M4             <-- master
   \
     B1 - B2 - B3             <-- HEAD=branch
                | \
                i - w ........<-- stash

(我在图表中省略了other_branchtag,但它们仍然存在。 我写HEAD=branch是为了暗示HEAD指向branch,而branch指向提交B3。)

这里iw是您stash的“索引”和“工作树”状态。名称stash直接指向提交w,而w有两个父级(即使它实际上并不是合并),其第一个父级为B3,第二个父级为i

当您运行git branch -D时,您只是擦除标签。所以假设您git checkout other_branch,然后擦除标签branch。现在您有这个:

          O1 - O2             <-- HEAD=other_branch
        /
M1 - M2 - M3 - M4             <-- master
   \
     B1 - B2 - B3
                | \
                i - w ........<-- stash

B3没有直接的标签,但隐藏点指向w,而w又回指到B3。所以所有东西仍然存在,并且只要存储(或者reflog,或者两者都保留)将B3保持在Git的内部视野范围内,它们就会一直存在。

(2) 不是这样的:正如您所看到的,stash仍然引用了该分支。 但是,一旦你删除了这个stash - 例如,使用git stash drop - 你会得到以下结果:

          O1 - O2             <-- HEAD=other_branch
        /
M1 - M2 - M3 - M4             <-- master
   \
     B1 - B2 - B3
                | \
                i - w

如果你已经执行了git addgit commit来提交所有的更改,你将会得到一个(单一,非合并)提交,我们可以称之为B4,在分支branch上。 分支标签将被移动到指向B4,然后你将检出other_branch并删除该标签,这样就会得到:

          O1 - O2             <-- HEAD=other_branch
        /
M1 - M2 - M3 - M4             <-- master
   \
     B1 - B2 - B3 - B4

这几乎(但并非完全)相同。

请注意,如果标签tag仍然指向B1,提交B1将一直保留,直到该标签也被删除。提交B2B4B2w只会在引用日志中保持不可见的状态下存在。在30天后(或您设置为引用日志过期的时间),引用日志条目将过期,这些提交将有资格进行垃圾回收。


10
  1. Stashing(存储)会将当前工作目录的未提交状态保存在一个堆栈中。如果您进行了存储,然后删除之前的分支,则您的存储变更不会消失。您可以使用以下命令列出存储堆栈中的内容:

git stash list

实际上,您可以保存一个存储,切换到另一个分支,并尝试重新应用该存储。在同一分支上应用存储并非必须。

在第二种情况下,应用存储后仍需要执行 git commit。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接