git-pull.sh 4.8 KB
Newer Older
1 2
#!/bin/sh
#
3 4 5 6
# Copyright (c) 2005 Junio C Hamano
#
# Fetch one or more remote refs and merge it/them into the current HEAD.

7
USAGE='[-n | --no-stat] [--[no-]commit] [--[no-]squash] [--[no-]ff] [-s strategy]... [<fetch-options>] <repo> <head>...'
8
LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'
9
SUBDIRECTORY_OK=Yes
10
OPTIONS_SPEC=
11
. git-sh-setup
12
set_reflog_action "pull $*"
13
require_work_tree
14
cd_to_toplevel
15

16
test -z "$(git ls-files -u)" ||
17
	die "You are in the middle of a conflicted merge."
18

19
strategy_args= no_stat= no_commit= squash= no_ff= log_arg=
20 21 22
curr_branch=$(git symbolic-ref -q HEAD)
curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
rebase=$(git config --bool branch.$curr_branch_short.rebase)
23
while :
24 25
do
	case "$1" in
26 27 28 29
	-n|--no-stat|--no-summary)
		no_stat=-n ;;
	--stat|--summary)
		no_stat=$1 ;;
30 31
	--log|--no-log)
		log_arg=$1 ;;
32 33
	--no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
		no_commit=--no-commit ;;
34 35
	--c|--co|--com|--comm|--commi|--commit)
		no_commit=--commit ;;
J
Junio C Hamano 已提交
36 37
	--sq|--squ|--squa|--squas|--squash)
		squash=--squash ;;
38 39 40 41 42 43
	--no-sq|--no-squ|--no-squa|--no-squas|--no-squash)
		squash=--no-squash ;;
	--ff)
		no_ff=--ff ;;
	--no-ff)
		no_ff=--no-ff ;;
44 45 46 47 48
	-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
		--strateg=*|--strategy=*|\
	-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
		case "$#,$1" in
		*,*=*)
D
Dennis Stosberg 已提交
49
			strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
50 51 52 53 54 55 56 57
		1,*)
			usage ;;
		*)
			strategy="$2"
			shift ;;
		esac
		strategy_args="${strategy_args}-s $strategy "
		;;
58 59 60 61 62 63
	-r|--r|--re|--reb|--reba|--rebas|--rebase)
		rebase=true
		;;
	--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)
		rebase=false
		;;
64 65 66
	-h|--h|--he|--hel|--help)
		usage
		;;
67 68
	*)
		# Pass thru anything that may be meant for fetch.
69
		break
70 71 72 73 74
		;;
	esac
	shift
done

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
error_on_no_merge_candidates () {
	exec >&2
	for opt
	do
		case "$opt" in
		-t|--t|--ta|--tag|--tags)
			echo "Fetching tags only, you probably meant:"
			echo "  git fetch --tags"
			exit 1
		esac
	done

	curr_branch=${curr_branch#refs/heads/}

	echo "You asked me to pull without telling me which branch you"
	echo "want to merge with, and 'branch.${curr_branch}.merge' in"
	echo "your configuration file does not tell me either.  Please"
	echo "name which branch you want to merge on the command line and"
	echo "try again (e.g. 'git pull <repository> <refspec>')."
	echo "See git-pull(1) for details on the refspec."
	echo
	echo "If you often merge with the same branch, you may want to"
	echo "configure the following variables in your configuration"
	echo "file:"
	echo
	echo "    branch.${curr_branch}.remote = <nickname>"
	echo "    branch.${curr_branch}.merge = <remote-ref>"
	echo "    remote.<nickname>.url = <url>"
	echo "    remote.<nickname>.fetch = <refspec>"
	echo
	echo "See git-config(1) for details."
	exit 1
}

109 110 111 112 113 114 115 116 117
test true = "$rebase" && {
	. git-parse-remote &&
	origin="$1"
	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 --verify \
		"refs/remotes/$origin/$reflist" 2>/dev/null)"
}
118
orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
119
git-fetch --update-head-ok "$@" || exit 1
120

121
curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
122 123 124 125 126 127 128 129 130
if test "$curr_head" != "$orig_head"
then
	# The fetch involved updating the current branch.

	# The working tree and the index file is still based on the
	# $orig_head commit, but we are merging into $curr_head.
	# First update the working tree to match $curr_head.

	echo >&2 "Warning: fetch updated the current branch head."
131
	echo >&2 "Warning: fast forwarding your working tree from"
132
	echo >&2 "Warning: commit $orig_head."
133 134
	git update-index --refresh 2>/dev/null
	git read-tree -u -m "$orig_head" "$curr_head" ||
135 136 137 138 139 140 141
		die 'Cannot fast-forward your working tree.
After making sure that you saved anything precious from
$ git diff '$orig_head'
output, run
$ git reset --hard
to recover.'

142 143
fi

144 145 146
merge_head=$(sed -e '/	not-for-merge	/d' \
	-e 's/	.*//' "$GIT_DIR"/FETCH_HEAD | \
	tr '\012' ' ')
147 148

case "$merge_head" in
149
'')
150
	case $? in
151 152 153 154 155 156
	0) error_on_no_merge_candidates "$@";;
	1) echo >&2 "You are not currently on a branch; you must explicitly"
	   echo >&2 "specify which branch you wish to merge:"
	   echo >&2 "  git pull <remote> <branch>"
	   exit 1;;
	*) exit $?;;
157
	esac
158
	;;
159
?*' '?*)
160 161 162 163 164
	if test -z "$orig_head"
	then
		echo >&2 "Cannot merge multiple branches into empty head"
		exit 1
	fi
165 166 167
	;;
esac

168 169
if test -z "$orig_head"
then
170 171
	git update-ref -m "initial pull" HEAD $merge_head "" &&
	git read-tree --reset -u HEAD || exit 1
172 173 174
	exit
fi

175
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
176
test true = "$rebase" &&
177 178
	exec git-rebase $strategy_args --onto $merge_head \
	${oldremoteref:-$merge_head}
179
exec git-merge $no_stat $no_commit $squash $no_ff $log_arg $strategy_args \
J
Junio C Hamano 已提交
180
	"$merge_name" HEAD $merge_head