为什么 rebase 不会提取我之前的 8 次提交?

Why won't rebase pull up my previous 8 commits?

我按照 stack overflow question 中的说明执行了交互式 rebase,但是交互式 rebase 会话并没有提取我之前的所有 8 个提交(回购的历史只有 8 个提交) .

这是我当前的提交历史:

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git log --oneline
80b0645 (HEAD -> master, origin/master) Applied Bill's changes. Resolve merge conflict.
cdfcbf1 Modified line 1.
073e94b Modified line in newmodule.py
d39ae96 Added newmodule.py
118a892 deleted newmodule.txt
81c7945 Changed newmodule.txt added Hello World!
add5483 Minh added newmodule.txt
386249b First commit.

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~8
fatal: invalid upstream 'HEAD~~8'

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~7
fatal: invalid upstream 'HEAD~~7'

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~6
fatal: invalid upstream 'HEAD~~6'

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~5

它适用于 HEAD~5,这就是我在互动会话中看到的全部内容。

pick add5483 Minh added newmodule.txt
pick 81c7945 Changed newmodule.txt added Hello World!
pick 118a892 deleted newmodule.txt
pick d39ae96 Added newmodule.py
pick cdfcbf1 Modified line 1.
pick 073e94b Modified line in newmodule.py

# Rebase 386249b..80b0645 onto d39ae96 (6 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# ... 

我想将我的存储库的状态恢复到第一次提交后的状态 (386249b),但如您所见,我没有看到我最近的提交 (80b0645).我尝试了 dropping 提交:

d add5483 Minh added newmodule.txt
d 81c7945 Changed newmodule.txt added Hello World!
d 118a892 deleted newmodule.txt
d d39ae96 Added newmodule.py
d cdfcbf1 Modified line 1.
d 073e94b Modified line in newmodule.py

这似乎已经完成了工作(在重新设置我的提交历史之后看起来像这样):

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git log --oneline
386249b (HEAD -> master) First commit.

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$

所以我想知道:

  1. 为什么提交 80b0645 未包含在计数中?
  2. Why/if 变基应该显示我的第一次提交 (386249b)?
  3. 为什么 git rebase -i HEAD~5 有效(以及 5 指的是什么)?

根据 运行 git log --all --decorate --oneline --graph 的建议:

$ git log --all --decorate --oneline --graph
*   80b0645 (HEAD -> master, origin/master, origin/HEAD) Applied Bill's changes. Resolve merge conflict.
|\
| * 073e94b Modified line in newmodule.py
* | cdfcbf1 Modified line 1.
|/
* d39ae96 Added newmodule.py
* 118a892 deleted newmodule.txt
* 81c7945 Changed newmodule.txt added Hello World!
* add5483 Minh added newmodule.txt
* 386249b First commit.

1 因为 HEAD~~5 恰好是 那个 修订版,所以不包括在内。

2 它可以...如果您使用 --root

3 因为您的分支中有 8 个修订.... HEAD 总是 您所站的位置....然后您使用 ~~5 转换为6 revisons back.

git log --oneline 非常有用,但不会向您显示合并提交。

如果您添加 --graph 选项,我猜您会看到类似 :

的内容
$ git log --oneline --graph
* 80b0645 (HEAD -> master, origin/master) Applied Bill's changes. Resolve merge conflict.
|\
| * cdfcbf1 Modified line 1.
* | 073e94b Modified line in newmodule.py
|/
* d39ae96 Added newmodule.py
* 118a892 deleted newmodule.txt
* 81c7945 Changed newmodule.txt added Hello World!
* add5483 Minh added newmodule.txt
* 386249b First commit.

回答您的问题:

  1. git rebase 将删除合并提交,并创建一个线性提交序列;如果您需要保留它们,您可以尝试 git rebase --rebase-merges (link to docs)

我会在 2 之前回答 3。:

  1. 你实际上写了 HEAD~~5(注意额外的 ~),它翻译成“6 次提交前”(或 HEAD~6

HEAD~6的意思是“从头开始,跟着'first parent'link的6次”;
如果您看上面的图表:cdfcbf1 是“旁路”(它是 80b0645second parent)。

因此:从 master 上升 6 次提交会将您带到“第一次提交”

至于2:

  1. git rebase -i HEAD~6 将重播从 HEAD~6HEAD~6 开始的提交 不包括

假设您想要包含从 118a892 deleted newmodule.txt 开始的提交:
你会写 git rebase -i 81c7945 (或等效地 git rebase -i 118a892~ :第一个 parent of 118a892)

对于历史上的第一个提交,您不能写 386249b~,因为该提交没有 parent ;
如果你想重播提交 包括 历史上的第一个提交,有一个特殊的 --root 选项:

git rebase -i --root

[edit] 说明如何计算 ~ :

HEAD   * 80b0645 (HEAD -> master, origin/master) Applied Bill's changes ...
       |\
       | * cdfcbf1 Modified line 1.
HEAD~  * | 073e94b Modified line in newmodule.py
       |/
HEAD~2 * d39ae96 Added newmodule.py
HEAD~3 * 118a892 deleted newmodule.txt
HEAD~4 * 81c7945 Changed newmodule.txt added Hello World!
HEAD~5 * add5483 Minh added newmodule.txt
HEAD~6 * 386249b First commit.