Skip to content

Commit d9eb3e4

Browse files
committed
Merge branch 'pw/subtree-gpg-sign' into jch
"git subtree" (in contrib/) learns to grok GPG signing its commits. * pw/subtree-gpg-sign: contrib/subtree: add -S/--gpg-sign contrib/subtree: parse using --stuck-long
2 parents b450482 + fea50ce commit d9eb3e4

File tree

3 files changed

+158
-40
lines changed

3 files changed

+158
-40
lines changed

contrib/subtree/git-subtree.adoc

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ git-subtree - Merge subtrees together and split repository into subtrees
99
SYNOPSIS
1010
--------
1111
[verse]
12-
'git subtree' [<options>] -P <prefix> add <local-commit>
13-
'git subtree' [<options>] -P <prefix> add <repository> <remote-ref>
14-
'git subtree' [<options>] -P <prefix> merge <local-commit> [<repository>]
15-
'git subtree' [<options>] -P <prefix> split [<local-commit>]
12+
'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <local-commit>
13+
'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <repository> <remote-ref>
14+
'git subtree' [<options>] -P <prefix> [-S[<keyid>]] merge <local-commit> [<repository>]
15+
'git subtree' [<options>] -P <prefix> [-S[<keyid>]] split [<local-commit>]
1616

1717
[verse]
18-
'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>
19-
'git subtree' [<options>] -P <prefix> push <repository> <refspec>
18+
'git subtree' [<options>] -P <prefix> [-S[<keyid>]] pull <repository> <remote-ref>
19+
'git subtree' [<options>] -P <prefix> [-S[<keyid>]] push <repository> <refspec>
2020

2121
DESCRIPTION
2222
-----------
@@ -149,6 +149,13 @@ OPTIONS FOR ALL COMMANDS
149149
want to manipulate. This option is mandatory
150150
for all commands.
151151

152+
-S[<keyid>]::
153+
--gpg-sign[=<keyid>]::
154+
--no-gpg-sign::
155+
GPG-sign commits. The `keyid` argument is optional and
156+
defaults to the committer identity; `--no-gpg-sign` is useful to
157+
countermand a `--gpg-sign` option given earlier on the command line.
158+
152159
OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin')
153160
-----------------------------------------------------------------------------------
154161
These options for 'add' and 'merge' may also be given to 'pull' (which

contrib/subtree/git-subtree.sh

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ then
2626
fi
2727

2828
OPTS_SPEC="\
29-
git subtree add --prefix=<prefix> <commit>
30-
git subtree add --prefix=<prefix> <repository> <ref>
31-
git subtree merge --prefix=<prefix> <commit>
32-
git subtree split --prefix=<prefix> [<commit>]
33-
git subtree pull --prefix=<prefix> <repository> <ref>
34-
git subtree push --prefix=<prefix> <repository> <refspec>
29+
git subtree add --prefix=<prefix> [-S[=<key-id>]] <commit>
30+
git subtree add --prefix=<prefix> [-S[=<key-id>]] <repository> <ref>
31+
git subtree merge --prefix=<prefix> [-S[=<key-id>]] <commit>
32+
git subtree split --prefix=<prefix> [-S[=<key-id>]] [<commit>]
33+
git subtree pull --prefix=<prefix> [-S[=<key-id>]] <repository> <ref>
34+
git subtree push --prefix=<prefix> [-S[=<key-id>]] <repository> <refspec>
3535
--
3636
h,help! show the help
3737
q,quiet! quiet
@@ -46,6 +46,7 @@ rejoin merge the new branch back into HEAD
4646
options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin')
4747
squash merge subtree changes as a single commit
4848
m,message!= use the given message as the commit message for the merge commit
49+
S,gpg-sign?key-id GPG-sign commits. The keyid argument is optional and defaults to the committer identity
4950
"
5051

5152
indent=0
@@ -115,7 +116,7 @@ main () {
115116
then
116117
set -- -h
117118
fi
118-
set_args="$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
119+
set_args="$(echo "$OPTS_SPEC" | git rev-parse --parseopt --stuck-long -- "$@" || echo exit $?)"
119120
eval "$set_args"
120121
. git-sh-setup
121122
require_work_tree
@@ -131,9 +132,6 @@ main () {
131132
opt="$1"
132133
shift
133134
case "$opt" in
134-
--annotate|-b|-P|-m|--onto)
135-
shift
136-
;;
137135
--rejoin)
138136
arg_split_rejoin=1
139137
;;
@@ -171,48 +169,44 @@ main () {
171169
arg_split_annotate=
172170
arg_addmerge_squash=
173171
arg_addmerge_message=
172+
arg_gpg_sign=
174173
while test $# -gt 0
175174
do
176175
opt="$1"
177176
shift
178177

179178
case "$opt" in
180-
-q)
179+
--quiet)
181180
arg_quiet=1
182181
;;
183-
-d)
182+
--debug)
184183
arg_debug=1
185184
;;
186-
--annotate)
185+
--annotate=*)
187186
test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command"
188-
arg_split_annotate="$1"
189-
shift
187+
arg_split_annotate="${opt#*=}"
190188
;;
191189
--no-annotate)
192190
test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command"
193191
arg_split_annotate=
194192
;;
195-
-b)
193+
--branch=*)
196194
test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command"
197-
arg_split_branch="$1"
198-
shift
195+
arg_split_branch="${opt#*=}"
199196
;;
200-
-P)
201-
arg_prefix="${1%/}"
202-
shift
197+
--prefix=*)
198+
arg_prefix="${opt#*=}"
203199
;;
204-
-m)
200+
--message=*)
205201
test -n "$allow_addmerge" || die_incompatible_opt "$opt" "$arg_command"
206-
arg_addmerge_message="$1"
207-
shift
202+
arg_addmerge_message="${opt#*=}"
208203
;;
209204
--no-prefix)
210205
arg_prefix=
211206
;;
212-
--onto)
207+
--onto=*)
213208
test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command"
214-
arg_split_onto="$1"
215-
shift
209+
arg_split_onto="${opt#*=}"
216210
;;
217211
--no-onto)
218212
test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command"
@@ -240,6 +234,9 @@ main () {
240234
test -n "$allow_addmerge" || die_incompatible_opt "$opt" "$arg_command"
241235
arg_addmerge_squash=
242236
;;
237+
--gpg-sign=* | --gpg-sign | --no-gpg-sign)
238+
arg_gpg_sign="$opt"
239+
;;
243240
--)
244241
break
245242
;;
@@ -272,6 +269,7 @@ main () {
272269
debug "quiet: {$arg_quiet}"
273270
debug "dir: {$dir}"
274271
debug "opts: {$*}"
272+
debug "gpg-sign: {$arg_gpg_sign}"
275273
debug
276274

277275
"cmd_$arg_command" "$@"
@@ -537,7 +535,7 @@ copy_commit () {
537535
printf "%s" "$arg_split_annotate"
538536
cat
539537
) |
540-
git commit-tree "$2" $3 # reads the rest of stdin
538+
git commit-tree $arg_gpg_sign "$2" $3 # reads the rest of stdin
541539
) || die "fatal: can't copy commit $1"
542540
}
543541

