git-pull.shon commit refactor duplicated code in builtin-send-pack.c and transport.c (f1863d0)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5# Fetch one or more remote refs and merge it/them into the current HEAD.
   6
   7USAGE='[-n | --no-stat] [--[no-]commit] [--[no-]squash] [--[no-]ff] [-s strategy]... [<fetch-options>] <repo> <head>...'
   8LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'
   9SUBDIRECTORY_OK=Yes
  10OPTIONS_SPEC=
  11. git-sh-setup
  12set_reflog_action "pull $*"
  13require_work_tree
  14cd_to_toplevel
  15
  16
  17die_conflict () {
  18    git diff-index --cached --name-status -r --ignore-submodules HEAD --
  19    if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
  20        die "Pull is not possible because you have unmerged files.
  21Please, fix them up in the work tree, and then use 'git add/rm <file>'
  22as appropriate to mark resolution, or use 'git commit -a'."
  23    else
  24        die "Pull is not possible because you have unmerged files."
  25    fi
  26}
  27
  28die_merge () {
  29    if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
  30        die "You have not concluded your merge (MERGE_HEAD exists).
  31Please, commit your changes before you can merge."
  32    else
  33        die "You have not concluded your merge (MERGE_HEAD exists)."
  34    fi
  35}
  36
  37test -z "$(git ls-files -u)" || die_conflict
  38test -f "$GIT_DIR/MERGE_HEAD" && die_merge
  39
  40strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
  41log_arg= verbosity=
  42merge_args=
  43curr_branch=$(git symbolic-ref -q HEAD)
  44curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
  45rebase=$(git config --bool branch.$curr_branch_short.rebase)
  46while :
  47do
  48        case "$1" in
  49        -q|--quiet)
  50                verbosity="$verbosity -q" ;;
  51        -v|--verbose)
  52                verbosity="$verbosity -v" ;;
  53        -n|--no-stat|--no-summary)
  54                diffstat=--no-stat ;;
  55        --stat|--summary)
  56                diffstat=--stat ;;
  57        --log|--no-log)
  58                log_arg=$1 ;;
  59        --no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
  60                no_commit=--no-commit ;;
  61        --c|--co|--com|--comm|--commi|--commit)
  62                no_commit=--commit ;;
  63        --sq|--squ|--squa|--squas|--squash)
  64                squash=--squash ;;
  65        --no-sq|--no-squ|--no-squa|--no-squas|--no-squash)
  66                squash=--no-squash ;;
  67        --ff)
  68                no_ff=--ff ;;
  69        --no-ff)
  70                no_ff=--no-ff ;;
  71        --ff-only)
  72                ff_only=--ff-only ;;
  73        -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
  74                --strateg=*|--strategy=*|\
  75        -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
  76                case "$#,$1" in
  77                *,*=*)
  78                        strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
  79                1,*)
  80                        usage ;;
  81                *)
  82                        strategy="$2"
  83                        shift ;;
  84                esac
  85                strategy_args="${strategy_args}-s $strategy "
  86                ;;
  87        -X*)
  88                case "$#,$1" in
  89                1,-X)
  90                        usage ;;
  91                *,-X)
  92                        xx="-X $(git rev-parse --sq-quote "$2")"
  93                        shift ;;
  94                *,*)
  95                        xx=$(git rev-parse --sq-quote "$1") ;;
  96                esac
  97                merge_args="$merge_args$xx "
  98                ;;
  99        -r|--r|--re|--reb|--reba|--rebas|--rebase)
 100                rebase=true
 101                ;;
 102        --no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)
 103                rebase=false
 104                ;;
 105        -h|--h|--he|--hel|--help)
 106                usage
 107                ;;
 108        *)
 109                # Pass thru anything that may be meant for fetch.
 110                break
 111                ;;
 112        esac
 113        shift
 114done
 115
 116error_on_no_merge_candidates () {
 117        exec >&2
 118        for opt
 119        do
 120                case "$opt" in
 121                -t|--t|--ta|--tag|--tags)
 122                        echo "Fetching tags only, you probably meant:"
 123                        echo "  git fetch --tags"
 124                        exit 1
 125                esac
 126        done
 127
 128        if test true = "$rebase"
 129        then
 130                op_type=rebase
 131                op_prep=against
 132        else
 133                op_type=merge
 134                op_prep=with
 135        fi
 136
 137        curr_branch=${curr_branch#refs/heads/}
 138        upstream=$(git config "branch.$curr_branch.merge")
 139        remote=$(git config "branch.$curr_branch.remote")
 140
 141        if [ $# -gt 1 ]; then
 142                if [ "$rebase" = true ]; then
 143                        printf "There is no candidate for rebasing against "
 144                else
 145                        printf "There are no candidates for merging "
 146                fi
 147                echo "among the refs that you just fetched."
 148                echo "Generally this means that you provided a wildcard refspec which had no"
 149                echo "matches on the remote end."
 150        elif [ $# -gt 0 ] && [ "$1" != "$remote" ]; then
 151                echo "You asked to pull from the remote '$1', but did not specify"
 152                echo "a branch. Because this is not the default configured remote"
 153                echo "for your current branch, you must specify a branch on the command line."
 154        elif [ -z "$curr_branch" ]; then
 155                echo "You are not currently on a branch, so I cannot use any"
 156                echo "'branch.<branchname>.merge' in your configuration file."
 157                echo "Please specify which remote branch you want to use on the command"
 158                echo "line and try again (e.g. 'git pull <repository> <refspec>')."
 159                echo "See git-pull(1) for details."
 160        elif [ -z "$upstream" ]; then
 161                echo "You asked me to pull without telling me which branch you"
 162                echo "want to $op_type $op_prep, and 'branch.${curr_branch}.merge' in"
 163                echo "your configuration file does not tell me, either. Please"
 164                echo "specify which branch you want to use on the command line and"
 165                echo "try again (e.g. 'git pull <repository> <refspec>')."
 166                echo "See git-pull(1) for details."
 167                echo
 168                echo "If you often $op_type $op_prep the same branch, you may want to"
 169                echo "use something like the following in your configuration file:"
 170                echo
 171                echo "    [branch \"${curr_branch}\"]"
 172                echo "    remote = <nickname>"
 173                echo "    merge = <remote-ref>"
 174                test rebase = "$op_type" &&
 175                        echo "    rebase = true"
 176                echo
 177                echo "    [remote \"<nickname>\"]"
 178                echo "    url = <url>"
 179                echo "    fetch = <refspec>"
 180                echo
 181                echo "See git-config(1) for details."
 182        else
 183                echo "Your configuration specifies to $op_type $op_prep the ref '${upstream#refs/heads/}'"
 184                echo "from the remote, but no such ref was fetched."
 185        fi
 186        exit 1
 187}
 188
 189test true = "$rebase" && {
 190        if ! git rev-parse -q --verify HEAD >/dev/null
 191        then
 192                # On an unborn branch
 193                if test -f "$GIT_DIR/index"
 194                then
 195                        die "updating an unborn branch with changes added to the index"
 196                fi
 197        else
 198                git update-index --ignore-submodules --refresh &&
 199                git diff-files --ignore-submodules --quiet &&
 200                git diff-index --ignore-submodules --cached --quiet HEAD -- ||
 201                die "refusing to pull with rebase: your working tree is not up-to-date"
 202        fi
 203        oldremoteref= &&
 204        . git-parse-remote &&
 205        remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
 206        oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
 207        for reflog in $(git rev-list -g $remoteref 2>/dev/null)
 208        do
 209                if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
 210                then
 211                        oldremoteref="$reflog"
 212                        break
 213                fi
 214        done
 215}
 216orig_head=$(git rev-parse -q --verify HEAD)
 217git fetch $verbosity --update-head-ok "$@" || exit 1
 218
 219curr_head=$(git rev-parse -q --verify HEAD)
 220if test -n "$orig_head" && test "$curr_head" != "$orig_head"
 221then
 222        # The fetch involved updating the current branch.
 223
 224        # The working tree and the index file is still based on the
 225        # $orig_head commit, but we are merging into $curr_head.
 226        # First update the working tree to match $curr_head.
 227
 228        echo >&2 "Warning: fetch updated the current branch head."
 229        echo >&2 "Warning: fast-forwarding your working tree from"
 230        echo >&2 "Warning: commit $orig_head."
 231        git update-index -q --refresh
 232        git read-tree -u -m "$orig_head" "$curr_head" ||
 233                die 'Cannot fast-forward your working tree.
 234After making sure that you saved anything precious from
 235$ git diff '$orig_head'
 236output, run
 237$ git reset --hard
 238to recover.'
 239
 240fi
 241
 242merge_head=$(sed -e '/  not-for-merge   /d' \
 243        -e 's/  .*//' "$GIT_DIR"/FETCH_HEAD | \
 244        tr '\012' ' ')
 245
 246case "$merge_head" in
 247'')
 248        error_on_no_merge_candidates "$@"
 249        ;;
 250?*' '?*)
 251        if test -z "$orig_head"
 252        then
 253                die "Cannot merge multiple branches into empty head"
 254        fi
 255        if test true = "$rebase"
 256        then
 257                die "Cannot rebase onto multiple branches"
 258        fi
 259        ;;
 260esac
 261
 262if test -z "$orig_head"
 263then
 264        git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
 265        git read-tree --reset -u HEAD || exit 1
 266        exit
 267fi
 268
 269merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
 270case "$rebase" in
 271true)
 272        eval="git-rebase $diffstat $strategy_args $merge_args"
 273        eval="$eval --onto $merge_head ${oldremoteref:-$merge_head}"
 274        ;;
 275*)
 276        eval="git-merge $diffstat $no_commit $squash $no_ff $ff_only"
 277        eval="$eval  $log_arg $strategy_args $merge_args"
 278        eval="$eval \"\$merge_name\" HEAD $merge_head $verbosity"
 279        ;;
 280esac
 281eval "exec $eval"