summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/SubmittingPatches3
-rw-r--r--Documentation/git-format-patch.txt14
-rw-r--r--Documentation/git-notes.txt4
-rw-r--r--Documentation/user-manual.txt7
-rw-r--r--builtin/blame.c5
-rw-r--r--commit.h4
-rw-r--r--log-tree.c51
-rw-r--r--notes.c13
-rw-r--r--notes.h6
-rw-r--r--pretty.c22
-rw-r--r--revision.c2
-rw-r--r--revision.h1
-rwxr-xr-xt/t4014-format-patch.sh15
13 files changed, 100 insertions, 47 deletions
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 0dbf2c9843..3d8b2fe4d1 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -179,7 +179,8 @@ message starts, you can put a "From: " line to name that person.
You often want to add additional explanation about the patch,
other than the commit message itself. Place such "cover letter"
-material between the three dash lines and the diffstat.
+material between the three dash lines and the diffstat. Git-notes
+can also be inserted using the `--notes` option.
Do not attach the patch as a MIME attachment, compressed or not.
Do not let your e-mail client send quoted-printable. Do not let
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 6d43f56279..259dce4994 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -20,7 +20,7 @@ SYNOPSIS
[--ignore-if-in-upstream]
[--subject-prefix=Subject-Prefix]
[--to=<email>] [--cc=<email>]
- [--cover-letter] [--quiet]
+ [--cover-letter] [--quiet] [--notes[=<ref>]]
[<common diff options>]
[ <since> | <revision range> ]
@@ -191,6 +191,18 @@ will want to ensure that threading is disabled for `git send-email`.
containing the shortlog and the overall diffstat. You can
fill in a description in the file before sending it out.
+--notes[=<ref>]::
+ Append the notes (see linkgit:git-notes[1]) for the commit
+ after the three-dash line.
++
+The expected use case of this is to write supporting explanation for
+the commit that does not belong to the commit log message proper,
+and include it with the patch submission. While one can simply write
+these explanations after `format-patch` has run but before sending,
+keeping them as git notes allows them to be maintained between versions
+of the patch series (but see the discussion of the `notes.rewrite`
+configuration options in linkgit:git-notes[1] to use this workflow).
+
--[no]-signature=<signature>::
Add a signature to each message produced. Per RFC 3676 the signature
is separated from the body by a line with '-- ' on it. If the
diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt
index b95aafae2d..46ef0466be 100644
--- a/Documentation/git-notes.txt
+++ b/Documentation/git-notes.txt
@@ -39,6 +39,10 @@ message stored in the commit object, the notes are indented like the
message, after an unindented line saying "Notes (<refname>):" (or
"Notes:" for `refs/notes/commits`).
+Notes can also be added to patches prepared with `git format-patch` by
+using the `--notes` option. Such notes are added as a patch commentary
+after a three dash separator line.
+
To change which notes are shown by 'git log', see the
"notes.displayRef" configuration in linkgit:git-log[1].
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 85651b57ae..1b377dc207 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -1787,6 +1787,13 @@ $ git format-patch origin
will produce a numbered series of files in the current directory, one
for each patch in the current branch but not in origin/HEAD.
+`git format-patch` can include an initial "cover letter". You can insert
+commentary on individual patches after the three dash line which
+`format-patch` places after the commit message but before the patch
+itself. If you use `git notes` to track your cover letter material,
+`git format-patch --notes` will include the commit's notes in a similar
+manner.
+
You can then import these into your mail client and send them by
hand. However, if you have a lot to send at once, you may prefer to
use the linkgit:git-send-email[1] script to automate the process.
diff --git a/builtin/blame.c b/builtin/blame.c
index c27ef21c23..cfae569905 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1425,7 +1425,7 @@ static void get_commit_info(struct commit *commit,
int detailed)
{
int len;
- const char *subject;
+ const char *subject, *encoding;
char *reencoded, *message;
static char author_name[1024];
static char author_mail[1024];
@@ -1446,7 +1446,8 @@ static void get_commit_info(struct commit *commit,
die("Cannot read commit %s",
sha1_to_hex(commit->object.sha1));
}
- reencoded = reencode_commit_message(commit, NULL);
+ encoding = get_log_output_encoding();
+ reencoded = logmsg_reencode(commit, encoding);
message = reencoded ? reencoded : commit->buffer;
ret->author = author_name;
ret->author_mail = author_mail;
diff --git a/commit.h b/commit.h
index c4cd046160..b6ad8f3f30 100644
--- a/commit.h
+++ b/commit.h
@@ -86,7 +86,7 @@ struct pretty_print_context {
enum date_mode date_mode;
unsigned date_mode_explicit:1;
int need_8bit_cte;
- int show_notes;
+ char *notes_message;
struct reflog_walk_info *reflog_info;
const char *output_encoding;
};
@@ -99,8 +99,6 @@ extern int has_non_ascii(const char *text);
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
extern char *logmsg_reencode(const struct commit *commit,
const char *output_encoding);
-extern char *reencode_commit_message(const struct commit *commit,
- const char **encoding_p);
extern void get_commit_format(const char *arg, struct rev_info *);
extern const char *format_subject(struct strbuf *sb, const char *msg,
const char *line_separator);
diff --git a/log-tree.c b/log-tree.c
index c894930c18..4f86defe32 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -540,7 +540,6 @@ void show_log(struct rev_info *opt)
struct pretty_print_context ctx = {0};
opt->loginfo = NULL;
- ctx.show_notes = opt->show_notes;
if (!opt->verbose_header) {
graph_show_commit(opt->graph);
@@ -648,6 +647,18 @@ void show_log(struct rev_info *opt)
if (!commit->buffer)
return;
+ if (opt->show_notes) {
+ int raw;
+ struct strbuf notebuf = STRBUF_INIT;
+
+ raw = (opt->commit_format == CMIT_FMT_USERFORMAT);
+ format_display_notes(commit->object.sha1, &notebuf,
+ get_log_output_encoding(), raw);
+ ctx.notes_message = notebuf.len
+ ? strbuf_detach(&notebuf, NULL)
+ : xcalloc(1, 1);
+ }
+
/*
* And then the pretty-printed message itself
*/
@@ -664,6 +675,16 @@ void show_log(struct rev_info *opt)
if (opt->add_signoff)
append_signoff(&msgbuf, opt->add_signoff);
+
+ if ((ctx.fmt != CMIT_FMT_USERFORMAT) &&
+ ctx.notes_message && *ctx.notes_message) {
+ if (ctx.fmt == CMIT_FMT_EMAIL) {
+ strbuf_addstr(&msgbuf, "---\n");
+ opt->shown_dashes = 1;
+ }
+ strbuf_addstr(&msgbuf, ctx.notes_message);
+ }
+
if (opt->show_log_size) {
printf("log size %i\n", (int)msgbuf.len);
graph_show_oneline(opt->graph);
@@ -689,10 +710,12 @@ void show_log(struct rev_info *opt)
}
strbuf_release(&msgbuf);
+ free(ctx.notes_message);
}
int log_tree_diff_flush(struct rev_info *opt)
{
+ opt->shown_dashes = 0;
diffcore_std(&opt->diffopt);
if (diff_queue_is_empty()) {
@@ -704,15 +727,16 @@ int log_tree_diff_flush(struct rev_info *opt)
}
if (opt->loginfo && !opt->no_commit_id) {
- /* When showing a verbose header (i.e. log message),
- * and not in --pretty=oneline format, we would want
- * an extra newline between the end of log and the
- * output for readability.
- */
show_log(opt);
if ((opt->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) &&
opt->verbose_header &&
opt->commit_format != CMIT_FMT_ONELINE) {
+ /*
+ * When showing a verbose header (i.e. log message),
+ * and not in --pretty=oneline format, we would want
+ * an extra newline between the end of log and the
+ * diff/diffstat output for readability.
+ */
int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH;
if (opt->diffopt.output_prefix) {
struct strbuf *msg = NULL;
@@ -720,9 +744,20 @@ int log_tree_diff_flush(struct rev_info *opt)
opt->diffopt.output_prefix_data);
fwrite(msg->buf, msg->len, 1, stdout);
}
- if ((pch & opt->diffopt.output_format) == pch) {
+
+ /*
+ * We may have shown three-dashes line early
+ * between notes and the log message, in which
+ * case we only want a blank line after the
+ * notes without (an extra) three-dashes line.
+ * Otherwise, we show the three-dashes line if
+ * we are showing the patch with diffstat, but
+ * in that case, there is no extra blank line
+ * after the three-dashes line.
+ */
+ if (!opt->shown_dashes &&
+ (pch & opt->diffopt.output_format) == pch)
printf("---");
- }
putchar('\n');
}
}
diff --git a/notes.c b/notes.c
index 19b0eaada2..f63fd572d6 100644
--- a/notes.c
+++ b/notes.c
@@ -1193,10 +1193,11 @@ void free_notes(struct notes_tree *t)
* If the given notes_tree is NULL, the internal/default notes_tree will be
* used instead.
*
- * 'flags' is a bitwise combination of the flags for format_display_notes.
+ * (raw != 0) gives the %N userformat; otherwise, the note message is given
+ * for human consumption.
*/
static void format_note(struct notes_tree *t, const unsigned char *object_sha1,
- struct strbuf *sb, const char *output_encoding, int flags)
+ struct strbuf *sb, const char *output_encoding, int raw)
{
static const char utf8[] = "utf-8";
const unsigned char *sha1;
@@ -1233,7 +1234,7 @@ static void format_note(struct notes_tree *t, const unsigned char *object_sha1,
if (msglen && msg[msglen - 1] == '\n')
msglen--;
- if (flags & NOTES_SHOW_HEADER) {
+ if (!raw) {
const char *ref = t->ref;
if (!ref || !strcmp(ref, GIT_NOTES_DEFAULT_REF)) {
strbuf_addstr(sb, "\nNotes:\n");
@@ -1249,7 +1250,7 @@ static void format_note(struct notes_tree *t, const unsigned char *object_sha1,
for (msg_p = msg; msg_p < msg + msglen; msg_p += linelen + 1) {
linelen = strchrnul(msg_p, '\n') - msg_p;
- if (flags & NOTES_INDENT)
+ if (!raw)
strbuf_addstr(sb, " ");
strbuf_add(sb, msg_p, linelen);
strbuf_addch(sb, '\n');
@@ -1259,13 +1260,13 @@ static void format_note(struct notes_tree *t, const unsigned char *object_sha1,
}
void format_display_notes(const unsigned char *object_sha1,
- struct strbuf *sb, const char *output_encoding, int flags)
+ struct strbuf *sb, const char *output_encoding, int raw)
{
int i;
assert(display_notes_trees);
for (i = 0; display_notes_trees[i]; i++)
format_note(display_notes_trees[i], object_sha1, sb,
- output_encoding, flags);
+ output_encoding, raw);
}
int copy_note(struct notes_tree *t,
diff --git a/notes.h b/notes.h
index 3592b19d2d..3324c486a1 100644
--- a/notes.h
+++ b/notes.h
@@ -237,10 +237,6 @@ void prune_notes(struct notes_tree *t, int flags);
*/
void free_notes(struct notes_tree *t);
-/* Flags controlling how notes are formatted */
-#define NOTES_SHOW_HEADER 1
-#define NOTES_INDENT 2
-
struct string_list;
struct display_notes_opt {
@@ -274,7 +270,7 @@ void init_display_notes(struct display_notes_opt *opt);
* You *must* call init_display_notes() before using this function.
*/
void format_display_notes(const unsigned char *object_sha1,
- struct strbuf *sb, const char *output_encoding, int flags);
+ struct strbuf *sb, const char *output_encoding, int raw);
/*
* Load the notes tree from each ref listed in 'refs'. The output is
diff --git a/pretty.c b/pretty.c
index dba682828c..5bdc2e70bc 100644
--- a/pretty.c
+++ b/pretty.c
@@ -1100,9 +1100,8 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
}
return 0; /* unknown %g placeholder */
case 'N':
- if (c->pretty_ctx->show_notes) {
- format_display_notes(commit->object.sha1, sb,
- get_log_output_encoding(), 0);
+ if (c->pretty_ctx->notes_message) {
+ strbuf_addstr(sb, c->pretty_ctx->notes_message);
return 1;
}
return 0;
@@ -1414,16 +1413,6 @@ void pp_remainder(const struct pretty_print_context *pp,
}
}
-char *reencode_commit_message(const struct commit *commit, const char **encoding_p)
-{
- const char *encoding;
-
- encoding = get_log_output_encoding();
- if (encoding_p)
- *encoding_p = encoding;
- return logmsg_reencode(commit, encoding);
-}
-
void pretty_print_commit(const struct pretty_print_context *pp,
const struct commit *commit,
struct strbuf *sb)
@@ -1440,7 +1429,8 @@ void pretty_print_commit(const struct pretty_print_context *pp,
return;
}
- reencoded = reencode_commit_message(commit, &encoding);
+ encoding = get_log_output_encoding();
+ reencoded = logmsg_reencode(commit, encoding);
if (reencoded) {
msg = reencoded;
}
@@ -1500,10 +1490,6 @@ void pretty_print_commit(const struct pretty_print_context *pp,
if (pp->fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
strbuf_addch(sb, '\n');
- if (pp->show_notes)
- format_display_notes(commit->object.sha1, sb, encoding,
- NOTES_SHOW_HEADER | NOTES_INDENT);
-
free(reencoded);
}
diff --git a/revision.c b/revision.c
index d7d621cdbf..95d21e6472 100644
--- a/revision.c
+++ b/revision.c
@@ -2242,7 +2242,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
if (!buf.len)
strbuf_addstr(&buf, commit->buffer);
format_display_notes(commit->object.sha1, &buf,
- get_log_output_encoding(), 0);
+ get_log_output_encoding(), 1);
}
/* Find either in the commit object, or in the temporary */
diff --git a/revision.h b/revision.h
index a95bd0b3f3..059bfff812 100644
--- a/revision.h
+++ b/revision.h
@@ -111,6 +111,7 @@ struct rev_info {
/* Format info */
unsigned int shown_one:1,
+ shown_dashes:1,
show_merge:1,
show_notes:1,
show_notes_given:1,
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index ad9f69e607..16a4ca1d60 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -650,8 +650,19 @@ test_expect_success 'format-patch --in-reply-to' '
'
test_expect_success 'format-patch --signoff' '
- git format-patch -1 --signoff --stdout |
- grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+ git format-patch -1 --signoff --stdout >out &&
+ grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
+'
+
+test_expect_success 'format-patch --notes --signoff' '
+ git notes --ref test add -m "test message" HEAD &&
+ git format-patch -1 --signoff --stdout --notes=test >out &&
+ # Three dashes must come after S-o-b
+ ! sed "/^Signed-off-by: /q" out | grep "test message" &&
+ sed "1,/^Signed-off-by: /d" out | grep "test message" &&
+ # Notes message must come after three dashes
+ ! sed "/^---$/q" out | grep "test message" &&
+ sed "1,/^---$/d" out | grep "test message"
'
echo "fatal: --name-only does not make sense" > expect.name-only