git-fetch fetches the branches from the remote and saves this information in .git/FETCH_FETCHED, and at the end it generates the file .git/FETCH_HEAD. There are two cases where the behaviour is changed: 1) branch.*.merge no longer must exactly match the remote part of the branch fetched. Both are expanded in full (as refs/heads/...) and matched afterwards. 2) When the remote is specified with $GIT_DIR/branches/... and there is a branch.*.merge, the remote branch name must match to get them merged. Before the branch in $GIT_DIR/branches/... was always merged. In the documentation the $GIT_DIR/branches/ is documented as a short-hand for a corresponding file in $GIT_DIR/remotes/, so I think this makes the new behaviour consistent. Signed-off-by: Santi Béjar <sbejar@xxxxxxxxx> --- Documentation/config.txt | 2 +- git-fetch.sh | 74 ++++++++++++++++++++++++++------------------- git-parse-remote.sh | 60 +++++++++---------------------------- t/t5510-fetch.sh | 16 ++++++++++ 4 files changed, 75 insertions(+), 77 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 9620126..e695de5 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -238,7 +238,7 @@ branch.<name>.remote:: branch.<name>.merge:: When in branch <name>, it tells `git fetch` the default refspec to - be marked for merging in FETCH_HEAD. The value has exactly to match + be marked for merging in FETCH_HEAD. The value has to match a remote part of one of the refspecs which are fetched from the remote given by "branch.<name>.remote". The merge information is used by `git pull` (which at first calls diff --git a/git-fetch.sh b/git-fetch.sh index ca984e7..727538d 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -77,9 +77,9 @@ do shift done +origin=$(get_default_remote) case "$#" in 0) - origin=$(get_default_remote) test -n "$(get_remote_url ${origin})" || die "Where do you want to fetch from today?" set x $origin ; shift ;; @@ -101,6 +101,7 @@ if test "" = "$append" then : >"$GIT_DIR/FETCH_HEAD" fi +: >"$GIT_DIR/FETCH_FETCHED" # Global that is reused later ls_remote_result=$(git ls-remote $exec "$remote") || @@ -112,10 +113,6 @@ append_fetch_head () { remote_name_="$3" remote_nick_="$4" local_name_="$5" - case "$6" in - t) not_for_merge_='not-for-merge' ;; - '') not_for_merge_= ;; - esac # remote-nick is the URL given on the command line (or a shorthand) # remote-name is the $GIT_DIR relative refs/ path we computed @@ -146,9 +143,7 @@ append_fetch_head () { if git-cat-file commit "$head_" >/dev/null 2>&1 then headc_=$(git-rev-parse --verify "$head_^0") || exit - echo "$headc_ $not_for_merge_ $note_" >>"$GIT_DIR/FETCH_HEAD" - else - echo "$head_ not-for-merge $note_" >>"$GIT_DIR/FETCH_HEAD" + echo "$headc_ $remote_name_:$local_name_ $note_" >>"$GIT_DIR/FETCH_FETCHED" fi update_local_ref "$local_name_" "$head_" "$note_" @@ -256,7 +251,7 @@ then git-show-ref --exclude-existing=refs/tags/ | while read sha1 name do - echo ".${name}:${name}" + echo "${name}:${name}" done` || exit if test "$#" -gt 1 then @@ -279,13 +274,6 @@ fetch_main () { # These are relative path from $GIT_DIR, typically starting at refs/ # but may be HEAD - if expr "z$ref" : 'z\.' >/dev/null - then - not_for_merge=t - ref=$(expr "z$ref" : 'z\.\(.*\)') - else - not_for_merge= - fi if expr "z$ref" : 'z+' >/dev/null then single_force=t @@ -366,7 +354,7 @@ fetch_main () { esac append_fetch_head "$head" "$remote" \ - "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" || exit + "$remote_name" "$remote_nick" "$local_name" || exit done @@ -409,28 +397,16 @@ fetch_main () { case "$ref" in +$remote_name:*) single_force=t - not_for_merge= - found="$ref" - break ;; - .+$remote_name:*) - single_force=t - not_for_merge=t - found="$ref" - break ;; - .$remote_name:*) - not_for_merge=t found="$ref" break ;; $remote_name:*) - not_for_merge= found="$ref" break ;; esac done local_name=$(expr "z$found" : 'z[^:]*:\(.*\)') append_fetch_head "$sha1" "$remote" \ - "$remote_name" "$remote_nick" "$local_name" \ - "$not_for_merge" || exit + "$remote_name" "$remote_nick" "$local_name" || exit done ) ) || exit ;; @@ -454,7 +430,7 @@ case "$no_tags$tags" in do git-cat-file -t "$sha1" >/dev/null 2>&1 || continue echo >&2 "Auto-following $name" - echo ".${name}:${name}" + echo "${name}:${name}" done) esac case "$taglist" in @@ -482,3 +458,39 @@ case "$orig_head" in fi ;; esac + +# Generate $GIT_DIR/FETCH_HEAD +case ",$#,$remote_nick," in +,1,$origin,) + curr_branch=$(git-symbolic-ref -q HEAD | sed -e 's|^refs/heads/||') + merge_branches=$(git-repo-config \ + --get-all "branch.${curr_branch}.merge") + [ -z "$merge_branches" ] && merge_first=yes;; +,1,$remote,) merge_branches=HEAD;; +,1,*)merge_first=yes ;; +*) + shift + merge_branches=$(for ref; do + expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:" + echo "$(expr "z$ref" : 'z\([^:]*\):')"; done);; +esac + +test "$merge_first" == "yes" && +test "$(get_remote_default_refs_for_fetch -t $remote_nick)" != "explicit" && +merge_branches= && merge_first= + +merge_branches=$(canon_refs_list_for_fetch $merge_branches | sed 's/:.*$//g') + +cat "$GIT_DIR"/FETCH_FETCHED | while IFS=' ' read sha1 ref note ; do + remote_branch=$(expr "z$ref" : 'z\([^:]*\):') + for merge_branch in $merge_branches ; do + [ "$merge_branch" == "$remote_branch" ] && + echo "$sha1 $note" && continue 2 + done + if ! test "$merge_first" || test "$merge_first" == "done" ; then + echo "$sha1 not-for-merge $note" + else + echo "$sha1 $note" + merge_first=done + fi +done >> "$GIT_DIR/FETCH_HEAD" diff --git a/git-parse-remote.sh b/git-parse-remote.sh index 5208ee6..212b3bc 100755 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -70,8 +70,7 @@ get_remote_default_refs_for_push () { esac } -# Called from canon_refs_list_for_fetch -d "$remote", which -# is called from get_remote_default_refs_for_fetch to grok +# 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 @@ -130,30 +129,6 @@ 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= @@ -166,18 +141,6 @@ canon_refs_list_for_fetch () { 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/* | refs/tags/* | refs/remotes/*) ;; @@ -196,32 +159,39 @@ canon_refs_list_for_fetch () { git-check-ref-format "$local_ref_name" || die "* refusing to create funny ref '$local_ref_name' locally" fi - echo "${dot_prefix}${force}${remote}:${local}" + echo "${force}${remote}:${local}" done } # Returns list of src: (no store), or src:dst (store) get_remote_default_refs_for_fetch () { + test "$1" == -t && type=yes && shift data_source=$(get_data_source "$1") case "$data_source" in '') - echo "HEAD:" ;; + set explicit "HEAD:" ;; config) - canon_refs_list_for_fetch -d "$1" \ - $(git-config --get-all "remote.$1.fetch") ;; + set $(expand_refs_wildcard "$1" \ + $(git-repo-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" + set explicit "refs/heads/${remote_branch}:refs/heads/$1" ;; remotes) - canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{ + set $(expand_refs_wildcard "$1" $(sed -ne '/^Pull: */{ s///p - }' "$GIT_DIR/remotes/$1") + }' "$GIT_DIR/remotes/$1")) ;; *) die "internal error: get-remote-default-ref-for-push $1" ;; esac + if [ "$type" ] ; then + echo $1 + else + shift + canon_refs_list_for_fetch "$@" + fi } get_remote_refs_for_push () { diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 50c6485..0a19a7d 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -50,6 +50,22 @@ test_expect_success "fetch test" ' test "z$mine" = "z$his" ' +test_expect_success "fetch test fetched" ' + cd "$D" && + cd three && + git fetch && + test -f .git/refs/heads/two && + test -f .git/refs/heads/one && + master_in_two=`cd ../two && git rev-parse master` && + one_in_two=`cd ../two && git rev-parse one` && + { + echo "$master_in_two refs/heads/master:refs/heads/two" + echo "$one_in_two refs/heads/one:refs/heads/one" + } >expected && + cut -f -2 .git/FETCH_FETCHED >actual && + diff expected actual' + + test_expect_success "fetch test for-merge" ' cd "$D" && cd three && -- 1.5.0.35.gaaba - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html