Ada*_*tan 4 git rebase merge-conflict-resolution
我一直在开发 git 存储库。在发布我的更改之前,我想删除一些提交 - a023b43、315424b和7b51754- 因为它们不反映任何有意义的更改。唯一重要的时间点是第一个 ( 70f72ca) 和最后一个 (6937ddd ) 提交。
git rebase -i 4c802c1
Run Code Online (Sandbox Code Playgroud)
我选择了:
pick 70f72ca Remove repetitions from Makefile
d a023b43 Separate target for image conversion
d 315424b Remove image conversion (#1)
d 7b51754 Fix Makefile
pick 6937ddd CV 2019.01
Run Code Online (Sandbox Code Playgroud)
最终目标是拥有如下所示的 git 日志:
6937ddd CV 2019.01
4c802c1 Initial commit
Run Code Online (Sandbox Code Playgroud)
Auto-merging src/Adam_Matan.tex
CONFLICT (content): Merge conflict in src/Adam_Matan.tex
error: could not apply 6937ddd... CV 2019.01
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".
Could not apply 6937ddd... CV 2019.01
Run Code Online (Sandbox Code Playgroud)
据我了解,这两次提交只是我的工作目录的快照。我想要两个快照 - 原始提交和一个CV 2019.01。我不想以任何方式合并或组合它们。为什么我收到合并冲突消息?
如何从分支中删除所有中间提交,并仅保留第一个和最后一个提交?
挤压也会产生合并冲突:
git rebase -i 4c802c1
Auto-merging Makefile
CONFLICT (content): Merge conflict in Makefile
error: could not apply 315424b... Remove image conversion (#1)
Run Code Online (Sandbox Code Playgroud)
变基通过进行一系列提交并重新应用它们来起作用,可能是在不同的“基础”对象上。它可以通过为每个提交创建补丁并重新应用它们,或者按顺序挑选它们来实现。
无论采用何种机制,通过从变基指令列表中删除提交,您都要求不包含这些更改。
想象一下,如果您有一些文件,并且在其初始版本中,它只有一行内容one。想象一下,在下一次提交中,您更改one为two. 在随后的提交中,two到three. 然后three到four,最后four到five。所以你现在有五个提交,每个提交都更改了这一行。
想象一下,在每次提交中,您都给了它一条指示内容更改的消息,并且提交 ID(哈希)神奇地也反映了内容。运行rebase -i --root会给你这个脚本:
pick 1111111 add one
pick 2222222 change one to two
pick 3333333 change two to three
pick 4444444 change three to four
pick 5555555 change four to five
Run Code Online (Sandbox Code Playgroud)
换句话说,第一次提交选择了从无到 的更改one。第二条指令将优先选择从one到 的更改,依此类推,直到最后一条指令优先选择从到 的two更改。fourfive
如果删除其中一些行,则会出现:
pick 1111111 add one
pick 5555555 change four to five
Run Code Online (Sandbox Code Playgroud)
您将有两个精选。第一个将添加一个包含内容的文件one。第二个将尝试将这些内容从 更改four为five。
唉,那些内容都不是 four。因此,你们之间有冲突。
如果您的目标是从 到one没有five中间提交,那么您需要squash它们或将它们标记为fixup提交。
pick 1111111 add one
pick 2222222 change one to two
squash 3333333 change two to three
squash 4444444 change three to four
squash 5555555 change four to five
Run Code Online (Sandbox Code Playgroud)
在这种情况下,将优先选择第一个更改,因此one将创建该文件。后续更改将被挑选,因此内容将从 更改one为two。随后的更改将被精心挑选,进一步更新文件,但这些更改将被“压缩”到之前的提交中。因此,您将获得完整的内容,但最终只会得到两次提交。
(如果您将它们标记为fixup提交,您将获得相同的内容,但它们的提交消息不会包含在您建议的提交消息中。
问题在于git rebase使用了相互矛盾的术语来描述 git 作为一个整体如何定义提交。提交是一个快照,但rebase将提交视为其父提交与其自身之间的补丁(一组更改)。
因此,如果您告诉rebase“删除提交”,它会认为您想要撤消该提交补丁应用的更改。
如果您想删除一些快照,同时保持以后的快照相同,您可以告诉rebase提交squash。用rebase术语来说,这意味着您要将多个提交的更改合并到最新的提交中。