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