git rebase跳过相同的提交 [英] Git rebase skipping identical commits

查看:123
本文介绍了git rebase跳过相同的提交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 git rebase doc

如果上游分支已经包含您所做的更改(例如,因为您邮寄了在上游应用的补丁程序),那么提交将被跳过.例如,在以下历史记录(其中A'和A引入了相同的一组更改,但提交者信息不同):

  A --- B --- C主题/D --- E --- A'-F主 

将导致:

  B'--- C'主题/D --- E --- A'-F主 

我无法理解的是,此优化需要什么?如果git会像这样重新定位:

  A''---- B'--- C'主题/D --- E --- A'-F主 

可能出了什么问题?(A = A'= A'')

编辑:为了更加清楚自己,让我们说 F 还原 A'的更改.现在,rebase将不会在 F 上应用 A 补丁,而仅在 B' C'上应用补丁.在这种情况下,git rebase行为可能出乎意料,对我而言这没有任何意义.

解决方案

有可能具有连续的提交来存储相同的源树.这就是您将要得到的,因为 A''不会对 F 进行任何更改-这些更改已经在 in F ;从 E F 的差异包括相同的变化,这是由于从 E A'的差异.

换句话说, A''中的快照与 F 中的快照相同.Git将这种提交对称为 empty commit::也就是说,如果父项与子项匹配,并且该子项不是合并提交,则Git表示该子项提交为空"(即使它仍然具有完整的快照). git commit 命令需要标志-allow-empty 进行此类提交.

此外, A''中的提交消息可能与 A'中的提交消息相同.如果是这样, A''在所有有用的方式中都是多余的.消除它可能是最好的方法.

请注意, git rebase 最初是使用 git format-patch 实现的,它将每个提交与它的父 1 进行比较使补丁可以通过电子邮件发送的其他文本.单独的程序 git am 读取邮箱格式"文件(通过电子邮件发送的序列)并应用补丁,并使用其他文本来复制提交作者,作者日期和日志消息.但是,format-patch和 git am 拒绝使用空补丁.因此,rebase的初始版本使用这两个程序来实现提交复制,必须删除这些空"的提交.

现代的 git rebase 具有其他后端,而不仅仅是 git am .这些可以创建或复制空的提交.您必须向 git rebase 提供 -k 标志,以获取重新创建基准以故意创建此类提交,并且 -k 标志强制rebase使用交互式或合并后端,而不是 git am 后端(当然还会修改其初始设置,以告诉它不要自动删除空"提交).

您还可以使用单个 git cherry-pick 命令或使用音序器进行大批量的Cherry-picking来手动进行变基.像重新设置一样,cherry-pick默认情况下拒绝复制空"提交,要求-allow-empty 和/或-keep-redundant-commits 标志保留这样的提交.


1 git format-patch 根本无法格式化合并提交,因为它们具有多个父提交.

According to git rebase doc

If the upstream branch already contains a change you have made (e.g., because you mailed a patch which was applied upstream), then that commit will be skipped. For example, running git rebase master on the following history (in which A' and A introduce the same set of changes, but have different committer information):

      A---B---C topic
     /
D---E---A'---F master 

will result in:

               B'---C' topic
              /
D---E---A'---F master

What I am not able to understand is what is the need of this optimisation ? If git would have rebased like :

               A''---- B'---C' topic
              /
D---E---A'---F master

what could have gone wrong ? (A = A' = A'')

EDIT : To make myself more clear, Let us say F reverts changes of A'. Now rebase will not apply A patch on F and just B' and C'. In such a case, git rebase behaviour might be unexpected and to me it does not make sense.

解决方案

It is possible to have successive commits that store the same source tree. That's what you would get here, because A'' would introduce no changes to F—those changes are already in F; the diff from E to F includes the same changes due to the diff from E to A'.

In other words, the snapshot in A'' would be the same as the snapshot in F. Git calls this kind of commit pair an empty commit: that is, if the parent matches the child, and the child is not a merge commit, Git says that the child commit is "empty" (even though it still has a full snapshot). The git commit command requires the flag --allow-empty to make such a commit.

Moreover, the commit message in A'' would likely be the same as the commit message in A'. If so, A'' is in all useful ways redundant. Eliminating it is probably the best course of action.

Note that git rebase was originally implemented using git format-patch, which turns each commit into a diff against its parent,1 with additional text to make the patch email-send-able. A separate program, git am, reads "mailbox format" files (sequences of emailed messages) and applies the patch, using the additional text to reproduce the commit author, author-date, and log message. However, format-patch and git am refuse to work with an empty patch. So the initial version of rebase, which used these two programs to achieve the commit copying, had to drop these "empty" commits.

Modern git rebase has additional back-ends, not just git am. These can create or copy empty commits. You must supply the -k flag to git rebase to get rebase to deliberately create such commits, and the -k flag forces rebase to use the interactive or merge back-end, rather than the git am back end (and of course also modifies its initial setup to tell it not to drop "empty" commits automatically).

You can also do your rebase manually, using individual git cherry-pick commands or en-masse cherry-picking using the sequencer. Like rebase, cherry-pick refuses to copy "empty" commits by default, requiring the --allow-empty and/or --keep-redundant-commits flags to keep such commits.


1git format-patch cannot format merge commits at all, as they have more than one parent.

这篇关于git rebase跳过相同的提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