This option causes the raw commit data to be inserted between the
changelog and the diffstat when you run git-format-patch. With a
following patch to 'git am', this will allow the exact reconstruction
of the commit to the point where the sha1 will be the same.

There is also a new config option controlling the default behaviour:

  format.complete

Signed-off-by: Vegard Nossum <vegard.nos...@oracle.com>
Previous-version: 622a0469a4970c5daac0c0323e2d6a77b3bebbdb
---
 Documentation/config/format.txt    |  7 ++++++
 Documentation/git-format-patch.txt |  9 ++++++++
 builtin/log.c                      | 35 ++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)

diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index 40cad9278f..3a38679837 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -87,6 +87,13 @@ format.useAutoBase::
        A boolean value which lets you enable the `--base=auto` option of
        format-patch by default.
 
+format.complete::
+       Provides the default value for the `--complete` option to
+       format-patch. If true, the raw commit metadata (including the
+       SHA1) is included at the bottom of the diff, before the signature.
+       This allows a recipient who has all the parent commits and/or the
+       tree to reconstruct the commit with the same SHA1.
+
 format.notes::
        Provides the default value for the `--notes` option to
        format-patch. Accepts a boolean value, or a ref which specifies
diff --git a/Documentation/git-format-patch.txt 
b/Documentation/git-format-patch.txt
index 2035d4d5d5..74fc6d8a8c 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -26,6 +26,7 @@ SYNOPSIS
                   [--no-notes | --notes[=<ref>]]
                   [--interdiff=<previous>]
                   [--range-diff=<previous> [--creation-factor=<percent>]]
+                  [--[no-]complete]
                   [--progress]
                   [<common diff options>]
                   [ <since> | <revision range> ]
@@ -325,6 +326,14 @@ you can use `--suffix=-patch` to get 
`0001-description-of-my-change-patch`.
        range are always formatted as creation patches, independently
        of this flag.
 
+--[no-]complete::
+       Include the raw commit metadata (including the SHA1) at the
+       bottom of the diff, before the signature. This allows a
+       recipient who has all the parent commits and/or the tree to
+       reconstruct the commit with the same SHA1. The default is
+       `--no-complete`, unless the `format.complete` configuration
+       option is set.
+
 --progress::
        Show progress reports on stderr as patches are generated.
 
diff --git a/builtin/log.c b/builtin/log.c
index 89873d2dc2..822a0838b6 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -783,6 +783,8 @@ enum {
        COVER_AUTO
 };
 
+static int fmt_complete;
+
 static int git_format_config(const char *var, const char *value, void *cb)
 {
        struct rev_info *rev = cb;
@@ -888,6 +890,10 @@ static int git_format_config(const char *var, const char 
*value, void *cb)
                }
                return 0;
        }
+       if (!strcmp(var, "format.complete")) {
+               fmt_complete = git_config_bool(var, value);
+               return 0;
+       }
 
        return git_log_config(var, value, cb);
 }
@@ -1490,6 +1496,23 @@ static void print_bases(struct base_tree_info *bases, 
FILE *file)
        oidclr(&bases->base_commit);
 }
 
+static void print_meta(struct rev_info *opt, struct commit *commit)
+{
+       const char *buffer = get_commit_buffer(commit, NULL);
+       const char *subject;
+
+       fprintf(opt->diffopt.file, "--\n");
+       fprintf(opt->diffopt.file, "commit %s\n", 
oid_to_hex(&commit->object.oid));
+
+       /*
+        * TODO: hex-encode to avoid mailer mangling?
+        */
+       if (find_commit_subject(buffer, &subject))
+               fprintf(opt->diffopt.file, "%.*s", (int) (subject - buffer), 
buffer);
+       else
+               fprintf(opt->diffopt.file, "%s", buffer);
+}
+
 static const char *diff_title(struct strbuf *sb, int reroll_count,
                       const char *generic, const char *rerolled)
 {
@@ -1622,6 +1645,8 @@ int cmd_format_patch(int argc, const char **argv, const 
char *prefix)
                            N_("add a signature")),
                OPT_STRING(0, "base", &base_commit, N_("base-commit"),
                           N_("add prerequisite tree info to the patch 
series")),
+               OPT_BOOL(0, "complete", &fmt_complete,
+                        N_("include all the information necessary to 
reconstruct commit exactly")),
                OPT_FILENAME(0, "signature-file", &signature_file,
                                N_("add a signature from a file")),
                OPT__QUIET(&quiet, N_("don't print the patch filenames")),
@@ -1921,6 +1946,14 @@ int cmd_format_patch(int argc, const char **argv, const 
char *prefix)
                prepare_bases(&bases, base, list, nr);
        }
 
+       if (fmt_complete) {
+               /*
+                * We need the commit buffer so that we can output the exact
+                * sequence of bytes that gets hashed as part of a commit.
+                */
+               save_commit_buffer = 1;
+       }
+
        if (in_reply_to || thread || cover_letter)
                rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
        if (in_reply_to) {
@@ -2004,6 +2037,8 @@ int cmd_format_patch(int argc, const char **argv, const 
char *prefix)
                        rev.shown_one = 0;
                if (shown) {
                        print_bases(&bases, rev.diffopt.file);
+                       if (fmt_complete)
+                               print_meta(&rev, commit);
                        if (rev.mime_boundary)
                                fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
                                       mime_boundary_leader,
--
commit 7fa59e79ef5474fb4c657fb2ff6a8341cc17c897
tree 891d334e23f950afbaaafc182384309fd8c73e48
parent d966095db01190a2196e31195ea6fa0c722aa732
author Vegard Nossum <vegard.nos...@oracle.com> 1570284959 +0200
committer Vegard Nossum <vegard.nos...@oracle.com> 1571666151 +0200

-- 
2.24.0.rc0.3.g4ba423c3c2

Reply via email to