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 коммит произвёл Junio C Hamano
Родитель c71f8f3d50
Коммит 15a147e618
6 изменённых файлов: 85 добавлений и 46 удалений

Просмотреть файл

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

Просмотреть файл

@ -9,7 +9,7 @@ SYNOPSIS
-------- --------
[verse] [verse]
'git rebase' [-i | --interactive] [options] [--onto <newbase>] 'git rebase' [-i | --interactive] [options] [--onto <newbase>]
<upstream> [<branch>] [<upstream>] [<branch>]
'git rebase' [-i | --interactive] [options] --onto <newbase> 'git rebase' [-i | --interactive] [options] --onto <newbase>
--root [<branch>] --root [<branch>]
@ -21,6 +21,12 @@ If <branch> is specified, 'git rebase' will perform an automatic
`git checkout <branch>` before doing anything else. Otherwise `git checkout <branch>` before doing anything else. Otherwise
it remains on the current branch. 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 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 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 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>::
Upstream branch to compare against. May be any valid commit, 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>:: <branch>::
Working branch; defaults to HEAD. Working branch; defaults to HEAD.

Просмотреть файл

@ -99,3 +99,41 @@ get_remote_merge_branch () {
esac esac
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
}

Просмотреть файл

@ -163,34 +163,10 @@ error_on_no_merge_candidates () {
echo "You asked to pull from the remote '$1', but did not specify" 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 "a branch. Because this is not the default configured remote"
echo "for your current branch, you must specify a branch on the command line." echo "for your current branch, you must specify a branch on the command line."
elif [ -z "$curr_branch" ]; then elif [ -z "$curr_branch" -o -z "$upstream" ]; then
echo "You are not currently on a branch, so I cannot use any" . git-parse-remote
echo "'branch.<branchname>.merge' in your configuration file." error_on_missing_default_upstream "pull" $op_type $op_prep \
echo "Please specify which remote branch you want to use on the command" "git pull <repository> <refspec>"
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."
else else
echo "Your configuration specifies to $op_type $op_prep the ref '${upstream#refs/heads/}'" echo "Your configuration specifies to $op_type $op_prep the ref '${upstream#refs/heads/}'"
echo "from the remote, but no such ref was fetched." echo "from the remote, but no such ref was fetched."

Просмотреть файл

@ -3,7 +3,7 @@
# Copyright (c) 2005 Junio C Hamano. # 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 LONG_USAGE='git-rebase replaces <branch> with a new branch of the
same name. When the --onto option is provided the new branch starts 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> 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.' valuable there.'
fi fi
test $# -eq 0 && test -z "$rebase_root" && usage
if test -n "$interactive_rebase" if test -n "$interactive_rebase"
then then
type=interactive type=interactive
@ -362,9 +360,20 @@ fi
if test -z "$rebase_root" if test -z "$rebase_root"
then then
# The upstream head must be given. Make sure it is valid. case "$#" in
upstream_name="$1" 0)
shift 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"` || upstream=`git rev-parse --verify "${upstream_name}^0"` ||
die "invalid upstream $upstream_name" die "invalid upstream $upstream_name"
upstream_arg="$upstream_name" upstream_arg="$upstream_name"

Просмотреть файл

@ -158,15 +158,24 @@ test_expect_success 'Show verbose error when HEAD could not be detached' '
' '
rm -f B rm -f B
test_expect_success 'dump usage when upstream arg is missing' ' test_expect_success 'fail when upstream arg is missing and not on branch' '
git checkout -b usage topic && git checkout topic &&
test_must_fail git rebase 2>error1 && test_must_fail git rebase >output.out &&
grep "[Uu]sage" error1 && grep "You are not currently on a branch" output.out
test_must_fail git rebase --abort 2>error2 && '
grep "No rebase in progress" error2 &&
test_must_fail git rebase --onto master 2>error3 && test_expect_success 'fail when upstream arg is missing and not configured' '
grep "[Uu]sage" error3 && git checkout -b no-config topic &&
! grep "can.t shift" error3 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' ' test_expect_success 'rebase -q is quiet' '