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:
commit
12d4ffaa94
@ -17,26 +17,6 @@ routines to parse files under $GIT_DIR/remotes/ and
|
|||||||
$GIT_DIR/branches/ and configuration variables that are related
|
$GIT_DIR/branches/ and configuration variables that are related
|
||||||
to fetching, pulling and pushing.
|
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
|
Author
|
||||||
------
|
------
|
||||||
Written by Junio C Hamano.
|
Written by Junio C Hamano.
|
||||||
|
@ -60,205 +60,36 @@ get_default_remote () {
|
|||||||
echo ${origin:-origin}
|
echo ${origin:-origin}
|
||||||
}
|
}
|
||||||
|
|
||||||
get_remote_default_refs_for_push () {
|
get_remote_merge_branch () {
|
||||||
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 () {
|
|
||||||
case "$#" in
|
case "$#" in
|
||||||
0) die "internal error: get-remote-refs-for-push." ;;
|
0|1)
|
||||||
1) get_remote_default_refs_for_push "$@" ;;
|
origin="$1"
|
||||||
*) shift; echo "$@" ;;
|
default=$(get_default_remote)
|
||||||
esac
|
test -z "$origin" && origin=$default
|
||||||
}
|
curr_branch=$(git symbolic-ref -q HEAD)
|
||||||
|
[ "$origin" = "$default" ] &&
|
||||||
get_remote_refs_for_fetch () {
|
echo $(git for-each-ref --format='%(upstream)' $curr_branch)
|
||||||
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
|
|
||||||
;;
|
;;
|
||||||
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
|
esac
|
||||||
}
|
}
|
||||||
|
@ -125,12 +125,9 @@ test true = "$rebase" && {
|
|||||||
die "refusing to pull with rebase: your working tree is not up-to-date"
|
die "refusing to pull with rebase: your working tree is not up-to-date"
|
||||||
|
|
||||||
. git-parse-remote &&
|
. git-parse-remote &&
|
||||||
origin="$1"
|
reflist="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
|
||||||
test -z "$origin" && origin=$(get_default_remote)
|
|
||||||
reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null |
|
|
||||||
sed "s|refs/heads/\(.*\):|\1|")" &&
|
|
||||||
oldremoteref="$(git rev-parse -q --verify \
|
oldremoteref="$(git rev-parse -q --verify \
|
||||||
"refs/remotes/$origin/$reflist")"
|
"$reflist")"
|
||||||
}
|
}
|
||||||
orig_head=$(git rev-parse -q --verify HEAD)
|
orig_head=$(git rev-parse -q --verify HEAD)
|
||||||
git fetch $verbosity --update-head-ok "$@" || exit 1
|
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 remote add -f me . &&
|
||||||
git checkout copy &&
|
git checkout copy &&
|
||||||
|
git tag copy-orig &&
|
||||||
git reset --hard HEAD^ &&
|
git reset --hard HEAD^ &&
|
||||||
echo conflicting modification > file &&
|
echo conflicting modification > file &&
|
||||||
git commit -m conflict file &&
|
git commit -m conflict file &&
|
||||||
git checkout to-rebase &&
|
git checkout to-rebase &&
|
||||||
echo file > file2 &&
|
echo file > file2 &&
|
||||||
git commit -m to-rebase file2 &&
|
git commit -m to-rebase file2 &&
|
||||||
|
git tag to-rebase-orig &&
|
||||||
git pull --rebase me copy &&
|
git pull --rebase me copy &&
|
||||||
test "conflicting modification" = "$(cat file)" &&
|
test "conflicting modification" = "$(cat file)" &&
|
||||||
test file = $(cat file2)
|
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' '
|
test_expect_success 'pull --rebase dies early with dirty working directory' '
|
||||||
|
|
||||||
|
git checkout to-rebase &&
|
||||||
git update-ref refs/remotes/me/copy copy^ &&
|
git update-ref refs/remotes/me/copy copy^ &&
|
||||||
COPY=$(git rev-parse --verify me/copy) &&
|
COPY=$(git rev-parse --verify me/copy) &&
|
||||||
git rebase --onto $COPY copy &&
|
git rebase --onto $COPY copy &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user