зеркало из https://github.com/microsoft/git.git
Merge branch 'sb/pull-rebase'
* sb/pull-rebase: parse-remote: remove unused functions parse-remote: support default reflist in get_remote_merge_branch parse-remote: function to get the tracking branch to be merge
This commit is contained in:
Коммит
12d4ffaa94
|
@ -17,26 +17,6 @@ routines to parse files under $GIT_DIR/remotes/ and
|
|||
$GIT_DIR/branches/ and configuration variables that are related
|
||||
to fetching, pulling and pushing.
|
||||
|
||||
The primary entry points are:
|
||||
|
||||
get_remote_refs_for_fetch::
|
||||
Given the list of user-supplied `<repo> <refspec>...`,
|
||||
return the list of refs to fetch after canonicalizing
|
||||
them into `$GIT_DIR` relative paths
|
||||
(e.g. `refs/heads/foo`). When `<refspec>...` is empty
|
||||
the returned list of refs consists of the defaults
|
||||
for the given `<repo>`, if specified in
|
||||
`$GIT_DIR/remotes/`, `$GIT_DIR/branches/`, or `remote.*.fetch`
|
||||
configuration.
|
||||
|
||||
get_remote_refs_for_push::
|
||||
Given the list of user-supplied `<repo> <refspec>...`,
|
||||
return the list of refs to push in a form suitable to be
|
||||
fed to the 'git-send-pack' command. When `<refspec>...`
|
||||
is empty the returned list of refs consists of the
|
||||
defaults for the given `<repo>`, if specified in
|
||||
`$GIT_DIR/remotes/`.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano.
|
||||
|
|
|
@ -60,205 +60,36 @@ get_default_remote () {
|
|||
echo ${origin:-origin}
|
||||
}
|
||||
|
||||
get_remote_default_refs_for_push () {
|
||||
data_source=$(get_data_source "$1")
|
||||
case "$data_source" in
|
||||
'' | branches | self)
|
||||
;; # no default push mapping, just send matching refs.
|
||||
config)
|
||||
git config --get-all "remote.$1.push" ;;
|
||||
remotes)
|
||||
sed -ne '/^Push: */{
|
||||
s///p
|
||||
}' "$GIT_DIR/remotes/$1" ;;
|
||||
*)
|
||||
die "internal error: get-remote-default-ref-for-push $1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Called from canon_refs_list_for_fetch -d "$remote", which
|
||||
# is called from get_remote_default_refs_for_fetch to grok
|
||||
# refspecs that are retrieved from the configuration, but not
|
||||
# from get_remote_refs_for_fetch when it deals with refspecs
|
||||
# supplied on the command line. $ls_remote_result has the list
|
||||
# of refs available at remote.
|
||||
#
|
||||
# The first token returned is either "explicit" or "glob"; this
|
||||
# is to help prevent randomly "globbed" ref from being chosen as
|
||||
# a merge candidate
|
||||
expand_refs_wildcard () {
|
||||
echo "$ls_remote_result" |
|
||||
git fetch--tool expand-refs-wildcard "-" "$@"
|
||||
}
|
||||
|
||||
# Subroutine to canonicalize remote:local notation.
|
||||
canon_refs_list_for_fetch () {
|
||||
# If called from get_remote_default_refs_for_fetch
|
||||
# leave the branches in branch.${curr_branch}.merge alone,
|
||||
# or the first one otherwise; add prefix . to the rest
|
||||
# to prevent the secondary branches to be merged by default.
|
||||
merge_branches=
|
||||
curr_branch=
|
||||
if test "$1" = "-d"
|
||||
then
|
||||
shift ; remote="$1" ; shift
|
||||
set $(expand_refs_wildcard "$remote" "$@")
|
||||
is_explicit="$1"
|
||||
shift
|
||||
if test "$remote" = "$(get_default_remote)"
|
||||
then
|
||||
curr_branch=$(git symbolic-ref -q HEAD | \
|
||||
sed -e 's|^refs/heads/||')
|
||||
merge_branches=$(git config \
|
||||
--get-all "branch.${curr_branch}.merge")
|
||||
fi
|
||||
if test -z "$merge_branches" && test $is_explicit != explicit
|
||||
then
|
||||
merge_branches=..this.will.never.match.any.ref..
|
||||
fi
|
||||
fi
|
||||
for ref
|
||||
do
|
||||
force=
|
||||
case "$ref" in
|
||||
+*)
|
||||
ref=$(expr "z$ref" : 'z+\(.*\)')
|
||||
force=+
|
||||
;;
|
||||
esac
|
||||
expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:"
|
||||
remote=$(expr "z$ref" : 'z\([^:]*\):')
|
||||
local=$(expr "z$ref" : 'z[^:]*:\(.*\)')
|
||||
dot_prefix=.
|
||||
if test -z "$merge_branches"
|
||||
then
|
||||
merge_branches=$remote
|
||||
dot_prefix=
|
||||
else
|
||||
for merge_branch in $merge_branches
|
||||
do
|
||||
[ "$remote" = "$merge_branch" ] &&
|
||||
dot_prefix= && break
|
||||
done
|
||||
fi
|
||||
case "$remote" in
|
||||
'' | HEAD ) remote=HEAD ;;
|
||||
refs/*) ;;
|
||||
heads/* | tags/* | remotes/* ) remote="refs/$remote" ;;
|
||||
*) remote="refs/heads/$remote" ;;
|
||||
esac
|
||||
case "$local" in
|
||||
'') local= ;;
|
||||
refs/*) ;;
|
||||
heads/* | tags/* | remotes/* ) local="refs/$local" ;;
|
||||
*) local="refs/heads/$local" ;;
|
||||
esac
|
||||
|
||||
if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)')
|
||||
then
|
||||
git check-ref-format "$local_ref_name" ||
|
||||
die "* refusing to create funny ref '$local_ref_name' locally"
|
||||
fi
|
||||
echo "${dot_prefix}${force}${remote}:${local}"
|
||||
done
|
||||
}
|
||||
|
||||
# Returns list of src: (no store), or src:dst (store)
|
||||
get_remote_default_refs_for_fetch () {
|
||||
data_source=$(get_data_source "$1")
|
||||
case "$data_source" in
|
||||
'')
|
||||
echo "HEAD:" ;;
|
||||
self)
|
||||
canon_refs_list_for_fetch -d "$1" \
|
||||
$(git for-each-ref --format='%(refname):')
|
||||
;;
|
||||
config)
|
||||
canon_refs_list_for_fetch -d "$1" \
|
||||
$(git config --get-all "remote.$1.fetch") ;;
|
||||
branches)
|
||||
remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
|
||||
case "$remote_branch" in '') remote_branch=master ;; esac
|
||||
echo "refs/heads/${remote_branch}:refs/heads/$1"
|
||||
;;
|
||||
remotes)
|
||||
canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{
|
||||
s///p
|
||||
}' "$GIT_DIR/remotes/$1")
|
||||
;;
|
||||
*)
|
||||
die "internal error: get-remote-default-ref-for-fetch $1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_remote_refs_for_push () {
|
||||
get_remote_merge_branch () {
|
||||
case "$#" in
|
||||
0) die "internal error: get-remote-refs-for-push." ;;
|
||||
1) get_remote_default_refs_for_push "$@" ;;
|
||||
*) shift; echo "$@" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_remote_refs_for_fetch () {
|
||||
case "$#" in
|
||||
0)
|
||||
die "internal error: get-remote-refs-for-fetch." ;;
|
||||
1)
|
||||
get_remote_default_refs_for_fetch "$@" ;;
|
||||
*)
|
||||
shift
|
||||
tag_just_seen=
|
||||
for ref
|
||||
do
|
||||
if test "$tag_just_seen"
|
||||
then
|
||||
echo "refs/tags/${ref}:refs/tags/${ref}"
|
||||
tag_just_seen=
|
||||
continue
|
||||
else
|
||||
case "$ref" in
|
||||
tag)
|
||||
tag_just_seen=yes
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
canon_refs_list_for_fetch "$ref"
|
||||
done
|
||||
0|1)
|
||||
origin="$1"
|
||||
default=$(get_default_remote)
|
||||
test -z "$origin" && origin=$default
|
||||
curr_branch=$(git symbolic-ref -q HEAD)
|
||||
[ "$origin" = "$default" ] &&
|
||||
echo $(git for-each-ref --format='%(upstream)' $curr_branch)
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
resolve_alternates () {
|
||||
# original URL (xxx.git)
|
||||
top_=`expr "z$1" : 'z\([^:]*:/*[^/]*\)/'`
|
||||
while read path
|
||||
do
|
||||
case "$path" in
|
||||
\#* | '')
|
||||
continue ;;
|
||||
/*)
|
||||
echo "$top_$path/" ;;
|
||||
../*)
|
||||
# relative -- ugly but seems to work.
|
||||
echo "$1/objects/$path/" ;;
|
||||
*)
|
||||
# exit code may not be caught by the reader.
|
||||
echo "bad alternate: $path"
|
||||
exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
get_uploadpack () {
|
||||
data_source=$(get_data_source "$1")
|
||||
case "$data_source" in
|
||||
config)
|
||||
uplp=$(git config --get "remote.$1.uploadpack")
|
||||
echo ${uplp:-git-upload-pack}
|
||||
;;
|
||||
*)
|
||||
echo "git-upload-pack"
|
||||
repo=$1
|
||||
shift
|
||||
ref=$1
|
||||
# FIXME: It should return the tracking branch
|
||||
# Currently only works with the default mapping
|
||||
case "$ref" in
|
||||
+*)
|
||||
ref=$(expr "z$ref" : 'z+\(.*\)')
|
||||
;;
|
||||
esac
|
||||
expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:"
|
||||
remote=$(expr "z$ref" : 'z\([^:]*\):')
|
||||
case "$remote" in
|
||||
'' | HEAD ) remote=HEAD ;;
|
||||
heads/*) remote=${remote#heads/} ;;
|
||||
refs/heads/*) remote=${remote#refs/heads/} ;;
|
||||
refs/* | tags/* | remotes/* ) remote=
|
||||
esac
|
||||
|
||||
[ -n "$remote" ] && echo "refs/remotes/$repo/$remote"
|
||||
esac
|
||||
}
|
||||
|
|
|
@ -125,12 +125,9 @@ test true = "$rebase" && {
|
|||
die "refusing to pull with rebase: your working tree is not up-to-date"
|
||||
|
||||
. git-parse-remote &&
|
||||
origin="$1"
|
||||
test -z "$origin" && origin=$(get_default_remote)
|
||||
reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null |
|
||||
sed "s|refs/heads/\(.*\):|\1|")" &&
|
||||
reflist="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
|
||||
oldremoteref="$(git rev-parse -q --verify \
|
||||
"refs/remotes/$origin/$reflist")"
|
||||
"$reflist")"
|
||||
}
|
||||
orig_head=$(git rev-parse -q --verify HEAD)
|
||||
git fetch $verbosity --update-head-ok "$@" || exit 1
|
||||
|
|
|
@ -92,20 +92,34 @@ test_expect_success '--rebase with rebased upstream' '
|
|||
|
||||
git remote add -f me . &&
|
||||
git checkout copy &&
|
||||
git tag copy-orig &&
|
||||
git reset --hard HEAD^ &&
|
||||
echo conflicting modification > file &&
|
||||
git commit -m conflict file &&
|
||||
git checkout to-rebase &&
|
||||
echo file > file2 &&
|
||||
git commit -m to-rebase file2 &&
|
||||
git tag to-rebase-orig &&
|
||||
git pull --rebase me copy &&
|
||||
test "conflicting modification" = "$(cat file)" &&
|
||||
test file = $(cat file2)
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--rebase with rebased default upstream' '
|
||||
|
||||
git update-ref refs/remotes/me/copy copy-orig &&
|
||||
git checkout --track -b to-rebase2 me/copy &&
|
||||
git reset --hard to-rebase-orig &&
|
||||
git pull --rebase &&
|
||||
test "conflicting modification" = "$(cat file)" &&
|
||||
test file = $(cat file2)
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'pull --rebase dies early with dirty working directory' '
|
||||
|
||||
git checkout to-rebase &&
|
||||
git update-ref refs/remotes/me/copy copy^ &&
|
||||
COPY=$(git rev-parse --verify me/copy) &&
|
||||
git rebase --onto $COPY copy &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче