如何保存或 "stash" 上次提交?

how to save or "stash" last commit?

我经常在其他人的提交(稍后称为 "base" 提交)合并到远程存储库之前处理它,通常这是我挑选的 gerrit 中的更改。当那个人将新的补丁集推送到 gerrit 时,我经常需要用新的 "base" 提交替换旧的 "base" 提交,其中包含最新的 gerrit 更改。

所以假设我有一个本地分支,上面有 2 提交,"base" 提交和我的提交在上面。完成我现在想要的方法是:

"commit" 我的意思是实际的 git 提交,即您通过 git commitgit cherry-pick.

创建的内容

问题:有什么好的方法可以保存我分支上的最高提交,包括提交消息,然后恢复它?

“提交”根据定义已经保存。使用 git reset --hard HEAD~2 本质上是 不保存 它,因为不再有 git ref 指向它。[1]

您基本上是在使用基于补丁的工作流,而不是基于分支的工作流。 (例如你的 format-patch)。如果您想继续执行基于补丁的工作流程,那么您的步骤将尽可能简单。[2]

如果您切换到更现代、更复杂的基于分支的工作流程,您将使用 git rebase 将任何一组提交变基到一个新基上。

我没有使用Gerrit,所以不知道它是否直接支持基于分支的工作流。我在某处读到它确实支持变基。下面的引用是 from Wikipedia。第一段描述了你的过程。第二段 似乎 是说,如果您使用 Gerrit,您将无法摆脱基于补丁的工作流程。 但我不确定。我认为你应该进行研究。 ;)

Gerrit is a commit review tool. Developers amend individual commits in response to feedback; Gerrit tracks each version of each commit, allowing developers to view the differences between versions, and to rebase individual commits while keeping shared history in the review interface. Developers can pull individual commits (e.g.: using the 'cherry pick' option) and can push groups of related commits as a patch set.

This patch-based workflow is avoided in favor of the pull request workflow used by several Git platforms such as GitHub and GitLab. In the pull request workflow complete branches are reviewed and merged. There are projects, such as Go (programming language) which use GitHub and Gerrit at the same time. Due to the process used by the Go team to sync GitHub pull requests to Gerrit, the pull request branch is squashed into a single commit. This loss of granular commit information in the squash is why the Go team recommends contributors to use their Gerrit instance.

如何在您当前的方法中使用git rebase

用以下内容替换上面的步骤。我将假设有两个提交的相同示例:

  1. head 移动到“基础提交”之前的提交:git checkout HEAD~2。你将处于超然的状态。

  2. 从 gerrit 中挑选一个新版本的“基础”提交到它上面(就像你以前做的那样)。

  3. 在此基础上重新设置本地分支,但只有提示是您的提交:git rebase --onto head my-branch^ my-branch.

如果您从 gerrit 中挑选了更多提交,或者您的本地工作有多个提交,您将必须相应地调整步骤 1 中的 HEAD~2 和步骤 3 中的 my-branch^


[1] 提交没有被删除,至少现在还没有,尽管当 git 最终 GC 将它们删除时它们会被删除。它们将作为孤立的提交继续存在于回购协议中。您可以通过 git reflog 找到它们,但您不应该将其作为 正常 工作流程的一部分。 Reflogs 用于从错误中恢复,而不是日常使用。

[2] 您可以使用 git stash,但这只适用于未提交的更改。您 可以 通过 git reset <base commit> 执行此操作,这实际上会将您的所有工作恢复为未提交状态,然后 git stash,然后 git pop 位于顶部更新的基础。

我曾经使用 gerrit,这个过程很有效。我按照您在问题中使用的方式使用名称 base

说你的分支看起来像这样

ID4 Your work 2
ID3 Your work 1
ID2 Base original version
ID1 The current head of master on the official branch

其中 ID 是您在 git log --oneline 时看到的提交 ID。

当您发现 base 有新版本时,您可以从 gerrit 中执行 fetch,而不是从 cherry -挑选。 (或者你可以挑选然后切换回你的分支。)然后你将有一个新提交的提交 ID,我们称之为 ID5。

ID5 Base new version

您想将上面列表中的 ID2 替换为 ID5。因为您已经获取了 ID5,所以您可以通过交互式变基轻松地做到这一点

git rebase -i ID1

当您保存文件并退出时,这将向您显示将在 ID1 之上应用(选择)的提交的待办事项列表。

只需将此列表中的 ID2 替换为 ID5。保存文件并退出。

提醒一句:您在 ID2 之上创建的提交(ID3 和 ID4)可能无法完全应用于 ID5(因为,例如,您更改了依赖于 ID2 的内容,或与 ID5 冲突).因此,我总是建议在使用命令

开始变基之前创建一个备份分支
git branch backupXYZ

如果您的提交不适用于变基并且您不知道如何手动合并,那么您可以回到原来的位置。