History Simplification
重现的repository在这里 https://github.com/ChuckTest/git-history-test
具体的讨论,参考这个,https://groups.google.com/g/git-users/c/n8Rj-YBUJEw
A more detailed explanation follows.
Suppose you specified foo
as the <paths>. We shall call commits that modify foo
!TREESAME, and the rest TREESAME. (In a diff filtered for foo
, they look different and equal, respectively.)只有修改了foo,才算是!TREESAME,其他的都算做TREESAME,比如修改了其他文件但是没有修改foo
In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file foo
in this commit graph:
.-A---M---N---O---P---Q
/ / / / / /
I B C D E Y
\ / / / / /
`-------------' X
The horizontal line of history A---Q is taken to be the first parent of each merge. The commits are:
-
I
is the initial commit, in whichfoo
exists with contents “asdf”, and a filequux
exists with contents “quux”. Initial commits are compared to an empty tree, soI
is !TREESAME. -
In
A
,foo
contains just “foo”. -
B
contains the same change asA
. Its mergeM
is trivial and hence TREESAME to all parents. M有两个parent,分别是A和B,但是相对A和B而言,从文件内容来看,是没有差异的 -
C
does not changefoo
【这里是提交了一个空的commit】, but its mergeN
changes it to “foobar”, so it is not TREESAME to any parent. -
D
setsfoo
to “baz”. Its mergeO
combines the strings fromN
andD
to “foobarbaz”; i.e., it is not TREESAME to any parent. -
E
changesquux
to “xyzzy”, and its mergeP
combines the strings to “quux xyzzy”.P
is TREESAME【这里的tree same是说没有修改foo文件】 toO
, but not toE
. -
X
is an independent root commit that added a new fileside
, andY
modified it.Y
is TREESAME toX
. Its mergeQ
addedside
toP
, andQ
is TREESAME toP
, but not toY
.
rev-list
walks backwards through history, including or excluding commits based on whether --full-history
and/or parent rewriting (via --parents
or --children
) are used. The following settings are available.
整体效果如图所示
Commits are included if they are not TREESAME to any parent (though this can be changed, see --sparse
below). If the commit was a merge, and it was TREESAME to one parent, follow only that parent. (Even if there are several TREESAME parents, follow only one of them.) Otherwise, follow all parents.
This results in:
.-A---N---O
/ / /
I---------D
默认的模式下,只看foo的日志的话。会自动过滤掉TREESAME的commit。
通过搜索foo来查看的话,会发现BPQ这三个commit中也包含了foo文件,但是针对foo文件来讲,它们都是TREESAME to parent.
git log --decorate --oneline --graph foo
git log --oneline foo
git log --oneline --graph foo
Note how the rule to only follow the TREESAME parent, if one is available, removed B
from consideration entirely. C
was considered via N
, but is TREESAME. Root commits are compared to an empty tree, so I
is !TREESAME.
Parent/child relations are only visible with --parents
, but that does not affect the commits selected in default mode, so we have shown the parent lines.
--full-history without parent rewriting 【--graph的作用是,启用parent rewriting】
This mode differs from the default in one point: always follow all parents of a merge, even if it is TREESAME to one of them. Even if more than one side of the merge has commits that are included, this does not imply that the merge itself is! In the example, we get
git log --oneline --full-history foo
I A B N D O P Q
M
was excluded because it is TREESAME to both parents. E
, C
and B
were all walked, but only B
was !TREESAME, so the others do not appear.
Note that without parent rewriting, it is not really possible to talk about the parent/child relationships between the commits, so we show them disconnected.
--full-history with parent rewriting
Ordinary commits are only included if they are !TREESAME (though this can be changed, see --sparse
below).
Merges are always included. However, their parent list is rewritten: Along each parent, prune away commits that are not included themselves. This results in
git log --decorate --oneline --graph --full-history foo
.-A---M---N---O---P---Q
/ / / / /
I B / D /
\ / / / /
`-------------'
Compare to --full-history
without rewriting above. Note that E
was pruned away because it is TREESAME, but the parent list of P was rewritten to contain E
's parent I
. The same happened for C
and N
, and X
, Y
and Q
.