Skip to content

Commit c871a1d

Browse files
committed
commit --amend -S: strip existing gpgsig headers
Any existing commit signature was made against the contents of the old commit, including its committer date that is about to change, and will become invalid by amending it. Signed-off-by: Junio C Hamano <[email protected]>
1 parent e3f55e0 commit c871a1d

File tree

4 files changed

+36
-8
lines changed

4 files changed

+36
-8
lines changed

builtin/commit.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
14941494
}
14951495

14961496
if (amend) {
1497-
extra = read_commit_extra_headers(current_head);
1497+
const char *exclude_gpgsig[2] = { "gpgsig", NULL };
1498+
extra = read_commit_extra_headers(current_head, exclude_gpgsig);
14981499
} else {
14991500
struct commit_extra_header **tail = &extra;
15001501
append_merge_tag_headers(parents, &tail);

commit.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -981,14 +981,15 @@ static void add_extra_header(struct strbuf *buffer,
981981
strbuf_addch(buffer, '\n');
982982
}
983983

984-
struct commit_extra_header *read_commit_extra_headers(struct commit *commit)
984+
struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
985+
const char **exclude)
985986
{
986987
struct commit_extra_header *extra = NULL;
987988
unsigned long size;
988989
enum object_type type;
989990
char *buffer = read_sha1_file(commit->object.sha1, &type, &size);
990991
if (buffer && type == OBJ_COMMIT)
991-
extra = read_commit_extra_header_lines(buffer, size);
992+
extra = read_commit_extra_header_lines(buffer, size, exclude);
992993
free(buffer);
993994
return extra;
994995
}
@@ -1002,7 +1003,23 @@ static inline int standard_header_field(const char *field, size_t len)
10021003
(len == 8 && !memcmp(field, "encoding ", 9)));
10031004
}
10041005

1005-
struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, size_t size)
1006+
static int excluded_header_field(const char *field, size_t len, const char **exclude)
1007+
{
1008+
if (!exclude)
1009+
return 0;
1010+
1011+
while (*exclude) {
1012+
size_t xlen = strlen(*exclude);
1013+
if (len == xlen &&
1014+
!memcmp(field, *exclude, xlen) && field[xlen] == ' ')
1015+
return 1;
1016+
exclude++;
1017+
}
1018+
return 0;
1019+
}
1020+
1021+
struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, size_t size,
1022+
const char **exclude)
10061023
{
10071024
struct commit_extra_header *extra = NULL, **tail = &extra, *it = NULL;
10081025
const char *line, *next, *eof, *eob;
@@ -1028,7 +1045,8 @@ struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, s
10281045
if (next <= eof)
10291046
eof = next;
10301047

1031-
if (standard_header_field(line, eof - line))
1048+
if (standard_header_field(line, eof - line) ||
1049+
excluded_header_field(line, eof - line, exclude))
10321050
continue;
10331051

10341052
it = xcalloc(1, sizeof(*it));

commit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ extern int commit_tree_extended(const char *msg, unsigned char *tree,
200200
const char *author, const char *sign_commit,
201201
struct commit_extra_header *);
202202

203-
extern struct commit_extra_header *read_commit_extra_headers(struct commit *);
204-
extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len);
203+
extern struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
204+
extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
205205

206206
extern void free_commit_extra_headers(struct commit_extra_header *extra);
207207

t/t7510-signed-commit.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ test_expect_success GPG 'create signed commits' '
2424
echo 4 >file && test_tick && git commit -a -m "fourth unsigned" &&
2525
git tag fourth-unsigned &&
2626
27-
test_tick && git commit --amend -S -m "fourth signed"
27+
test_tick && git commit --amend -S -m "fourth signed" &&
28+
git tag fourth-signed
2829
'
2930

3031
test_expect_success GPG 'show signatures' '
@@ -68,4 +69,12 @@ test_expect_success GPG 'detect fudged signature with NUL' '
6869
! grep "Good signature from" actual2
6970
'
7071

72+
test_expect_success GPG 'amending already signed commit' '
73+
git checkout fourth-signed^0 &&
74+
git commit --amend -S --no-edit &&
75+
git show -s --show-signature HEAD >actual &&
76+
grep "Good signature from" actual &&
77+
! grep "BAD signature from" actual
78+
'
79+
7180
test_done

0 commit comments

Comments
 (0)