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