git-pull.sh 6.4 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= diffstat= no_commit= squash= no_ff= log_arg= verbosity=
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
T
Tuncer Ayaz 已提交
26
	-q|--quiet)
27
		verbosity="$verbosity -q" ;;
T
Tuncer Ayaz 已提交
28
	-v|--verbose)
29
		verbosity="$verbosity -v" ;;
30
	-n|--no-stat|--no-summary)
31
		diffstat=--no-stat ;;
32
	--stat|--summary)
33
		diffstat=--stat ;;
34 35
	--log|--no-log)
		log_arg=$1 ;;
36 37
	--no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
		no_commit=--no-commit ;;
38 39
	--c|--co|--com|--comm|--commi|--commit)
		no_commit=--commit ;;
J
Junio C Hamano 已提交
40 41
	--sq|--squ|--squa|--squas|--squash)
		squash=--squash ;;
42 43 44 45 46 47
	--no-sq|--no-squ|--no-squa|--no-squas|--no-squash)
		squash=--no-squash ;;
	--ff)
		no_ff=--ff ;;
	--no-ff)
		no_ff=--no-ff ;;
48 49 50 51 52
	-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
		--strateg=*|--strategy=*|\
	-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
		case "$#,$1" in
		*,*=*)
D
Dennis Stosberg 已提交
53
			strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;;
54 55 56 57 58 59 60 61
		1,*)
			usage ;;
		*)
			strategy="$2"
			shift ;;
		esac
		strategy_args="${strategy_args}-s $strategy "
		;;
62 63 64 65 66 67
	-r|--r|--re|--reb|--reba|--rebas|--rebase)
		rebase=true
		;;
	--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)
		rebase=false
		;;
68 69 70
	-h|--h|--he|--hel|--help)
		usage
		;;
71 72
	*)
		# Pass thru anything that may be meant for fetch.
73
		break
74 75 76 77 78
		;;
	esac
	shift
done

79 80 81 82 83 84 85 86 87 88 89 90 91
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/}
92
	upstream=$(git config "branch.$curr_branch.merge")
93
	remote=$(git config "branch.$curr_branch.remote")
94

95 96 97 98 99 100 101 102 103
	if [ $# -gt 1 ]; then
		echo "There are no candidates for merging in the refs that you just fetched."
		echo "Generally this means that you provided a wildcard refspec which had no"
		echo "matches on the remote end."
	elif [ $# -gt 0 ] && [ "$1" != "$remote" ]; then
		echo "You asked to pull from the remote '$1', but did not specify"
		echo "a branch to merge. Because this is not the default configured remote"
		echo "for your current branch, you must specify a branch on the command line."
	elif [ -z "$curr_branch" ]; then
104 105 106 107 108
		echo "You are not currently on a branch, so I cannot use any"
		echo "'branch.<branchname>.merge' in your configuration file."
		echo "Please specify which branch you want to merge on the command"
		echo "line and try again (e.g. 'git pull <repository> <refspec>')."
		echo "See git-pull(1) for details."
109
	elif [ -z "$upstream" ]; then
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
		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 "specify 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."
		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."
127
	else
128 129
		echo "Your configuration specifies to merge the ref '${upstream#refs/heads/}' from the"
		echo "remote, but no such ref was fetched."
130
	fi
131 132 133
	exit 1
}

134
test true = "$rebase" && {
135 136 137 138 139 140 141 142 143 144 145 146 147
	if ! git rev-parse -q --verify HEAD >/dev/null
	then
		# On an unborn branch
		if test -f "$GIT_DIR/index"
		then
			die "updating an unborn branch with changes added to the index"
		fi
	else
		git update-index --ignore-submodules --refresh &&
		git diff-files --ignore-submodules --quiet &&
		git diff-index --ignore-submodules --cached --quiet HEAD -- ||
		die "refusing to pull with rebase: your working tree is not up-to-date"
	fi
148
	oldremoteref= &&
149
	. git-parse-remote &&
150 151 152 153 154 155 156 157 158 159
	remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
	oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
	for reflog in $(git rev-list -g $remoteref 2>/dev/null)
	do
		if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
		then
			oldremoteref="$reflog"
			break
		fi
	done
160
}
M
Miklos Vajna 已提交
161
orig_head=$(git rev-parse -q --verify HEAD)
T
Tuncer Ayaz 已提交
162
git fetch $verbosity --update-head-ok "$@" || exit 1
163

M
Miklos Vajna 已提交
164
curr_head=$(git rev-parse -q --verify HEAD)
165
if test -n "$orig_head" && test "$curr_head" != "$orig_head"
166 167 168 169 170 171 172 173
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."
174
	echo >&2 "Warning: fast forwarding your working tree from"
175
	echo >&2 "Warning: commit $orig_head."
176
	git update-index -q --refresh
177
	git read-tree -u -m "$orig_head" "$curr_head" ||
178 179 180 181 182 183 184
		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.'

185 186
fi

187 188 189
merge_head=$(sed -e '/	not-for-merge	/d' \
	-e 's/	.*//' "$GIT_DIR"/FETCH_HEAD | \
	tr '\012' ' ')
190 191

case "$merge_head" in
192
'')
J
Junio C Hamano 已提交
193
	error_on_no_merge_candidates "$@"
194
	;;
195
?*' '?*)
196 197
	if test -z "$orig_head"
	then
198
		die "Cannot merge multiple branches into empty head"
199
	fi
200 201
	if test true = "$rebase"
	then
202
		die "Cannot rebase onto multiple branches"
203
	fi
204 205 206
	;;
esac

207 208
if test -z "$orig_head"
then
209
	git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
210
	git read-tree --reset -u HEAD || exit 1
211 212 213
	exit
fi

214
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
215
test true = "$rebase" &&
216
	exec git-rebase $diffstat $strategy_args --onto $merge_head \
217
	${oldremoteref:-$merge_head}
218
exec git-merge $diffstat $no_commit $squash $no_ff $log_arg $strategy_args \
T
Tuncer Ayaz 已提交
219
	"$merge_name" HEAD $merge_head $verbosity