rebase: define linearization ordering and enforce it

Ever since commit 3f213981e4 ("add tests for rebasing merged history",
2013-06-06), t3425 has had tests which included the rebasing of merged
history and whose order of applied commits was checked.  Unfortunately,
the tests expected different behavior depending on which backend was in
use.  Implementing these checks was the following four lines (including
the TODO message) which were repeated verbatim three times in t3425:

    #TODO: make order consistent across all flavors of rebase
    test_run_rebase success 'e n o' ''
    test_run_rebase success 'e n o' -m
    test_run_rebase success 'n o e' -i

As part of the effort to reduce differences between the rebase backends
so that users get more uniform behavior, let's define the correct
behavior and modify the different backends so they all get the right
answer.  It turns out that the difference in behavior here is entirely
due to topological sorting; since some backends require topological
sorting (particularly when --rebase-merges is specified), require it for
all modes.  Modify the am and merge backends to implement this.

Performance Considerations:

I was unable to measure any appreciable performance difference with this
change.  Trying to control the run-to-run variation was difficult; I
eventually found a headless beefy box that I could ssh into, which
seemed to help.  Using git.git, I ran the following testcase:
    $ git reset --hard v2.20.0-rc1~2
    $ time git rebase --quiet v2.20.0-rc0~16

I first ran once to warm any disk caches, then ran five subsequent runs
and recorded the times of those five.  I observed the following results
for the average time:

     Before this change:
       "real" timing: 1.340s (standard deviation: 0.040s)
       "user" timing: 1.050s (standard deviation: 0.041s)
       "sys"  timing: 0.270s (standard deviation: 0.011s)
     After  this change:
       "real" timing: 1.327s (standard deviation: 0.065s)
       "user" timing: 1.031s (standard deviation: 0.061s)
       "sys"  timing: 0.280s (standard deviation: 0.014s)

Measurements aside, I would expect the timing for walking revisions to
be dwarfed by the work involved in creating and applying patches, so
this isn't too surprising.  Further, while somewhat counter-intuitive,
it is possible that turning on topological sorting is actually a
performance improvement: by way of comparison, turning on --topo-order
made fast-export faster (see
https://public-inbox.org/git/20090211135640.GA19600@coredump.intra.peff.net/).

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Elijah Newren 2018-12-11 08:11:38 -08:00 committed by Junio C Hamano
parent 7b76ac664c
commit c91c944a06
3 changed files with 8 additions and 11 deletions

View File

@ -36,7 +36,7 @@ rm -f "$GIT_DIR/rebased-patches"
git format-patch -k --stdout --full-index --cherry-pick --right-only \
--src-prefix=a/ --dst-prefix=b/ --no-renames --no-cover-letter \
--pretty=mboxrd \
--pretty=mboxrd --topo-order \
$git_format_patch_opt \
"$revisions" ${restrict_revision+^$restrict_revision} \
>"$GIT_DIR/rebased-patches"

View File

@ -143,7 +143,7 @@ write_basic_state
rm -f "$(git rev-parse --git-path REBASE_HEAD)"
msgnum=0
for cmt in $(git rev-list --reverse --no-merges "$revisions")
for cmt in $(git rev-list --topo-order --reverse --no-merges "$revisions")
do
msgnum=$(($msgnum + 1))
echo "$cmt" > "$state_dir/cmt.$msgnum"

View File

@ -70,9 +70,8 @@ test_run_rebase () {
test_linear_range "\'"$expected"\'" d..
"
}
#TODO: make order consistent across all flavors of rebase
test_run_rebase success 'e n o' ''
test_run_rebase success 'e n o' -m
test_run_rebase success 'n o e' ''
test_run_rebase success 'n o e' -m
test_run_rebase success 'n o e' -i
test_run_rebase () {
@ -87,9 +86,8 @@ test_run_rebase () {
test_linear_range "\'"$expected"\'" c..
"
}
#TODO: make order consistent across all flavors of rebase
test_run_rebase success 'd e n o' ''
test_run_rebase success 'd e n o' -m
test_run_rebase success 'd n o e' ''
test_run_rebase success 'd n o e' -m
test_run_rebase success 'd n o e' -i
test_run_rebase () {
@ -104,9 +102,8 @@ test_run_rebase () {
test_linear_range "\'"$expected"\'" c..
"
}
#TODO: make order consistent across all flavors of rebase
test_run_rebase success 'd e n o' ''
test_run_rebase success 'd e n o' -m
test_run_rebase success 'd n o e' ''
test_run_rebase success 'd n o e' -m
test_run_rebase success 'd n o e' -i
if ! test_have_prereq REBASE_P; then