快速、小型、随意 git 仅针对一个或几个大块头进行变基:任何设施?

Quick, small, casual git rebase for only one or a few hunks: any facility?

我正在编辑我的源文件以在我的 dev 分支上生成一个新的提交。我的更改已保存在磁盘上但尚未暂存。

然后我注意到一个小错误是由以前的提交引入的,比如 HEAD~10。一旦修复,结果是我的磁盘上只有一个(或几个)额外的 git diff hunk。

我不希望这些帅哥被记录在新的提交中,因为他们属于 HEAD~10。所以我需要变基。这是我的工作流程,但我对此并不满意:

$ git stash # save my current work + the small fix
$ git rebase --interactive HEAD~11
# set first commit appearing in todo list to `edit` action

$ git stash pop # re-introduce my changes here (**may conflict**)
$ git add --patch fixed_files # or similar, to only stage relevant fix hunk(s)
$ git commit --amend # fix old commit
$ git stash # save my current work again
$ git rebase --continue # get back to my current commit (will likely *not* conflict)
$ git stash pop # back here with HEAD~10 fixed

我不满意的是这个过程很复杂,第一行 git stash pop 可能会引入无意义的冲突,尽管我相信在执行 git rebase --continue行。

有没有更好的方法?假设我在 HEAD 中只有几个上演的帅哥,我可以通过一些神奇的方式在我的分支中更早地介绍它们吗:

git amend-old-commit-then-rebase HEAD~10

还保留我未暂存的更改吗? (当然,如果固有的 rebase 发生冲突,我会收到警告)

Interactive rebase 已经有一个内置的方法来处理这个问题。让我们来演示一下。我们首先检查一些现有分支名称的提示提交:

git switch main

然后创建我们的功能或主题分支:

git switch -c topic

我们开始工作并进行提交,其中有一个小错误:

... edit ...
git add frotz.c
git commit

假设这是提交 a123456(稍后我们将通过 git log 找到哈希 ID,或者我们将像您在示例中所做的那样使用 HEAD~10;我只是想在这里放些具体的东西。

我们做了更多的提交:

... edit and commit repeatedly ...

然后发现错误。我们暂时修复 错误,做出我们需要做出的承诺:

git commit

然后我们修正错误,git add,并使用git commit --fixup:

... edit frotz.c to fix the mistake ...
git add frotz.c
git commit --fixup a123456   # or git commit --fixup HEAD~10

--fixup 选项指示 git commit 使用 specially-formatted 提交消息

现在我们有了修复提交,我们 运行:

git rebase -i --autosquash main

(因为 topic 是基于 main;在这里使用你需要的任何东西)。带有所有 pick 命令的表单弹出,但是当我们仔细观察它时,我们发现其中一行没有说 pick,而是说 fixup:

pick a123456   commit subject line
fixup b789abc  fixup! commit subject line
pick 9876543   another commit subject
... and so on ...

写出这组命令(或者不打扰,因为我们不需要改变它们)并退出编辑器会启动实际的 rebase,它...吸收修复提交 into 糟糕的 提交,所以它现在只是一个提交。

fixup 命令基本上告诉 Git:将此提交压缩到上一个提交中,同时完全删除此提交的日志消息。 使用 squash 而不是 fixup 告诉 Git: 将这个提交压缩到前一个,但停下来给我一个机会写一条新的日志消息,向我展示两个现有的日志消息. 这些实际上是相同的 除了 有机会编辑提交消息。

因为你没有提到要修复提交消息,所以我们在这里使用 --fixup。要自动获取“挤压”命令,请使用 git commit --squash。在这两种情况下,git commit 安排未来 git rebase --autosquash 看到一条消息,告诉 rebase 重新排列 pick 命令的顺序,并根据需要将第二个更改为 squash 或 fixup.

与往常一样,您也可以re-order and/or 手动修改说明。 (我通常这样做而不是使用 git commit --fixup,因为我经常想做很多提交消息重写,并考虑要合并哪些提交以及将它们放入的顺序。)