@@ -683,10 +681,10 @@ new_squash_commit () {
683681
if test -n "$old"
684682
then
685683
squash_msg "$dir" "$oldsub" "$newsub" |
686-
git commit-tree "$tree" -p "$old" || exit $?
684+
git commit-tree $arg_gpg_sign "$tree" -p "$old" || exit $?
687685
else
688686
squash_msg "$dir" "" "$newsub" |
689-
git commit-tree "$tree" || exit $?
687+
git commit-tree $arg_gpg_sign "$tree" || exit $?
690688
fi
691689
}
692690

@@ -925,11 +923,11 @@ cmd_add_commit () {
925923
then
926924
rev=$(new_squash_commit "" "" "$rev") || exit $?
927925
commit=$(add_squashed_msg "$rev" "$dir" |
928-
git commit-tree "$tree" $headp -p "$rev") || exit $?
926+
git commit-tree $arg_gpg_sign "$tree" $headp -p "$rev") || exit $?
929927
else
930928
revp=$(peel_committish "$rev") || exit $?
931929
commit=$(add_msg "$dir" $headrev "$rev" |
932-
git commit-tree "$tree" $headp -p "$revp") || exit $?
930+
git commit-tree $arg_gpg_sign "$tree" $headp -p "$revp") || exit $?
933931
fi
934932
git reset "$commit" || exit $?
935933

@@ -1080,9 +1078,9 @@ cmd_merge () {
10801078
if test -n "$arg_addmerge_message"
10811079
then
10821080
git merge --no-ff -Xsubtree="$arg_prefix" \
1083-
--message="$arg_addmerge_message" "$rev"
1081+
--message="$arg_addmerge_message" $arg_gpg_sign "$rev"
10841082
else
1085-
git merge --no-ff -Xsubtree="$arg_prefix" $rev
1083+
git merge --no-ff -Xsubtree="$arg_prefix" $arg_gpg_sign $rev
10861084
fi
10871085
}
10881086

contrib/subtree/t/t7900-subtree.sh

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and push subcommands of git subtree.
1111

1212
TEST_DIRECTORY=$(pwd)/../../../t
1313
. "$TEST_DIRECTORY"/test-lib.sh
14+
. "$TEST_DIRECTORY"/lib-gpg.sh
1415

1516
# Use our own wrapper around test-lib.sh's test_create_repo, in order
1617
# to set log.date=relative. `git subtree` parses the output of `git
@@ -1563,4 +1564,116 @@ test_expect_success 'subtree descendant check' '
15631564
)
15641565
'
15651566

