如何在分支的第一个(根)提交上使用交互式变基?

How to use interactive rebase on the first (root) commit of a branch?

如果我遇到以下情况,

$ git log --oneline
* abcdef commit #b
* 123456 commit #a

我知道我总能运行

$ git reset HEAD~ 
$ git commit --amend

但是,我尝试 运行

$ git rebase -i HEAD~2

但我得到了

fatal: Needed a single revision
invalid upstream HEAD~2

因此我的问题是:有没有办法使用 git rebase 压缩这两个提交?

看来这个参数可能有帮助:

--root 

Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a branch.

这应该可以让你压缩(我猜你真的想修复)你的第二次提交到第一个:

git rebase --root -i

注意理解 --root 选项的作用,因为在你的情况下它满足了你的需求,但在分支中使用时可能会很棘手,因为它会变基到历史上最远的祖先可达(即树的根);所以 rebase --root 将在 aA-B-D-E-X-Y-Z:

上变基 z
master      A-B-C
               \
upstream        D-E  
                   \     
current branch      X-Y-Z

您想变基到 master 分支的根提交。更具体地说,要压缩这两个提交,您需要 运行

git rebase -i --root

然后在弹出的编辑器缓冲区的第二行用squash代替pick

pick 123456 a                                                        
squash abcdef b

我建议您参阅 git-rebase man page 以了解有关该标志的更多详细信息:

--root

Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a branch. [...]

根的交互式变基示例

# Set things up
$ mkdir testgit
$ cd testgit
$ git init

# Make two commits
$ touch README
$ git add README
$ git commit -m "add README"
$ printf "foo\n" > README
$ git commit -am "write 'foo' in README"

# Inspect the log
$ git log --oneline --decorate --graph
* 815b6ca (HEAD -> master) write 'foo' in README
* 630ede6 add README

# Rebase (interactively) the root of the current branch: 
# - Substitute 'squash' for 'pick' on the second line; save and quit the editor.
# - Then write the commit message of the resulting commit; save and quit the editor.
$ git rebase -i --root
[detached HEAD c9003cd] add README; write 'foo' in README
 Date: Sat May 16 17:38:43 2015 +0100
 1 file changed, 1 insertion(+)
 create mode 100644 README
Successfully rebased and updated refs/heads/master.

# Inspect the log again
$ git log --oneline --decorate --graph
* c9003cd (HEAD -> master) add README; write 'foo' in README

我来到这个问题是为了寻找标题的答案。在一个非常大的 repo 上,接受的答案会为主分支(又名:master)中的每个提交生成一个交互式 rebase,而不是给定分支的 just。对于来到这里的其他人,替代方法是使用 parent 分支名称(或提交):

git rebase -i <base_branch_name>

我在深入研究 git 文档并找到这个 (https://git-scm.com/docs/git-rebase#_interactive_mode) 后意识到了这一点:

Start it with the last commit you want to retain as-is:

git rebase -i <after-this-commit>

An editor will be fired up with all the commits in your current branch (ignoring merge commits), which come after the given commit.

假设您有 branch_a 从 master 分支出来,并且您想要以交互方式对 branch_a 上的所有提交进行变基。为此,您可以:

git rebase -i master

或者,如果您想从中间开始(或在任何提交时),您可以这样做:

git rebase -i <some-commit-hash-in-the-middle>

另一个常见的形式是如果你知道 "I want to rebase back 5 commits from where I am now"

git rebase -i HEAD~5

希望这可以帮助其他人在 git rebase 打开一个包含数千行提交的编辑器时避免心脏病发作。 ─=≡Σ(((つ><)つ