Reputation: 4940
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.
Upvotes: 3
Views: 3791
Reputation: 487725
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 multiple back-ends, not just git am
. These can create or copy empty commits. Depending on your particular Git version, you may need to supply the -k
flag to git rebase
to get rebase to deliberately create such commits. If your version of Git uses git am
as a default back-end, git rebase -k
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).
Git version 2.26 and later use a merge-based back end by default, and do not require the -k
flag to keep empty commits. Using -k
now means keep commits that become empty rather than keep commits that are initially empty.
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.
Upvotes: 7
Reputation: 21908
Your last schema is an impossible state. (Or ar least, it was, but now you edited your question so it's not apparent any more)
A
has E
for its parent and this cannot change ever. If it did, then A
would not be A
any more, since a commit is the hashed result of (contents + metadata).
That's the reason A'
is used here, by the way.
But to answer the title question, skipping these commits is a way to avoid verbose histories with (potentially, depending on workflows, of course) lots of empty commits.
Upvotes: 1
Reputation: 30156
First, it would not be A.... it would be A''.... but the real 'problem' is that the revision would be empty because those changes would be already applied on A'. But you can keep it in history, if so you want.
Upvotes: 1