rebase: use @{upstream} if no upstream specified

'git rebase' without arguments is currently not supported. Make it
default to 'git rebase @{upstream}'. That is also what 'git pull
[--rebase]' defaults to, so it only makes sense that 'git rebase'
defaults to the same thing.

Defaulting to @{upstream} will make it possible to run e.g. 'git
rebase -i' without arguments, which is probably a quite common use
case. It also improves the scenario where you have multiple branches
that rebase against a remote-tracking branch, where you currently have
to choose between the extra network delay of 'git pull' or the
slightly awkward keys to enter 'git rebase @{u}'.

The error reporting when no upstream is configured for the current
branch or when no branch is checked out is reused from git-pull.sh. A
function is extracted into git-parse-remote.sh for this purpose.

Helped-by: Yann Dirson <ydirson@altern.org>
Helped-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Martin von Zweigbergk 2011-02-09 20:54:02 -05:00 committed by Junio C Hamano
parent c71f8f3d50
commit 15a147e618
6 changed files with 85 additions and 46 deletions

View file

@ -646,7 +646,7 @@ branch.<name>.remote::
branch.<name>.merge::
Defines, together with branch.<name>.remote, the upstream branch
for the given branch. It tells 'git fetch'/'git pull' which
for the given branch. It tells 'git fetch'/'git pull'/'git rebase' which
branch to merge and can also affect 'git push' (see push.default).
When in branch <name>, it tells 'git fetch' the default
refspec to be marked for merging in FETCH_HEAD. The value is

View file

