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