submodule update: allow custom command to update submodule working tree

Users can set submodule.$name.update to '!command' which will cause 'command' to be run instead of checkout/merge/rebase. This allows the user finer-grained control over how the update is done. The primary motivation for this was interoperability with stgit; however being able to intercept the submodule update process may prove useful for integrating with or extending other tools. Signed-off-by: Chris Packham <judge.packham@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Chris Packham committed Jul 3, 2013 at 21:02 UTC 6cb5728c43f34a7348e128b44b80d00b9417cb19
3 files changed +38 -1
Documentation/git-submodule.txt
+3 -1
@@ -159,7 +159,9 @@ update::
159 This will make the submodules HEAD be detached unless `--rebase` or
160 `--merge` is specified or the key `submodule.$name.update` is set to
161 `rebase`, `merge` or `none`. `none` can be overridden by specifying
162 - `--checkout`.
162 + `--checkout`. Setting the key `submodule.$name.update` to `!command`
163 + will cause `command` to be run. `command` can be any arbitrary shell
164 + command that takes a single argument, namely the sha1 to update to.
165 +
166 If the submodule is not yet initialized, and you just want to use the
167 setting as stored in .gitmodules, you can automatically initialize the
git-submodule.sh
+6
@@ -860,6 +860,12 @@ Maybe you want to use 'update --init'?")"
860 say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
861 must_die_on_failure=yes
862 ;;
863 + !*)
864 + command="${update_module#!}"
865 + die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
866 + say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
867 + must_die_on_failure=yes
868 + ;;
869 *)
870 command="git checkout $subforce -q"
871 die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
t/t7406-submodule-update.sh
+29
@@ -294,6 +294,35 @@ test_expect_success 'submodule update - checkout in .git/config' '
294 )
295 '
296
297 +test_expect_success 'submodule update - command in .git/config' '
298 + (cd super &&
299 + git config submodule.submodule.update "!git checkout"
300 + ) &&
301 + (cd super/submodule &&
302 + git reset --hard HEAD^
303 + ) &&
304 + (cd super &&
305 + (cd submodule &&
306 + compare_head
307 + ) &&
308 + git submodule update submodule &&
309 + cd submodule &&
310 + ! compare_head
311 + )
312 +'
313 +
314 +test_expect_success 'submodule update - command in .git/config catches failure' '
315 + (cd super &&
316 + git config submodule.submodule.update "!false"
317 + ) &&
318 + (cd super/submodule &&
319 + git reset --hard HEAD^
320 + ) &&
321 + (cd super &&
322 + test_must_fail git submodule update submodule
323 + )
324 +'
325 +
326 test_expect_success 'submodule init picks up rebase' '
327 (cd super &&
328 git config -f .gitmodules submodule.rebasing.update rebase &&