1567+
test_expect_success GPG 'add subproj with GPG signing using -S flag' '
1568+
subtree_test_create_repo "$test_count" &&
1569+
subtree_test_create_repo "$test_count/sub proj" &&
1570+
test_create_commit "$test_count" main1 &&
1571+
test_create_commit "$test_count/sub proj" sub1 &&
1572+
(
1573+
cd "$test_count" &&
1574+
git fetch ./"sub proj" HEAD &&
1575+
git subtree add --prefix="sub dir" -S FETCH_HEAD &&
1576+
git verify-commit HEAD &&
1577+
test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''"
1578+
)
1579+
'
1580+
1581+
test_expect_success GPG 'add subproj with GPG signing using --gpg-sign flag' '
1582+
subtree_test_create_repo "$test_count" &&
1583+
subtree_test_create_repo "$test_count/sub proj" &&
1584+
test_create_commit "$test_count" main1 &&
1585+
test_create_commit "$test_count/sub proj" sub1 &&
1586+
(
1587+
cd "$test_count" &&
1588+
git fetch ./"sub proj" HEAD &&
1589+
git subtree add --prefix="sub dir" --gpg-sign FETCH_HEAD &&
1590+
git verify-commit HEAD &&
1591+
test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''"
1592+
)
1593+
'
1594+
1595+
test_expect_success GPG 'add subproj with GPG signing using specific key ID' '
1596+
subtree_test_create_repo "$test_count" &&
1597+
subtree_test_create_repo "$test_count/sub proj" &&
1598+
test_create_commit "$test_count" main1 &&
1599+
test_create_commit "$test_count/sub proj" sub1 &&
1600+
(
1601+
cd "$test_count" &&
1602+
git fetch ./"sub proj" HEAD &&
1603+
git subtree add --prefix="sub dir" -S"$GIT_COMMITTER_EMAIL" FETCH_HEAD &&
1604+
git verify-commit HEAD &&
1605+
test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''"
1606+
)
1607+
'
1608+
1609+
test_expect_success GPG 'merge with GPG signing' '
1610+
subtree_test_create_repo "$test_count" &&
1611+
subtree_test_create_repo "$test_count/sub proj" &&
1612+
test_create_commit "$test_count" main1 &&
1613+
test_create_commit "$test_count/sub proj" sub1 &&
1614+
(
1615+
cd "$test_count" &&
1616+
git fetch ./"sub proj" HEAD &&
1617+
git subtree add --prefix="sub dir" FETCH_HEAD
1618+
) &&
1619+
test_create_commit "$test_count/sub proj" sub2 &&
1620+
(
1621+
cd "$test_count" &&
1622+
git fetch ./"sub proj" HEAD &&
1623+
git subtree merge --prefix="sub dir" -S FETCH_HEAD &&
1624+
git verify-commit HEAD
1625+
)
1626+
'
1627+
1628+
test_expect_success GPG 'split with GPG signing and --rejoin' '
1629+
subtree_test_create_repo "$test_count" &&
1630+
subtree_test_create_repo "$test_count/sub proj" &&
1631+
test_create_commit "$test_count" main1 &&
1632+
test_create_commit "$test_count/sub proj" sub1 &&
1633+
(
1634+
cd "$test_count" &&
1635+
git fetch ./"sub proj" HEAD &&
1636+
git subtree add --prefix="sub dir" FETCH_HEAD
1637+
) &&
1638+
test_create_commit "$test_count" "sub dir/main-sub1" &&
1639+
(
1640+
cd "$test_count" &&
1641+
git subtree split --prefix="sub dir" --rejoin -S &&
1642+
git verify-commit HEAD
1643+
)
1644+
'
1645+
1646+
test_expect_success GPG 'add with --squash and GPG signing' '
1647+
subtree_test_create_repo "$test_count" &&
1648+
subtree_test_create_repo "$test_count/sub proj" &&
1649+
test_create_commit "$test_count" main1 &&
1650+
test_create_commit "$test_count/sub proj" sub1 &&
1651+
(
1652+
cd "$test_count" &&
1653+
git fetch ./"sub proj" HEAD &&
1654+
git subtree add --prefix="sub dir" --squash -S FETCH_HEAD &&
1655+
git verify-commit HEAD &&
1656+
# With --squash, the commit subject should reference the squash commit (first parent of merge)
1657+
squash_commit=$(git rev-parse HEAD^2) &&
1658+
test "$(last_commit_subject)" = "Merge commit '\''$squash_commit'\'' as '\''sub dir'\''"
1659+
)
1660+
'
1661+
1662+
test_expect_success GPG 'pull with GPG signing' '
1663+
subtree_test_create_repo "$test_count" &&
1664+
subtree_test_create_repo "$test_count/sub proj" &&
1665+
test_create_commit "$test_count" main1 &&
1666+
test_create_commit "$test_count/sub proj" sub1 &&
1667+
(
1668+
cd "$test_count" &&
1669+
git subtree add --prefix="sub dir" ./"sub proj" HEAD
1670+
) &&
1671+
test_create_commit "$test_count/sub proj" sub2 &&
1672+
(
1673+
cd "$test_count" &&
1674+
git subtree pull --prefix="sub dir" -S ./"sub proj" HEAD &&
1675+
git verify-commit HEAD
1676+
)
1677+
'
1678+
15661679
test_done

0 commit comments

Comments
 (0)