@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git rebase' [-i | --interactive] [options] [--onto <newbase>]
<upstream> [<branch>]
[<upstream>] [<branch>]
'git rebase' [-i | --interactive] [options] --onto <newbase>
--root [<branch>]
@ -21,6 +21,12 @@ If <branch> is specified, 'git rebase' will perform an automatic
`git checkout <branch>` before doing anything else. Otherwise
it remains on the current branch.
If <upstream> is not specified, the upstream configured in
branch.<name>.remote and branch.<name>.merge options will be used; see
linkgit:git-config[1] for details. If you are currently not on any
branch or if the current branch does not have a configured upstream,
the rebase will abort.
All changes made by commits in the current branch but that are not
in <upstream> are saved to a temporary area. This is the same set
of commits that would be shown by `git log <upstream>..HEAD` (or
@ -216,7 +222,8 @@ leave out at most one of A and B, in which case it defaults to HEAD.
<upstream>::
Upstream branch to compare against. May be any valid commit,
not just an existing branch name.
not just an existing branch name. Defaults to the configured
upstream for the current branch.
<branch>::
Working branch; defaults to HEAD.

View file

@ -99,3 +99,41 @@ get_remote_merge_branch () {
esac
esac
}
error_on_missing_default_upstream () {
cmd="$1"
op_type="$2"
op_prep="$3"
example="$4"
branch_name=$(git symbolic-ref -q HEAD)
if test -z "$branch_name"
then
echo "You are not currently on a branch, so I cannot use any
'branch.<branchname>.merge' in your configuration file.
Please specify which branch you want to $op_type $op_prep on the command
line and try again (e.g. '$example').
See git-${cmd}(1) for details."
else
echo "You asked me to $cmd without telling me which branch you
want to $op_type $op_prep, and 'branch.${branch_name#refs/heads/}.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. '$example').
See git-${cmd}(1) for details.
If you often $op_type $op_prep the same branch, you may want to
use something like the following in your configuration file:
[branch \"${branch_name#refs/heads/}\"]
remote = <nickname>
merge = <remote-ref>"
test rebase = "$op_type" &&
echo " rebase = true"
echo "
[remote \"<nickname>\"]
url = <url>
fetch = <refspec>
See git-config(1) for details."
fi
exit 1
}

View file

@ -163,34 +163,10 @@ error_on_no_merge_candidates () {
echo "You asked to pull from the remote '$1', but did not specify"
echo "a branch. Because this is not the default configured remote"
echo "for your current branch, you must specify a branch on the command line."
elif [ -z "$curr_branch" ]; then
echo "You are not currently on a branch, so I cannot use any"
echo "'branch.<branchname>.merge' in your configuration file."
echo "Please specify which remote branch you want to use on the command"
echo "line and try again (e.g. 'git pull <repository> <refspec>')."
echo "See git-pull(1) for details."
elif [ -z "$upstream" ]; then
echo "You asked me to pull without telling me which branch you"
echo "want to $op_type $op_prep, and 'branch.${curr_branch}.merge' in"
echo "your configuration file does not tell me, either. Please"
echo "specify which branch you want to use on the command line and"
echo "try again (e.g. 'git pull <repository> <refspec>')."
echo "See git-pull(1) for details."
echo
echo "If you often $op_type $op_prep the same branch, you may want to"
echo "use something like the following in your configuration file:"
echo
echo " [branch \"${curr_branch}\"]"
echo " remote = <nickname>"
echo " merge = <remote-ref>"
test rebase = "$op_type" &&
echo " rebase = true"
echo
echo " [remote \"<nickname>\"]"
echo " url = <url>"
echo " fetch = <refspec>"
echo
echo "See git-config(1) for details."
elif [ -z "$curr_branch" -o -z "$upstream" ]; then
. git-parse-remote
error_on_missing_default_upstream "pull" $op_type $op_prep \
"git pull <repository> <refspec>"
else
echo "Your configuration specifies to $op_type $op_prep the ref '${upstream#refs/heads/}'"
echo "from the remote, but no such ref was fetched."

View file

@ -3,7 +3,7 @@
# Copyright (c) 2005 Junio C Hamano.
#
USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--no-ff] [--onto <newbase>] (<upstream>|--root) [<branch>] [--quiet | -q]'
USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--no-ff] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]'
LONG_USAGE='git-rebase replaces <branch> with a new branch of the
same name. When the --onto option is provided the new branch starts
out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
@ -345,8 +345,6 @@ and run me again. I am stopping in case you still have something
valuable there.'
fi
test $# -eq 0 && test -z "$rebase_root" && usage
if test -n "$interactive_rebase"
then
type=interactive
@ -362,9 +360,20 @@ fi
if test -z "$rebase_root"
then
# The upstream head must be given. Make sure it is valid.
upstream_name="$1"
shift
case "$#" in
0)
if ! upstream_name=$(git rev-parse --symbolic-full-name \
--verify -q @{upstream} 2>/dev/null)
then
. git-parse-remote
error_on_missing_default_upstream "rebase" "rebase" \
"against" "git rebase <upstream branch>"
fi
;;
*) upstream_name="$1"
shift
;;
esac
upstream=`git rev-parse --verify "${upstream_name}^0"` ||
die "invalid upstream $upstream_name"
upstream_arg="$upstream_name"

View file

@ -158,15 +158,24 @@ test_expect_success 'Show verbose error when HEAD could not be detached' '
'
rm -f B
test_expect_success 'dump usage when upstream arg is missing' '
git checkout -b usage topic &&
test_must_fail git rebase 2>error1 &&
grep "[Uu]sage" error1 &&
test_must_fail git rebase --abort 2>error2 &&
grep "No rebase in progress" error2 &&
test_must_fail git rebase --onto master 2>error3 &&
grep "[Uu]sage" error3 &&
! grep "can.t shift" error3
test_expect_success 'fail when upstream arg is missing and not on branch' '
git checkout topic &&
test_must_fail git rebase >output.out &&
grep "You are not currently on a branch" output.out
'
test_expect_success 'fail when upstream arg is missing and not configured' '
git checkout -b no-config topic &&
test_must_fail git rebase >output.out &&
grep "branch.no-config.merge" output.out
'
test_expect_success 'default to @{upstream} when upstream arg is missing' '
git checkout -b default topic &&
git config branch.default.remote .
git config branch.default.merge refs/heads/master
git rebase &&
test "$(git rev-parse default~1)" = "$(git rev-parse master)"
'
test_expect_success 'rebase -q is quiet' '