Git 的基本存储机制是“提交”——事实上,git stash 所做的只是进行一些不寻常的提交——所以Nick Volynkin's answer 是正确的。不过,它也许可以使用一些扩展,并且有更简单(嗯,可能更简单)的方法。
我不是git stash的忠实粉丝,但如果你习惯使用它,这里是其他方法中最简单的:
-
git stash save(又名git stash)。这将写入两个提交,一个基于当前索引,另一个用于保存尚未暂存的工作树文件。 (如果你需要保存 untracked 文件,你可以添加 -u 标志,然后 stash 脚本添加第三次提交。通常你可以让这些未跟踪的文件在你的工作树中浮动但是,未跟踪。)这些提交不在任何分支上,它们仅在特殊的“存储”参考中/中。与此同时,你仍然在“错误”的分支上,我将在下面调用wrongbr。
-
git checkout 你想要这些的分支。现在你在正确的分支上。
-
git stash apply --index。这使用了在步骤 1 中进行的特殊存储提交,同时也将它们保留在存储中 (apply)。 --index 非常重要:它告诉 stash 脚本将索引和未暂存文件分开,即,让您恢复之前的暂存和未暂存设置。
如果一切顺利,您现在可以git commit 对您想要的分支进行更改。先前暂存的文件再次暂存,而未暂存的文件仍处于未暂存状态,因为您 apply- 使用 --index 编辑了暂存文件。提交将提交暂存文件,使未暂存文件不暂存。
-
现在您可以返回另一个“错误”分支(您最初在其中进行存储)和git stash apply 或git stash pop,无论是否使用--index。您可能需要清除所有未暂存的文件(这样做是安全的,它们仍在存储中):git reset --hard,然后是 git checkout wrongbr,然后是 git stash pop。请注意,pop 只是 apply 后跟 drop:我们不想要删除步骤 3 中的存储(存储只有原始修改但未暂存的文件),这就是我们在那里使用 apply 的原因,但现在我们(大概)确实想要删除存储,所以使用 pop 是可以的。
不过,第 3 步有一个很大的潜在陷阱:存储可能无法正确应用。如果是这样,您必须使用其他方法。这是我不太喜欢stash 系统的原因之一:它在困难的情况下会崩溃,如果你不使用stash,你需要知道可以使用的工具。在这种情况下,您可以在大多数情况下只使用这些工具......然后使用stash 作为您确定它可以工作的便捷捷径。
背景:提交现在获取索引中的任何内容—git ls-files --cached 将显示完整的内容,而git status 将其缩减为“有趣”的内容并添加额外的有用信息 — 并从中进行提交,以及所有必要的树对象等等。新提交的父提交是当前提交之前的任何内容。
您希望在另一个分支上进行新的提交。一种方法是现在就在当前分支上创建它;然后将该提交复制到不同分支上的新的不同提交。要执行“将提交复制到不同分支上的新的不同提交”,您可以使用git cherry-pick。确实可以使用git rebase:在幕后,它使用git cherry-pick 本身。但是rebase 不是一个完全正确的工具:它是为集体采摘而设计的,你只有一个提交;最后它使用git reset 移动一个分支标签,但不是你想要的方式。你可以让它工作,但有一些更合适的工具。
让我们回到最初的问题:您想要获取当前索引并使用它来进行新的提交,但是在另一个分支上。如果您现在可以直接切换到另一个分支,而不做任何其他事情,然后进行新的提交,这将是最简单的。
您可以这样做的机会很大。只需git checkout otherbranch,然后是git commit。这里有三种可能的情况:
-
另一个分支还不存在。伟大的!使用git checkout -b newbranch 创建它,从您现在所在的位置开始。然后git commit。你已经完成了,除非你想重新设置新分支以从“你现在所在的位置”以外的地方开始。如果是这样,请在新分支上使用 git rebase。请注意,您可以在处理完未暂存的文件之后再进行变基。
-
另一个分支确实存在,而且——幸运的是——git checkout otherbranch 工作正常。这样做并提交,你就完成了。然后,您可以git checkout 任何您想要的未暂存文件的分支。
-
最烦人的情况:另一个分支确实存在,但是git checkout 告诉你你会覆盖你没有提交的东西。
案例 3 是您需要提交或隐藏的情况。
在这里做什么取决于您最喜欢什么。例如,您可以尝试上述四步 stash 方法,这是最简单的替代方法。
不过,对于我自己来说,我现在只需在“错误”分支上提交,然后再次提交(或使用git stash)以消除未暂存的文件。这给了我一个提交,我可以git cherry-pick 进入 right 分支。下面是一个可能有效的示例序列:
-
git commit 进行提交,但在“错误”分支上(我们将您当前的分支称为 wrongbr 以供参考)。
-
git stash save 保存未暂存的更改(或者,使用 -u,也可以保存未跟踪的文件)。
-
git checkout 您希望提交所在的分支,例如 git checkout rightbr。
-
git cherry-pick wrongbr。如果这成功了,很好;如果没有,请在合并问题后根据需要编辑文件以清理,然后git commit 结果。
-
git checkout wrongbr:我们现在将通过删除在第 4 步中复制的提交来解决这个问题。
-
git reset --hard HEAD^:这会删除我们复制的提交。
-
git stash pop(或 git stash apply && git stash drop 做同样的事情,apply 变体只是让您有机会在 drop 存储之前检查结果)。
请注意此处的第 4 步:git cherry-pick 采用命名提交(wrongbr 的提示,其中包含我们想要的提交,它只是在错误的分支上),将其与其父级进行比较,然后尝试将结果差异应用于当前分支。如果当前分支中的文件与wrongbr 中的相应文件有很大不同,则可能需要进行 3 路合并。这与在仅签出rightbr 并最初提交的简单情况下发生并发症的地方相同。也就是说,我们正在做这个长版本,因为“最烦人”的情况发生在我们在提交之前尝试只 git checkout rightbr 时,所以我们很有可能需要做一些修复。这也可能导致原来的 4 步 stash 方法出现问题。