mirror of
https://github.com/git/git
synced 2024-08-27 19:49:21 +00:00
![Elijah Newren](/assets/img/avatar_default.png)
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>
86 lines
1.6 KiB
Bash
86 lines
1.6 KiB
Bash
# This shell script fragment is sourced by git-rebase to implement
|
|
# its default, fast, patch-based, non-interactive mode.
|
|
#
|
|
# Copyright (c) 2010 Junio C Hamano.
|
|
#
|
|
|
|
git_rebase__am () {
|
|
|
|
case "$action" in
|
|
continue)
|
|
git am --resolved --resolvemsg="$resolvemsg" \
|
|
${gpg_sign_opt:+"$gpg_sign_opt"} &&
|
|
move_to_original_branch
|
|
return
|
|
;;
|
|
skip)
|
|
git am --skip --resolvemsg="$resolvemsg" &&
|
|
move_to_original_branch
|
|
return
|
|
;;
|
|
show-current-patch)
|
|
exec git am --show-current-patch
|
|
;;
|
|
esac
|
|
|
|
if test -z "$rebase_root"
|
|
# this is now equivalent to ! -z "$upstream"
|
|
then
|
|
revisions=$upstream...$orig_head
|
|
else
|
|
revisions=$onto...$orig_head
|
|
fi
|
|
|
|
ret=0
|
|
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 --topo-order \
|
|
$git_format_patch_opt \
|
|
"$revisions" ${restrict_revision+^$restrict_revision} \
|
|
>"$GIT_DIR/rebased-patches"
|
|
ret=$?
|
|
|
|
if test 0 != $ret
|
|
then
|
|
rm -f "$GIT_DIR/rebased-patches"
|
|
case "$head_name" in
|
|
refs/heads/*)
|
|
git checkout -q "$head_name"
|
|
;;
|
|
*)
|
|
git checkout -q "$orig_head"
|
|
;;
|
|
esac
|
|
|
|
cat >&2 <<-EOF
|
|
|
|
git encountered an error while preparing the patches to replay
|
|
these revisions:
|
|
|
|
$revisions
|
|
|
|
As a result, git cannot rebase them.
|
|
EOF
|
|
return $ret
|
|
fi
|
|
|
|
git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
|
|
--patch-format=mboxrd \
|
|
$allow_rerere_autoupdate \
|
|
${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"
|
|
ret=$?
|
|
|
|
rm -f "$GIT_DIR/rebased-patches"
|
|
|
|
if test 0 != $ret
|
|
then
|
|
test -d "$state_dir" && write_basic_state
|
|
return $ret
|
|
fi
|
|
|
|
move_to_original_branch
|
|
|
|
}
|