git 变基到同一个分支时怎么会发生合并冲突?

How can there be a merge conflict when git rebasing onto an the same branch?

来自 git 的 the documentation 变基:

The current branch is reset to , or if the --onto option was supplied. This has the exact same effect as git reset --hard (or ). ORIG_HEAD is set to point at the tip of the branch before the reset.

The commits that were previously saved into the temporary area are then reapplied to the current branch, one by one, in order. Note that any commits in HEAD which introduce the same textual changes as a commit in HEAD.. are omitted (i.e., a patch already accepted upstream with a different commit message or timestamp will be skipped).

然后是重要的一点:

It is possible that a merge failure will prevent this process from being completely automatic

我知道一般情况下是如何发生的,但我有一个案例,它似乎发生得很奇怪。

这是我的命令:

407  07/09/18 16:53:09 cd temp
  408  07/09/18 16:53:16 git clone https://github.com/joereddington/todo.txt
  410  07/09/18 16:53:35 cd todo.txt/
  412  07/09/18 16:53:41 git rebase HEAD~20

我觉得这不可能失败。我的理解是顺序是:

但是我得到一个错误:

Applying: update Using index info to reconstruct a base tree... M   todo.txt .git/rebase-apply/patch:21: trailing whitespace. (A) Apply for gift aid number  .git/rebase-apply/patch:30: trailing whitespace. (C) Sort all the 'to sort' spending in the right categories in the expenditure against grant file.  .git/rebase-apply/patch:76: trailing whitespace. (E) Go thought calendar and find at least one 'thank you's you *can* make  warning: 3 lines add whitespace errors. Falling back to patching base and 3-way merge... Auto-merging todo.txt CONFLICT (content): Merge conflict in todo.txt error: Failed to merge in the changes. Patch failed at 0025 update The copy of the patch that failed is found in: .git/rebase-apply/patch

Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort".

Josephs-Mini:todo.txt josephreddington$

怎么会这样?它拒绝对已经执行过相同更改的内容执行提交!

这个问题是基于对版本控制系统的过时理解。

CVS 和 SVN 等系统将提交存储为增量 - 提交实际上是与先前版本的差异列表。如果 git 以相同的方式工作,那么这种变基将完全没有错误是有道理的。

Git 不是这样的(有 some delta compression under the hood)。 Git 存储文件每次的外观快照。这意味着如果在变基中有任何合并,那么它不知道如何处理它们 - 当变基合并时 git 有三个不同的文件系统要比较并需要一些指导(在这种情况下启发式'make it look exactly like the next link in the chain' 会很好,但这是一个边缘情况)。

为了解决所提供的示例,开关“--preserve-merges”解决了这个问题。