@@ -21,6 +21,10 @@ is_symlink () {
2121 test " $1 " = 120000
2222}
2323
24+ is_submodule () {
25+ test " $1 " = 160000
26+ }
27+
2428local_present () {
2529 test -n " $local_mode "
2630}
@@ -35,7 +39,8 @@ base_present () {
3539
3640cleanup_temp_files () {
3741 if test " $1 " = --save-backup ; then
38- mv -- " $BACKUP " " $MERGED .orig"
42+ rm -rf -- " $MERGED .orig"
43+ test -e " $BACKUP " && mv -- " $BACKUP " " $MERGED .orig"
3944 rm -f -- " $LOCAL " " $REMOTE " " $BASE "
4045 else
4146 rm -f -- " $LOCAL " " $REMOTE " " $BASE " " $BACKUP "
@@ -52,11 +57,13 @@ describe_file () {
5257 echo " deleted"
5358 elif is_symlink " $mode " ; then
5459 echo " a symbolic link -> '$( cat " $file " ) '"
60+ elif is_submodule " $mode " ; then
61+ echo " submodule commit $file "
5562 else
5663 if base_present; then
57- echo " modified"
64+ echo " modified file "
5865 else
59- echo " created"
66+ echo " created file "
6067 fi
6168 fi
6269}
@@ -112,6 +119,67 @@ resolve_deleted_merge () {
112119 done
113120}
114121
122+ resolve_submodule_merge () {
123+ while true ; do
124+ printf " Use (l)ocal or (r)emote, or (a)bort? "
125+ read ans
126+ case " $ans " in
127+ [lL]* )
128+ if ! local_present; then
129+ if test -n " $( git ls-tree HEAD -- " $MERGED " ) " ; then
130+ # Local isn't present, but it's a subdirectory
131+ git ls-tree --full-name -r HEAD -- " $MERGED " | git update-index --index-info || exit $?
132+ else
133+ test -e " $MERGED " && mv -- " $MERGED " " $BACKUP "
134+ git update-index --force-remove " $MERGED "
135+ cleanup_temp_files --save-backup
136+ fi
137+ elif is_submodule " $local_mode " ; then
138+ stage_submodule " $MERGED " " $local_sha1 "
139+ else
140+ git checkout-index -f --stage=2 -- " $MERGED "
141+ git add -- " $MERGED "
142+ fi
143+ return 0
144+ ;;
145+ [rR]* )
146+ if ! remote_present; then
147+ if test -n " $( git ls-tree MERGE_HEAD -- " $MERGED " ) " ; then
148+ # Remote isn't present, but it's a subdirectory
149+ git ls-tree --full-name -r MERGE_HEAD -- " $MERGED " | git update-index --index-info || exit $?
150+ else
151+ test -e " $MERGED " && mv -- " $MERGED " " $BACKUP "
152+ git update-index --force-remove " $MERGED "
153+ fi
154+ elif is_submodule " $remote_mode " ; then
155+ ! is_submodule " $local_mode " && test -e " $MERGED " && mv -- " $MERGED " " $BACKUP "
156+ stage_submodule " $MERGED " " $remote_sha1 "
157+ else
158+ test -e " $MERGED " && mv -- " $MERGED " " $BACKUP "
159+ git checkout-index -f --stage=3 -- " $MERGED "
160+ git add -- " $MERGED "
161+ fi
162+ cleanup_temp_files --save-backup
163+ return 0
164+ ;;
165+ [aA]* )
166+ return 1
167+ ;;
168+ esac
169+ done
170+ }
171+
172+ stage_submodule () {
173+ path=" $1 "
174+ submodule_sha1=" $2 "
175+ mkdir -p " $path " || die " fatal: unable to create directory for module at $path "
176+ # Find $path relative to work tree
177+ work_tree_root=$( cd_to_toplevel && pwd)
178+ work_rel_path=$( cd " $path " && GIT_WORK_TREE=" ${work_tree_root} " git rev-parse --show-prefix)
179+ test -n " $work_rel_path " || die " fatal: unable to get path of module $path relative to work tree"
180+ git update-index --add --replace --cacheinfo 160000 " $submodule_sha1 " " ${work_rel_path%/ } " || die
181+ }
182+
115183checkout_staged_file () {
116184 tmpfile=$( expr " $( git checkout-index --temp --stage=" $1 " " $2 " ) " : ' \([^ ]*\) ' )
117185
@@ -139,13 +207,23 @@ merge_file () {
139207 REMOTE=" ./$MERGED .REMOTE.$ext "
140208 BASE=" ./$MERGED .BASE.$ext "
141209
142- mv -- " $MERGED " " $BACKUP "
143- cp -- " $BACKUP " " $MERGED "
144-
145210 base_mode=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==1) print $1;}' )
146211 local_mode=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==2) print $1;}' )
147212 remote_mode=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==3) print $1;}' )
148213
214+ if is_submodule " $local_mode " || is_submodule " $remote_mode " ; then
215+ echo " Submodule merge conflict for '$MERGED ':"
216+ local_sha1=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==2) print $2;}' )
217+ remote_sha1=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==3) print $2;}' )
218+ describe_file " $local_mode " " local" " $local_sha1 "
219+ describe_file " $remote_mode " " remote" " $remote_sha1 "
220+ resolve_submodule_merge
221+ return
222+ fi
223+
224+ mv -- " $MERGED " " $BACKUP "
225+ cp -- " $BACKUP " " $MERGED "
226+
149227 base_present && checkout_staged_file 1 " $MERGED " " $BASE "
150228 local_present && checkout_staged_file 2 " $MERGED " " $LOCAL "
151229 remote_present && checkout_staged_file 3 " $MERGED " " $REMOTE "
0 commit comments