Re: [PATCH] rebase: be cleverer with rebased upstream branches
- From
- Santi Béjar <santi@agolina.net>
- Date
- Feb 16, 2011, 13:22 UTC
- Message-ID
- <AANLkTinsvfXjVhJfLDeZ+g4skev6bBmJgByyxXW7eO39@mail.gmail.com>
- In-Reply-To
- <AANLkTinmxbYLB-K+VzY50NtOAPwd-q3WwAosAHqKRq_0@mail.gmail.com>
On Wed, Feb 16, 2011 at 1:10 PM, Santi Béjar <santi@agolina.net> wrote:
Show 60 quoted lines
> On Wed, Feb 16, 2011 at 3:03 AM, Martin von Zweigbergk
> <martin.von.zweigbergk@gmail.com> wrote:
>> On Tue, 15 Feb 2011, Junio C Hamano wrote:
>>
>>> Would bisection help to avoid the cost?
>>
>> I don't think the straight-forward use of bisection would work. If the
>> history looks something like below, where 'b' is the branch to rebase
>> and 'u' is the upstream, we have to go through each entry in the
>> reflog to find u@{3}.
>>
>>
>> .-u@{0}
>> /
>> .---u@{1}
>> /
>> x---y-----u@{2}
>> \
>> .---u@{3}---b
>> \
>> .-u@{4}
>>
>>
>> I have an idea inspired by bisection, Thomas's exponential stride, and
>> what someone (you?) mentioned the other day about virtual merge
>> commits. I haven't tried it out, but let me know what you think. I'll
>> try to explain it using an example only:
>>
>> Exponential stride phase:
>> 1. candidates={ u@{0} }
>> merge-base b $candidates -> y, _not_ in $candidates
>> 2. candidates={ u@{1} u@{2} }
>> merge-base b $candidates -> y, _not_ in $candidates
>> 3. candidates={ u@{3} u@{4} u@{5} u@{6} }
>> merge-base b $candidates -> u@{3}, in $candidates
>
> Doesn't it indicate that u@{3} is the commit we are looking for? I
> haven't found a counterexample...
>
> If this is true the following patch can implement it for git-pull.sh and
> git-rebase.sh (sorry if it is space damaged):
>
> diff --git i/git-pull.sh w/git-pull.sh
> index 2cdea26..09ef0a9 100755
> --- i/git-pull.sh
> +++ w/git-pull.sh
> @@ -189,14 +189,7 @@ test true = "$rebase" && {
> . git-parse-remote &&
> remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
> oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
> - for reflog in $(git rev-list -g $remoteref 2>/dev/null)
> - do
> - if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
> - then
> - oldremoteref="$reflog"
> - break
> - fi
> - done
> + oldremoteref=$(git merge-base $curr_branch $oldremoteref $(git
> rev-list -g $remoteref 2>/dev/null))One thing I forgot to say is that it seems to perform quite well:
Hot cache:
$ git rev-list -g origin/next | wc -l 36 $ git rev-list -g origin/master | wc -l 52 $ time git merge-base $(git rev-list -g origin/next) 3b781df0a25d5ba23bd2603b0e3e9bb4731369df
real 0m0.155s user 0m0.064s sys 0m0.044s $ time git merge-base $(git rev-list -g origin/master) 7811d9600f02e70c9f835719c71156c967a684f7
real 0m0.161s user 0m0.064s sys 0m0.040s $ time git merge-base $(git rev-list -g origin/master origin/master) 7811d9600f02e70c9f835719c71156c967a684f7
real 0m0.175s user 0m0.076s sys 0m0.036s
Cold-cache around 1 second. And it's not linear with the number of reflog entries, but with the number of independent branches, I suppose.
HTH, Santi
P.D.: Attached is the patch, in case someone wants to try it.