@@ -21,6 +21,10 @@ is_symlink () {
21
21
test " $1 " = 120000
22
22
}
23
23
24
+ is_submodule () {
25
+ test " $1 " = 160000
26
+ }
27
+
24
28
local_present () {
25
29
test -n " $local_mode "
26
30
}
@@ -35,7 +39,8 @@ base_present () {
35
39
36
40
cleanup_temp_files () {
37
41
if test " $1 " = --save-backup ; then
38
- mv -- " $BACKUP " " $MERGED .orig"
42
+ rm -rf -- " $MERGED .orig"
43
+ test -e " $BACKUP " && mv -- " $BACKUP " " $MERGED .orig"
39
44
rm -f -- " $LOCAL " " $REMOTE " " $BASE "
40
45
else
41
46
rm -f -- " $LOCAL " " $REMOTE " " $BASE " " $BACKUP "
@@ -52,11 +57,13 @@ describe_file () {
52
57
echo " deleted"
53
58
elif is_symlink " $mode " ; then
54
59
echo " a symbolic link -> '$( cat " $file " ) '"
60
+ elif is_submodule " $mode " ; then
61
+ echo " submodule commit $file "
55
62
else
56
63
if base_present; then
57
- echo " modified"
64
+ echo " modified file "
58
65
else
59
- echo " created"
66
+ echo " created file "
60
67
fi
61
68
fi
62
69
}
@@ -112,6 +119,67 @@ resolve_deleted_merge () {
112
119
done
113
120
}
114
121
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
+
115
183
checkout_staged_file () {
116
184
tmpfile=$( expr " $( git checkout-index --temp --stage=" $1 " " $2 " ) " : ' \([^ ]*\) ' )
117
185
@@ -139,13 +207,23 @@ merge_file () {
139
207
REMOTE=" ./$MERGED .REMOTE.$ext "
140
208
BASE=" ./$MERGED .BASE.$ext "
141
209
142
- mv -- " $MERGED " " $BACKUP "
143
- cp -- " $BACKUP " " $MERGED "
144
-
145
210
base_mode=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==1) print $1;}' )
146
211
local_mode=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==2) print $1;}' )
147
212
remote_mode=$( git ls-files -u -- " $MERGED " | awk ' {if ($3==3) print $1;}' )
148
213
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
+
149
227
base_present && checkout_staged_file 1 " $MERGED " " $BASE "
150
228
local_present && checkout_staged_file 2 " $MERGED " " $LOCAL "
151
229
remote_present && checkout_staged_file 3 " $MERGED " " $REMOTE "
0 commit comments