GIT隐藏和分支之间的切换问题——一个分支的工作出现在另一个分支上,而没有合并



我最近同时处理多个分支(确切地说是3个分支,我们称它们为A、B和C)。

我在A分支,然后决定切换到B,但我还有一些工作,还没有准备好提交。所以我把它藏起来换了。

在B上重新显示代码后,我切换到C,以便立即进行一些更正。再一次,我需要换成B,所以我把它们藏起来了。

然后我决定转到A分支,以便从最后一个"开始"工作;检查点";我申请了最后一笔。

然后奇怪的事情开始发生了——我看到C分支的部分变化。

我知道这是一个混乱的工作流程,但今天它发生在我身上…

既然我没有合并任何东西,这怎么可能发生?

最糟糕的是,我删除了所有隐藏的东西,除了我申请的一个,认为这是一些旧的、不必要的隐藏。

然后我决定切换到A分支,以便从最后一个开始工作;检查点";我申请了最后一笔。

;最后一次藏匿";你在这里申请的是你在分支C上做的隐藏。这就是为什么你会看到你早些时候在分支C做的更改。为了正确地做到这一点,你需要应用顶部的第二个隐藏:

git checkout A
git stash apply stash@{1}

我知道这是一个混乱的工作流程,但今天它发生在我身上…

这似乎是一个合理的工作流程。作为一名程序员,由于管理者的要求,我们经常被拉向多个方向。git stash的全部意义在于让我们处理这些类型的干扰。你只需要正确使用它。

。。。最糟糕的是,我删除了所有隐藏的东西,除了我申请的一个,认为这是一些旧的、不必要的隐藏。

这是个问题。这很可能意味着您丢失了分支A和C上两个藏匿处的工作。作为最后的手段,您可以通过检查输出git reflog来恢复一些工作。

Stash被称为有害

藏匿物是一种非常奇怪和复杂的野兽,(正如你所发现的)滥用它太容易了

当然,存储与HEAD(当前分支)、索引(描述当前分支上可能的新提交)以及创建存储时的工作树密切相关:

index-commit ⬅︎ working-tree-commit
|         |
       /    
⬇︎      ⬇︎
HEAD-commit

那个图中的箭头指向父母关系的方向。因此,工作树提交是一种合并(一种非常奇怪的合并,一种合并,然后是一些)。

实际上,您可以通过调用存储中的git log查看提交的复杂性:

$ git log stash --graph --oneline
*   778388c (refs/stash) WIP on master: 3429244 z
|  
| * dcd25d1 index on master: 3429244 z
|/  
* 3429244 (HEAD -> master, branch) z

HEAD提交不是";内部";存储,但该图中的其他两个提交是。请记住,索引是HEAD快照中所有文件的快照,这是提交时您的所有文件;工作树快照是您可以看到的所有文件的快照。

因此,如果你将这个隐藏应用于不同的分支,你将向索引和工作树中注入一大堆关于这个分支的内容。你可以很容易地做到这一点,因为正如你正确地说的那样,你可以有多个藏匿处,它们都是全球可见的。

因此,我不建议过多使用隐藏。在你描述的特定情况下,我认为这种反应是错误的:

但我有一些工作,还没有准备好提交。所以我把它藏起来

否。这标志着对承诺的态度不够灵活;准备提交";。您应该尽早并经常提交。WIP(在制品)提交没有任何问题。毕竟,以后当您修改历史记录以将其总结为一系列有意义的提交时,您总是可以将WIP提交压缩掉。

所以,在这两种情况下,你都藏起来了,我只会提交一个在制品。这要安全得多,因为它直接绑定到分支——事实上,它就是分支。只需给它一条"WIP"消息,这样当你再次查看它时,你就会立刻知道你正在做一些事情。

(所以当时,你需要一个隐藏?在这种罕见的情况下,你甚至不能做我刚才说的事情,你需要它。索引是部分形成的,可能包含了一些不应该包含的东西,所以你正处于索引所说的和工作树所说的之间的精心平衡过程中,没有时间把它们全部解决并形成真正的承诺。这就是为什么y隐藏保存了的状态索引工作树:这是因为它们都处于一种部分半生不熟的状态,而你很忙,也很困惑,你只需要保留那个半生不灭的状态,然后离开这里。)

这一切都是关于隐藏。。。

它们在分支机构之间共享。如果您将工作存储在一个分支上,则可以很容易地将其应用于另一个分支(因此,从其他分支可以看到它)。

我一定是从C分支到A分支应用了隐藏。这就是为什么我看到A的部分工作——因为我只应用了一个隐藏,而不是整个分支。

如何恢复丢失的STASH

当隐藏时,特殊类型的提交是

删除后,它仍然可以在GIT历史中找到,如@Code Apprentice mention,并且可以用git reflog进行检查,这只是的缩写

git log --reflog --oneline

在我的案例中,丢失的提交显示为:

b10b2fc (refs/stash) WIP on branch: 78beda0 [COMMIT MESSAGE]

所以我可以将这个提交合并到我的分支中(这对我来说意味着一些冲突,但这比只重做所有内容要好):

git merge b10b2fc

最新更新