{"thread":{"id":"28891","subject":"[PATCH v3 00/17] Pulling signed tags","startedAt":"2011-11-09T01:01:46Z","lastAt":"2011-11-09T13:39:32Z","messageCount":21,"participants":["Junio C Hamano","Robin H. Johnson"],"isPatch":true,"patchVersion":3,"patchTotal":17},"messages":[{"id":"179174","messageId":"1320800523-5407-1-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":null,"subject":"[PATCH v3 00/17] Pulling signed tags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:46Z","receivedAt":"2011-11-09T01:01:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The third iteration of the fourth approach to give more confidence on the\nauthenticity of history, but the third approach of giving GPG signature to\nindividual commits is independently useful and has been rebased on top.\n\nNotable differences from the previous round are:\n\n - The way to handle multi-line header lines in a commit object is\n   officially defined --- the second and subsequent lines begin with a\n   single SP to indent them. The \"mergetag\" header and \"gpgsig\" header are\n   now expressed using it;\n\n - commit_tree() figures out what \"mergetag\" extra headers to generate by\n   inspecting the annotation added to the util field of parent commits as\n   before; it uses a new lower level commit_tree_extended() API to record\n   the extra headers.\n\n - \"commit --amend\" propagates \"mergetag\" extra header from the original\n   (but not \"gpgsig\" for obvious reasons).\n\n\n . Split GPG interface into its own helper library\n . fetch: do not store peeled tag object names in FETCH_HEAD\n . merge: notice local merging of tags and keep it unwrapped\n . fetch: allow \"git fetch $there v1.0\" to fetch a tag\n . refs DWIMmery: use the same rule for both \"git fetch\" and others\n . fmt-merge-msg: avoid early returns\n . fmt-merge-msg: package options into a structure\n . fmt-merge-msg: Add contents of merged tag in the merge message\n . merge: make usage of commit->util more extensible\n . merge: record tag objects without peeling in MERGE_HEAD\n\n   Unchanged from the previous round.\n\n . commit: copy merged signed tags to headers of merge commit\n\n   The way commit_tree() notices that some parents are signed tags and\n   copies them to \"mergetag\" extra header has been reimplemented by using\n   the new commit_tree_extended() API.\n\n . merge: force edit mode when merging a tag object\n\n   Unchanged.\n\n . commit: teach --amend to carry forward extra headers\n\n   New. This is the reason commit_tree_extended() was introduced. The\n   plumbing \"git commit-tree\" should learn to read list of extra headers\n   and record them to its product to help scripts (e.g. \"rebase -i\"), but\n   it is outside the scope of this series for now.\n\n . commit: teach --gpg-sign option\n . log: --show-signature\n\n   These two use the new multi-line header format, but otherwise\n   unchanged.\n\n . test \"commit -S\" and \"log --show-signature\"\n . pretty: %G[?GS] placeholders\n\n   Unchanged.\n\n Makefile                                           |    2 +\n builtin.h                                          |    8 +-\n builtin/commit-tree.c                              |   24 ++-\n builtin/commit.c                                   |   28 ++-\n builtin/fetch.c                                    |    3 +-\n builtin/fmt-merge-msg.c                            |  113 +++++++--\n builtin/merge.c                                    |  109 +++++----\n builtin/tag.c                                      |   76 +------\n builtin/verify-tag.c                               |   35 +---\n cache.h                                            |    2 +-\n commit.c                                           |  260 +++++++++++++++++++-\n commit.h                                           |   39 +++-\n gpg-interface.c                                    |  138 +++++++++++\n gpg-interface.h                                    |   10 +\n log-tree.c                                         |   39 +++\n merge-recursive.c                                  |   13 +-\n notes-cache.c                                      |    2 +-\n notes-merge.c                                      |    2 +-\n pretty.c                                           |   86 +++++++\n refs.c                                             |    7 -\n revision.c                                         |    2 +\n revision.h                                         |    1 +\n strbuf.c                                           |   14 +\n strbuf.h                                           |    8 +\n t/t4202-log.sh                                     |    4 +-\n t/t5510-fetch.sh                                   |    5 +-\n t/t5515/fetch.br-branches-default                  |    6 +-\n t/t5515/fetch.br-branches-default-merge            |    6 +-\n ...etch.br-branches-default-merge_branches-default |    6 +-\n t/t5515/fetch.br-branches-default-octopus          |    6 +-\n ...ch.br-branches-default-octopus_branches-default |    6 +-\n t/t5515/fetch.br-branches-default_branches-default |    6 +-\n t/t5515/fetch.br-branches-one                      |    6 +-\n t/t5515/fetch.br-branches-one-merge                |    6 +-\n t/t5515/fetch.br-branches-one-merge_branches-one   |    6 +-\n t/t5515/fetch.br-branches-one-octopus              |    6 +-\n t/t5515/fetch.br-branches-one-octopus_branches-one |    6 +-\n t/t5515/fetch.br-branches-one_branches-one         |    6 +-\n t/t5515/fetch.br-config-explicit                   |    6 +-\n t/t5515/fetch.br-config-explicit-merge             |    6 +-\n .../fetch.br-config-explicit-merge_config-explicit |    6 +-\n t/t5515/fetch.br-config-explicit-octopus           |    6 +-\n ...etch.br-config-explicit-octopus_config-explicit |    6 +-\n t/t5515/fetch.br-config-explicit_config-explicit   |    6 +-\n t/t5515/fetch.br-config-glob                       |    6 +-\n t/t5515/fetch.br-config-glob-merge                 |    6 +-\n t/t5515/fetch.br-config-glob-merge_config-glob     |    6 +-\n t/t5515/fetch.br-config-glob-octopus               |    6 +-\n t/t5515/fetch.br-config-glob-octopus_config-glob   |    6 +-\n t/t5515/fetch.br-config-glob_config-glob           |    6 +-\n t/t5515/fetch.br-remote-explicit                   |    6 +-\n t/t5515/fetch.br-remote-explicit-merge             |    6 +-\n .../fetch.br-remote-explicit-merge_remote-explicit |    6 +-\n t/t5515/fetch.br-remote-explicit-octopus           |    6 +-\n ...etch.br-remote-explicit-octopus_remote-explicit |    6 +-\n t/t5515/fetch.br-remote-explicit_remote-explicit   |    6 +-\n t/t5515/fetch.br-remote-glob                       |    6 +-\n t/t5515/fetch.br-remote-glob-merge                 |    6 +-\n t/t5515/fetch.br-remote-glob-merge_remote-glob     |    6 +-\n t/t5515/fetch.br-remote-glob-octopus               |    6 +-\n t/t5515/fetch.br-remote-glob-octopus_remote-glob   |    6 +-\n t/t5515/fetch.br-remote-glob_remote-glob           |    6 +-\n t/t5515/fetch.br-unconfig                          |    6 +-\n t/t5515/fetch.br-unconfig_--tags_.._.git           |    6 +-\n ...nfig_.._.git_one_tag_tag-one_tag_tag-three-file |    6 +-\n ...fig_.._.git_tag_tag-one-tree_tag_tag-three-file |    6 +-\n ...h.br-unconfig_.._.git_tag_tag-one_tag_tag-three |    6 +-\n t/t5515/fetch.br-unconfig_branches-default         |    6 +-\n t/t5515/fetch.br-unconfig_branches-one             |    6 +-\n t/t5515/fetch.br-unconfig_config-explicit          |    6 +-\n t/t5515/fetch.br-unconfig_config-glob              |    6 +-\n t/t5515/fetch.br-unconfig_remote-explicit          |    6 +-\n t/t5515/fetch.br-unconfig_remote-glob              |    6 +-\n t/t5515/fetch.master                               |    6 +-\n t/t5515/fetch.master_--tags_.._.git                |    6 +-\n ...ster_.._.git_one_tag_tag-one_tag_tag-three-file |    6 +-\n ...ter_.._.git_tag_tag-one-tree_tag_tag-three-file |    6 +-\n .../fetch.master_.._.git_tag_tag-one_tag_tag-three |    6 +-\n t/t5515/fetch.master_branches-default              |    6 +-\n t/t5515/fetch.master_branches-one                  |    6 +-\n t/t5515/fetch.master_config-explicit               |    6 +-\n t/t5515/fetch.master_config-glob                   |    6 +-\n t/t5515/fetch.master_remote-explicit               |    6 +-\n t/t5515/fetch.master_remote-glob                   |    6 +-\n t/t7510-signed-commit.sh                           |   71 ++++++\n t/t7600-merge.sh                                   |   12 +-\n t/t7604-merge-custom-message.sh                    |    2 +-\n t/t7608-merge-messages.sh                          |    4 +-\n tag.c                                              |    5 +\n 89 files changed, 1080 insertions(+), 392 deletions(-)\n create mode 100644 gpg-interface.c\n create mode 100644 gpg-interface.h\n create mode 100755 t/t7510-signed-commit.sh\n\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179176","messageId":"1320800523-5407-2-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 01/17] Split GPG interface into its own helper library","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:47Z","receivedAt":"2011-11-09T01:01:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This mostly moves existing code from builtin/tag.c (for signing)\nand builtin/verify-tag.c (for verifying) to a new gpg-interface.c\nfile to provide a more generic library interface.\n\n - sign_buffer() takes a payload strbuf, a signature strbuf, and a signing\n   key, runs \"gpg\" to produce a detached signature for the payload, and\n   appends it to the signature strbuf. The contents of a signed tag that\n   concatenates the payload and the detached signature can be produced by\n   giving the same strbuf as payload and signature strbuf.\n\n - verify_signed_buffer() takes a payload and a detached signature as\n   <ptr, len> pairs, and runs \"gpg --verify\" to see if the payload matches\n   the signature. It can optionally capture the output from GPG to allow\n   the callers to pretty-print it in a way more suitable for their\n   contexts.\n\n\"verify-tag\" (aka \"tag -v\") used to save the whole tag contents as if it\nis a detached signature, and fed gpg the payload part of the tag. It\nrelied on gpg to fail when the given tag is not signed but just is\nannotated.  The updated run_gpg_verify() function detects the lack of\ndetached signature in the input, and errors out without bothering \"gpg\".\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Makefile             |    2 +\n builtin/tag.c        |   76 ++-------------------------\n builtin/verify-tag.c |   35 ++-----------\n gpg-interface.c      |  138 ++++++++++++++++++++++++++++++++++++++++++++++++++\n gpg-interface.h      |   10 ++++\n tag.c                |    5 ++\n 6 files changed, 166 insertions(+), 100 deletions(-)\n create mode 100644 gpg-interface.c\n create mode 100644 gpg-interface.h\n\ndiff --git a/Makefile b/Makefile\nindex 17404c4..e4b14af 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -528,6 +528,7 @@ LIB_H += exec_cmd.h\n LIB_H += fsck.h\n LIB_H += gettext.h\n LIB_H += git-compat-util.h\n+LIB_H += gpg-interface.h\n LIB_H += graph.h\n LIB_H += grep.h\n LIB_H += hash.h\n@@ -621,6 +622,7 @@ LIB_OBJS += entry.o\n LIB_OBJS += environment.o\n LIB_OBJS += exec_cmd.o\n LIB_OBJS += fsck.o\n+LIB_OBJS += gpg-interface.o\n LIB_OBJS += graph.o\n LIB_OBJS += grep.o\n LIB_OBJS += hash.o\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 9b6fd95..cca1205 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -14,6 +14,7 @@\n #include \"parse-options.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n+#include \"gpg-interface.h\"\n \n static const char * const git_tag_usage[] = {\n \t\"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]\",\n@@ -23,8 +24,6 @@ static const char * const git_tag_usage[] = {\n \tNULL\n };\n \n-static char signingkey[1000];\n-\n struct tag_filter {\n \tconst char **patterns;\n \tint lines;\n@@ -208,60 +207,7 @@ static int verify_tag(const char *name, const char *ref,\n \n static int do_sign(struct strbuf *buffer)\n {\n-\tstruct child_process gpg;\n-\tconst char *args[4];\n-\tchar *bracket;\n-\tint len;\n-\tint i, j;\n-\n-\tif (!*signingkey) {\n-\t\tif (strlcpy(signingkey, git_committer_info(IDENT_ERROR_ON_NO_NAME),\n-\t\t\t\tsizeof(signingkey)) > sizeof(signingkey) - 1)\n-\t\t\treturn error(_(\"committer info too long.\"));\n-\t\tbracket = strchr(signingkey, '>');\n-\t\tif (bracket)\n-\t\t\tbracket[1] = '\\0';\n-\t}\n-\n-\t/* When the username signingkey is bad, program could be terminated\n-\t * because gpg exits without reading and then write gets SIGPIPE. */\n-\tsignal(SIGPIPE, SIG_IGN);\n-\n-\tmemset(&gpg, 0, sizeof(gpg));\n-\tgpg.argv = args;\n-\tgpg.in = -1;\n-\tgpg.out = -1;\n-\targs[0] = \"gpg\";\n-\targs[1] = \"-bsau\";\n-\targs[2] = signingkey;\n-\targs[3] = NULL;\n-\n-\tif (start_command(&gpg))\n-\t\treturn error(_(\"could not run gpg.\"));\n-\n-\tif (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {\n-\t\tclose(gpg.in);\n-\t\tclose(gpg.out);\n-\t\tfinish_command(&gpg);\n-\t\treturn error(_(\"gpg did not accept the tag data\"));\n-\t}\n-\tclose(gpg.in);\n-\tlen = strbuf_read(buffer, gpg.out, 1024);\n-\tclose(gpg.out);\n-\n-\tif (finish_command(&gpg) || !len || len < 0)\n-\t\treturn error(_(\"gpg failed to sign the tag\"));\n-\n-\t/* Strip CR from the line endings, in case we are on Windows. */\n-\tfor (i = j = 0; i < buffer->len; i++)\n-\t\tif (buffer->buf[i] != '\\r') {\n-\t\t\tif (i != j)\n-\t\t\t\tbuffer->buf[j] = buffer->buf[i];\n-\t\t\tj++;\n-\t\t}\n-\tstrbuf_setlen(buffer, j);\n-\n-\treturn 0;\n+\treturn sign_buffer(buffer, buffer, get_signing_key());\n }\n \n static const char tag_template[] =\n@@ -270,21 +216,11 @@ static const char tag_template[] =\n \t\"# Write a tag message\\n\"\n \t\"#\\n\");\n \n-static void set_signingkey(const char *value)\n-{\n-\tif (strlcpy(signingkey, value, sizeof(signingkey)) >= sizeof(signingkey))\n-\t\tdie(_(\"signing key value too long (%.10s...)\"), value);\n-}\n-\n static int git_tag_config(const char *var, const char *value, void *cb)\n {\n-\tif (!strcmp(var, \"user.signingkey\")) {\n-\t\tif (!value)\n-\t\t\treturn config_error_nonbool(var);\n-\t\tset_signingkey(value);\n-\t\treturn 0;\n-\t}\n-\n+\tint status = git_gpg_config(var, value, cb);\n+\tif (status)\n+\t\treturn status;\n \treturn git_default_config(var, value, cb);\n }\n \n@@ -463,7 +399,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \n \tif (keyid) {\n \t\tsign = 1;\n-\t\tset_signingkey(keyid);\n+\t\tset_signing_key(keyid);\n \t}\n \tif (sign)\n \t\tannotate = 1;\ndiff --git a/builtin/verify-tag.c b/builtin/verify-tag.c\nindex 3134766..28c2174 100644\n--- a/builtin/verify-tag.c\n+++ b/builtin/verify-tag.c\n@@ -11,6 +11,7 @@\n #include \"run-command.h\"\n #include <signal.h>\n #include \"parse-options.h\"\n+#include \"gpg-interface.h\"\n \n static const char * const verify_tag_usage[] = {\n \t\t\"git verify-tag [-v|--verbose] <tag>...\",\n@@ -19,42 +20,16 @@ static const char * const verify_tag_usage[] = {\n \n static int run_gpg_verify(const char *buf, unsigned long size, int verbose)\n {\n-\tstruct child_process gpg;\n-\tconst char *args_gpg[] = {\"gpg\", \"--verify\", \"FILE\", \"-\", NULL};\n-\tchar path[PATH_MAX];\n-\tsize_t len;\n-\tint fd, ret;\n+\tint len;\n \n-\tfd = git_mkstemp(path, PATH_MAX, \".git_vtag_tmpXXXXXX\");\n-\tif (fd < 0)\n-\t\treturn error(\"could not create temporary file '%s': %s\",\n-\t\t\t\t\t\tpath, strerror(errno));\n-\tif (write_in_full(fd, buf, size) < 0)\n-\t\treturn error(\"failed writing temporary file '%s': %s\",\n-\t\t\t\t\t\tpath, strerror(errno));\n-\tclose(fd);\n-\n-\t/* find the length without signature */\n \tlen = parse_signature(buf, size);\n \tif (verbose)\n \t\twrite_in_full(1, buf, len);\n \n-\tmemset(&gpg, 0, sizeof(gpg));\n-\tgpg.argv = args_gpg;\n-\tgpg.in = -1;\n-\targs_gpg[2] = path;\n-\tif (start_command(&gpg)) {\n-\t\tunlink(path);\n-\t\treturn error(\"could not run gpg.\");\n-\t}\n-\n-\twrite_in_full(gpg.in, buf, len);\n-\tclose(gpg.in);\n-\tret = finish_command(&gpg);\n+\tif (size == len)\n+\t\treturn error(\"no signature found\");\n \n-\tunlink_or_warn(path);\n-\n-\treturn ret;\n+\treturn verify_signed_buffer(buf, len, buf + len, size - len, NULL);\n }\n \n static int verify_tag(const char *name, int verbose)\ndiff --git a/gpg-interface.c b/gpg-interface.c\nnew file mode 100644\nindex 0000000..ff232c8\n--- /dev/null\n+++ b/gpg-interface.c\n@@ -0,0 +1,138 @@\n+#include \"cache.h\"\n+#include \"run-command.h\"\n+#include \"strbuf.h\"\n+#include \"gpg-interface.h\"\n+#include \"sigchain.h\"\n+\n+static char *configured_signing_key;\n+\n+void set_signing_key(const char *key)\n+{\n+\tfree(configured_signing_key);\n+\tconfigured_signing_key = xstrdup(key);\n+}\n+\n+int git_gpg_config(const char *var, const char *value, void *cb)\n+{\n+\tif (!strcmp(var, \"user.signingkey\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\tset_signing_key(value);\n+\t}\n+\treturn 0;\n+}\n+\n+const char *get_signing_key(void)\n+{\n+\tif (configured_signing_key)\n+\t\treturn configured_signing_key;\n+\treturn git_committer_info(IDENT_ERROR_ON_NO_NAME|IDENT_NO_DATE);\n+}\n+\n+/*\n+ * Create a detached signature for the contents of \"buffer\" and append\n+ * it after \"signature\"; \"buffer\" and \"signature\" can be the same\n+ * strbuf instance, which would cause the detached signature appended\n+ * at the end.\n+ */\n+int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)\n+{\n+\tstruct child_process gpg;\n+\tconst char *args[4];\n+\tssize_t len;\n+\tsize_t i, j, bottom;\n+\n+\tmemset(&gpg, 0, sizeof(gpg));\n+\tgpg.argv = args;\n+\tgpg.in = -1;\n+\tgpg.out = -1;\n+\targs[0] = \"gpg\";\n+\targs[1] = \"-bsau\";\n+\targs[2] = signing_key;\n+\targs[3] = NULL;\n+\n+\tif (start_command(&gpg))\n+\t\treturn error(_(\"could not run gpg.\"));\n+\n+\t/*\n+\t * When the username signingkey is bad, program could be terminated\n+\t * because gpg exits without reading and then write gets SIGPIPE.\n+\t */\n+\tsigchain_push(SIGPIPE, SIG_IGN);\n+\n+\tif (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {\n+\t\tclose(gpg.in);\n+\t\tclose(gpg.out);\n+\t\tfinish_command(&gpg);\n+\t\treturn error(_(\"gpg did not accept the data\"));\n+\t}\n+\tclose(gpg.in);\n+\n+\tbottom = signature->len;\n+\tlen = strbuf_read(signature, gpg.out, 1024);\n+\tclose(gpg.out);\n+\n+\tsigchain_pop(SIGPIPE);\n+\n+\tif (finish_command(&gpg) || !len || len < 0)\n+\t\treturn error(_(\"gpg failed to sign the data\"));\n+\n+\t/* Strip CR from the line endings, in case we are on Windows. */\n+\tfor (i = j = bottom; i < signature->len; i++)\n+\t\tif (signature->buf[i] != '\\r') {\n+\t\t\tif (i != j)\n+\t\t\t\tsignature->buf[j] = signature->buf[i];\n+\t\t\tj++;\n+\t\t}\n+\tstrbuf_setlen(signature, j);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Run \"gpg\" to see if the payload matches the detached signature.\n+ * gpg_output_to tells where the output from \"gpg\" should go:\n+ *   < 0: /dev/null\n+ *   = 0: standard error of the calling process\n+ *   > 0: the specified file descriptor\n+ */\n+int verify_signed_buffer(const char *payload, size_t payload_size,\n+\t\t\t const char *signature, size_t signature_size,\n+\t\t\t struct strbuf *gpg_output)\n+{\n+\tstruct child_process gpg;\n+\tconst char *args_gpg[] = {\"gpg\", \"--verify\", \"FILE\", \"-\", NULL};\n+\tchar path[PATH_MAX];\n+\tint fd, ret;\n+\n+\tfd = git_mkstemp(path, PATH_MAX, \".git_vtag_tmpXXXXXX\");\n+\tif (fd < 0)\n+\t\treturn error(\"could not create temporary file '%s': %s\",\n+\t\t\t     path, strerror(errno));\n+\tif (write_in_full(fd, signature, signature_size) < 0)\n+\t\treturn error(\"failed writing detached signature to '%s': %s\",\n+\t\t\t     path, strerror(errno));\n+\tclose(fd);\n+\n+\tmemset(&gpg, 0, sizeof(gpg));\n+\tgpg.argv = args_gpg;\n+\tgpg.in = -1;\n+\tif (gpg_output)\n+\t\tgpg.err = -1;\n+\targs_gpg[2] = path;\n+\tif (start_command(&gpg)) {\n+\t\tunlink(path);\n+\t\treturn error(\"could not run gpg.\");\n+\t}\n+\n+\twrite_in_full(gpg.in, payload, payload_size);\n+\tclose(gpg.in);\n+\n+\tif (gpg_output)\n+\t\tstrbuf_read(gpg_output, gpg.err, 0);\n+\tret = finish_command(&gpg);\n+\n+\tunlink_or_warn(path);\n+\n+\treturn ret;\n+}\ndiff --git a/gpg-interface.h b/gpg-interface.h\nnew file mode 100644\nindex 0000000..b9c3608\n--- /dev/null\n+++ b/gpg-interface.h\n@@ -0,0 +1,10 @@\n+#ifndef GPG_INTERFACE_H\n+#define GPG_INTERFACE_H\n+\n+extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key);\n+extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output);\n+extern int git_gpg_config(const char *, const char *, void *);\n+extern void set_signing_key(const char *);\n+extern const char *get_signing_key(void);\n+\n+#endif\ndiff --git a/tag.c b/tag.c\nindex 7d38cc0..3aa186d 100644\n--- a/tag.c\n+++ b/tag.c\n@@ -139,6 +139,11 @@ int parse_tag(struct tag *item)\n \treturn ret;\n }\n \n+/*\n+ * Look at a signed tag object, and return the offset where\n+ * the embedded detached signature begins, or the end of the\n+ * data when there is no such signature.\n+ */\n size_t parse_signature(const char *buf, unsigned long size)\n {\n \tchar *eol;\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179179","messageId":"1320800523-5407-3-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 02/17] fetch: do not store peeled tag object names in FETCH_HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:48Z","receivedAt":"2011-11-09T01:01:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Linus Torvalds <torvalds@linux-foundation.org>\n\nWe do not want to record tags as parents of a merge when the user does\n\"git pull $there tag v1.0\" to merge tagged commit, but that is not a good\nenough excuse to peel the tag down to commit when storing in FETCH_HEAD.\nThe caller of underlying \"git fetch $there tag v1.0\" may have other uses\nof information contained in v1.0 tag in mind.\n\n[jc: the test adjustment is to update for the new expectation]\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/fetch.c                                    |    3 +--\n t/t5515/fetch.br-branches-default                  |    6 +++---\n t/t5515/fetch.br-branches-default-merge            |    6 +++---\n ...etch.br-branches-default-merge_branches-default |    6 +++---\n t/t5515/fetch.br-branches-default-octopus          |    6 +++---\n ...ch.br-branches-default-octopus_branches-default |    6 +++---\n t/t5515/fetch.br-branches-default_branches-default |    6 +++---\n t/t5515/fetch.br-branches-one                      |    6 +++---\n t/t5515/fetch.br-branches-one-merge                |    6 +++---\n t/t5515/fetch.br-branches-one-merge_branches-one   |    6 +++---\n t/t5515/fetch.br-branches-one-octopus              |    6 +++---\n t/t5515/fetch.br-branches-one-octopus_branches-one |    6 +++---\n t/t5515/fetch.br-branches-one_branches-one         |    6 +++---\n t/t5515/fetch.br-config-explicit                   |    6 +++---\n t/t5515/fetch.br-config-explicit-merge             |    6 +++---\n .../fetch.br-config-explicit-merge_config-explicit |    6 +++---\n t/t5515/fetch.br-config-explicit-octopus           |    6 +++---\n ...etch.br-config-explicit-octopus_config-explicit |    6 +++---\n t/t5515/fetch.br-config-explicit_config-explicit   |    6 +++---\n t/t5515/fetch.br-config-glob                       |    6 +++---\n t/t5515/fetch.br-config-glob-merge                 |    6 +++---\n t/t5515/fetch.br-config-glob-merge_config-glob     |    6 +++---\n t/t5515/fetch.br-config-glob-octopus               |    6 +++---\n t/t5515/fetch.br-config-glob-octopus_config-glob   |    6 +++---\n t/t5515/fetch.br-config-glob_config-glob           |    6 +++---\n t/t5515/fetch.br-remote-explicit                   |    6 +++---\n t/t5515/fetch.br-remote-explicit-merge             |    6 +++---\n .../fetch.br-remote-explicit-merge_remote-explicit |    6 +++---\n t/t5515/fetch.br-remote-explicit-octopus           |    6 +++---\n ...etch.br-remote-explicit-octopus_remote-explicit |    6 +++---\n t/t5515/fetch.br-remote-explicit_remote-explicit   |    6 +++---\n t/t5515/fetch.br-remote-glob                       |    6 +++---\n t/t5515/fetch.br-remote-glob-merge                 |    6 +++---\n t/t5515/fetch.br-remote-glob-merge_remote-glob     |    6 +++---\n t/t5515/fetch.br-remote-glob-octopus               |    6 +++---\n t/t5515/fetch.br-remote-glob-octopus_remote-glob   |    6 +++---\n t/t5515/fetch.br-remote-glob_remote-glob           |    6 +++---\n t/t5515/fetch.br-unconfig                          |    6 +++---\n t/t5515/fetch.br-unconfig_--tags_.._.git           |    6 +++---\n ...nfig_.._.git_one_tag_tag-one_tag_tag-three-file |    6 +++---\n ...fig_.._.git_tag_tag-one-tree_tag_tag-three-file |    6 +++---\n ...h.br-unconfig_.._.git_tag_tag-one_tag_tag-three |    6 +++---\n t/t5515/fetch.br-unconfig_branches-default         |    6 +++---\n t/t5515/fetch.br-unconfig_branches-one             |    6 +++---\n t/t5515/fetch.br-unconfig_config-explicit          |    6 +++---\n t/t5515/fetch.br-unconfig_config-glob              |    6 +++---\n t/t5515/fetch.br-unconfig_remote-explicit          |    6 +++---\n t/t5515/fetch.br-unconfig_remote-glob              |    6 +++---\n t/t5515/fetch.master                               |    6 +++---\n t/t5515/fetch.master_--tags_.._.git                |    6 +++---\n ...ster_.._.git_one_tag_tag-one_tag_tag-three-file |    6 +++---\n ...ter_.._.git_tag_tag-one-tree_tag_tag-three-file |    6 +++---\n .../fetch.master_.._.git_tag_tag-one_tag_tag-three |    6 +++---\n t/t5515/fetch.master_branches-default              |    6 +++---\n t/t5515/fetch.master_branches-one                  |    6 +++---\n t/t5515/fetch.master_config-explicit               |    6 +++---\n t/t5515/fetch.master_config-glob                   |    6 +++---\n t/t5515/fetch.master_remote-explicit               |    6 +++---\n t/t5515/fetch.master_remote-glob                   |    6 +++---\n 59 files changed, 175 insertions(+), 176 deletions(-)\n\ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex 1adf6c1..d061e2c 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -436,8 +436,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,\n \t\t}\n \t\tnote[note_len] = '\\0';\n \t\tfprintf(fp, \"%s\\t%s\\t%s\",\n-\t\t\tsha1_to_hex(commit ? commit->object.sha1 :\n-\t\t\t\t    rm->old_sha1),\n+\t\t\tsha1_to_hex(rm->old_sha1),\n \t\t\trm->merge ? \"\" : \"not-for-merge\",\n \t\t\tnote);\n \t\tfor (i = 0; i < url_len; ++i)\ndiff --git a/t/t5515/fetch.br-branches-default b/t/t5515/fetch.br-branches-default\nindex 2e0414f..a1bc3d5 100644\n--- a/t/t5515/fetch.br-branches-default\n+++ b/t/t5515/fetch.br-branches-default\n@@ -1,8 +1,8 @@\n # br-branches-default\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\t\tbranch 'master' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-default-merge b/t/t5515/fetch.br-branches-default-merge\nindex ca2cc1d..e3a41ae 100644\n--- a/t/t5515/fetch.br-branches-default-merge\n+++ b/t/t5515/fetch.br-branches-default-merge\n@@ -1,9 +1,9 @@\n # br-branches-default-merge\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\tbranch 'master' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-default-merge_branches-default b/t/t5515/fetch.br-branches-default-merge_branches-default\nindex 7d947cd..1f60561 100644\n--- a/t/t5515/fetch.br-branches-default-merge_branches-default\n+++ b/t/t5515/fetch.br-branches-default-merge_branches-default\n@@ -1,9 +1,9 @@\n # br-branches-default-merge branches-default\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\tbranch 'master' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-default-octopus b/t/t5515/fetch.br-branches-default-octopus\nindex ec39c54..f31e1b3 100644\n--- a/t/t5515/fetch.br-branches-default-octopus\n+++ b/t/t5515/fetch.br-branches-default-octopus\n@@ -2,9 +2,9 @@\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\tbranch 'master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-default-octopus_branches-default b/t/t5515/fetch.br-branches-default-octopus_branches-default\nindex 6bf42e2..7060bd9 100644\n--- a/t/t5515/fetch.br-branches-default-octopus_branches-default\n+++ b/t/t5515/fetch.br-branches-default-octopus_branches-default\n@@ -2,9 +2,9 @@\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\tbranch 'master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-default_branches-default b/t/t5515/fetch.br-branches-default_branches-default\nindex 4a2bf3c..8cbd718 100644\n--- a/t/t5515/fetch.br-branches-default_branches-default\n+++ b/t/t5515/fetch.br-branches-default_branches-default\n@@ -1,8 +1,8 @@\n # br-branches-default branches-default\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\t\tbranch 'master' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-one b/t/t5515/fetch.br-branches-one\nindex 12ac8d2..c98f670 100644\n--- a/t/t5515/fetch.br-branches-one\n+++ b/t/t5515/fetch.br-branches-one\n@@ -1,8 +1,8 @@\n # br-branches-one\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-one-merge b/t/t5515/fetch.br-branches-one-merge\nindex b4b3b35..aa1c8a9 100644\n--- a/t/t5515/fetch.br-branches-one-merge\n+++ b/t/t5515/fetch.br-branches-one-merge\n@@ -1,9 +1,9 @@\n # br-branches-one-merge\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-one-merge_branches-one b/t/t5515/fetch.br-branches-one-merge_branches-one\nindex 2ecef38..c93310a 100644\n--- a/t/t5515/fetch.br-branches-one-merge_branches-one\n+++ b/t/t5515/fetch.br-branches-one-merge_branches-one\n@@ -1,9 +1,9 @@\n # br-branches-one-merge branches-one\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-one-octopus b/t/t5515/fetch.br-branches-one-octopus\nindex 96e3029..97c4b54 100644\n--- a/t/t5515/fetch.br-branches-one-octopus\n+++ b/t/t5515/fetch.br-branches-one-octopus\n@@ -1,9 +1,9 @@\n # br-branches-one-octopus\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-one-octopus_branches-one b/t/t5515/fetch.br-branches-one-octopus_branches-one\nindex 55e0bad..df705f7 100644\n--- a/t/t5515/fetch.br-branches-one-octopus_branches-one\n+++ b/t/t5515/fetch.br-branches-one-octopus_branches-one\n@@ -1,9 +1,9 @@\n # br-branches-one-octopus branches-one\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-branches-one_branches-one b/t/t5515/fetch.br-branches-one_branches-one\nindex 281fa09..96890e5 100644\n--- a/t/t5515/fetch.br-branches-one_branches-one\n+++ b/t/t5515/fetch.br-branches-one_branches-one\n@@ -1,8 +1,8 @@\n # br-branches-one branches-one\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-explicit b/t/t5515/fetch.br-config-explicit\nindex e2fa9c8..68fc927 100644\n--- a/t/t5515/fetch.br-config-explicit\n+++ b/t/t5515/fetch.br-config-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-explicit-merge b/t/t5515/fetch.br-config-explicit-merge\nindex ec1a723..f6475b7 100644\n--- a/t/t5515/fetch.br-config-explicit-merge\n+++ b/t/t5515/fetch.br-config-explicit-merge\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-explicit-merge_config-explicit b/t/t5515/fetch.br-config-explicit-merge_config-explicit\nindex 54f6891..018bdd7 100644\n--- a/t/t5515/fetch.br-config-explicit-merge_config-explicit\n+++ b/t/t5515/fetch.br-config-explicit-merge_config-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-explicit-octopus b/t/t5515/fetch.br-config-explicit-octopus\nindex 7011dfc..36d0270 100644\n--- a/t/t5515/fetch.br-config-explicit-octopus\n+++ b/t/t5515/fetch.br-config-explicit-octopus\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-explicit-octopus_config-explicit b/t/t5515/fetch.br-config-explicit-octopus_config-explicit\nindex bdad51f..6654ad0 100644\n--- a/t/t5515/fetch.br-config-explicit-octopus_config-explicit\n+++ b/t/t5515/fetch.br-config-explicit-octopus_config-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-explicit_config-explicit b/t/t5515/fetch.br-config-explicit_config-explicit\nindex 1b237dd..b19b016 100644\n--- a/t/t5515/fetch.br-config-explicit_config-explicit\n+++ b/t/t5515/fetch.br-config-explicit_config-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-glob b/t/t5515/fetch.br-config-glob\nindex e75ec2f..946d70c 100644\n--- a/t/t5515/fetch.br-config-glob\n+++ b/t/t5515/fetch.br-config-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-glob-merge b/t/t5515/fetch.br-config-glob-merge\nindex ce8f739..8bb5e8b 100644\n--- a/t/t5515/fetch.br-config-glob-merge\n+++ b/t/t5515/fetch.br-config-glob-merge\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-glob-merge_config-glob b/t/t5515/fetch.br-config-glob-merge_config-glob\nindex 5817bed..113c08d 100644\n--- a/t/t5515/fetch.br-config-glob-merge_config-glob\n+++ b/t/t5515/fetch.br-config-glob-merge_config-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-glob-octopus b/t/t5515/fetch.br-config-glob-octopus\nindex 938e532..9bbd537 100644\n--- a/t/t5515/fetch.br-config-glob-octopus\n+++ b/t/t5515/fetch.br-config-glob-octopus\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-glob-octopus_config-glob b/t/t5515/fetch.br-config-glob-octopus_config-glob\nindex c9225bf..4e51043 100644\n--- a/t/t5515/fetch.br-config-glob-octopus_config-glob\n+++ b/t/t5515/fetch.br-config-glob-octopus_config-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-config-glob_config-glob b/t/t5515/fetch.br-config-glob_config-glob\nindex a6c20f9..19daf0c 100644\n--- a/t/t5515/fetch.br-config-glob_config-glob\n+++ b/t/t5515/fetch.br-config-glob_config-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-explicit b/t/t5515/fetch.br-remote-explicit\nindex 83534d2..ab44bc5 100644\n--- a/t/t5515/fetch.br-remote-explicit\n+++ b/t/t5515/fetch.br-remote-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-explicit-merge b/t/t5515/fetch.br-remote-explicit-merge\nindex a9064dd..7421b2c 100644\n--- a/t/t5515/fetch.br-remote-explicit-merge\n+++ b/t/t5515/fetch.br-remote-explicit-merge\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-explicit-merge_remote-explicit b/t/t5515/fetch.br-remote-explicit-merge_remote-explicit\nindex 732a37e..b6975d3 100644\n--- a/t/t5515/fetch.br-remote-explicit-merge_remote-explicit\n+++ b/t/t5515/fetch.br-remote-explicit-merge_remote-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-explicit-octopus b/t/t5515/fetch.br-remote-explicit-octopus\nindex ecf020d..7681281 100644\n--- a/t/t5515/fetch.br-remote-explicit-octopus\n+++ b/t/t5515/fetch.br-remote-explicit-octopus\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit b/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit\nindex af77531..4c896cf 100644\n--- a/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit\n+++ b/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-explicit_remote-explicit b/t/t5515/fetch.br-remote-explicit_remote-explicit\nindex 51fae56..01e014e 100644\n--- a/t/t5515/fetch.br-remote-explicit_remote-explicit\n+++ b/t/t5515/fetch.br-remote-explicit_remote-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-glob b/t/t5515/fetch.br-remote-glob\nindex 94e6ad3..09bfcee 100644\n--- a/t/t5515/fetch.br-remote-glob\n+++ b/t/t5515/fetch.br-remote-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-glob-merge b/t/t5515/fetch.br-remote-glob-merge\nindex 09362e2..4b62b01 100644\n--- a/t/t5515/fetch.br-remote-glob-merge\n+++ b/t/t5515/fetch.br-remote-glob-merge\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-glob-merge_remote-glob b/t/t5515/fetch.br-remote-glob-merge_remote-glob\nindex e2eabec..7478f1f 100644\n--- a/t/t5515/fetch.br-remote-glob-merge_remote-glob\n+++ b/t/t5515/fetch.br-remote-glob-merge_remote-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-glob-octopus b/t/t5515/fetch.br-remote-glob-octopus\nindex b08e046..2543420 100644\n--- a/t/t5515/fetch.br-remote-glob-octopus\n+++ b/t/t5515/fetch.br-remote-glob-octopus\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-glob-octopus_remote-glob b/t/t5515/fetch.br-remote-glob-octopus_remote-glob\nindex d4d547c..5ffde9c 100644\n--- a/t/t5515/fetch.br-remote-glob-octopus_remote-glob\n+++ b/t/t5515/fetch.br-remote-glob-octopus_remote-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\t\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-remote-glob_remote-glob b/t/t5515/fetch.br-remote-glob_remote-glob\nindex 646dbc8..20ba5cb 100644\n--- a/t/t5515/fetch.br-remote-glob_remote-glob\n+++ b/t/t5515/fetch.br-remote-glob_remote-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig b/t/t5515/fetch.br-unconfig\nindex 65ce6d9..887ccfc 100644\n--- a/t/t5515/fetch.br-unconfig\n+++ b/t/t5515/fetch.br-unconfig\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_--tags_.._.git b/t/t5515/fetch.br-unconfig_--tags_.._.git\nindex 8258c80..1669cc4 100644\n--- a/t/t5515/fetch.br-unconfig_--tags_.._.git\n+++ b/t/t5515/fetch.br-unconfig_--tags_.._.git\n@@ -1,7 +1,7 @@\n # br-unconfig --tags ../.git\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file\nindex f02bab2..7411536 100644\n--- a/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file\n+++ b/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file\n@@ -2,7 +2,7 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\ttag 'tag-one' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file\nindex 85de411..7726983 100644\n--- a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file\n+++ b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file\n@@ -1,7 +1,7 @@\n # br-unconfig ../.git tag tag-one-tree tag tag-three-file\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three\nindex 0da2337..7b3750c 100644\n--- a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three\n+++ b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three\n@@ -1,7 +1,7 @@\n # br-unconfig ../.git tag tag-one tag tag-three\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\ttag 'tag-one' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\ttag 'tag-three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\t\ttag 'tag-three' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_branches-default b/t/t5515/fetch.br-unconfig_branches-default\nindex fc7041e..da30e3c 100644\n--- a/t/t5515/fetch.br-unconfig_branches-default\n+++ b/t/t5515/fetch.br-unconfig_branches-default\n@@ -1,8 +1,8 @@\n # br-unconfig branches-default\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\t\tbranch 'master' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_branches-one b/t/t5515/fetch.br-unconfig_branches-one\nindex e94cde7..e461431 100644\n--- a/t/t5515/fetch.br-unconfig_branches-one\n+++ b/t/t5515/fetch.br-unconfig_branches-one\n@@ -1,8 +1,8 @@\n # br-unconfig branches-one\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_config-explicit b/t/t5515/fetch.br-unconfig_config-explicit\nindex 01a283e..ed323c9 100644\n--- a/t/t5515/fetch.br-unconfig_config-explicit\n+++ b/t/t5515/fetch.br-unconfig_config-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_config-glob b/t/t5515/fetch.br-unconfig_config-glob\nindex 3a556c5..2372ed0 100644\n--- a/t/t5515/fetch.br-unconfig_config-glob\n+++ b/t/t5515/fetch.br-unconfig_config-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_remote-explicit b/t/t5515/fetch.br-unconfig_remote-explicit\nindex db216df..6318dd1 100644\n--- a/t/t5515/fetch.br-unconfig_remote-explicit\n+++ b/t/t5515/fetch.br-unconfig_remote-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.br-unconfig_remote-glob b/t/t5515/fetch.br-unconfig_remote-glob\nindex aee65c2..1d9afad 100644\n--- a/t/t5515/fetch.br-unconfig_remote-glob\n+++ b/t/t5515/fetch.br-unconfig_remote-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master b/t/t5515/fetch.master\nindex 950fd07..9b29d67 100644\n--- a/t/t5515/fetch.master\n+++ b/t/t5515/fetch.master\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_--tags_.._.git b/t/t5515/fetch.master_--tags_.._.git\nindex 0e59950..8a74935 100644\n--- a/t/t5515/fetch.master_--tags_.._.git\n+++ b/t/t5515/fetch.master_--tags_.._.git\n@@ -1,7 +1,7 @@\n # master --tags ../.git\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file\nindex 8286852..0672d12 100644\n--- a/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file\n+++ b/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file\n@@ -2,7 +2,7 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\ttag 'tag-one' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file\nindex 2e133ef..0fd737c 100644\n--- a/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file\n+++ b/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file\n@@ -1,7 +1,7 @@\n # master ../.git tag tag-one-tree tag tag-three-file\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three b/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three\nindex 92b18b4..e488986 100644\n--- a/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three\n+++ b/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three\n@@ -1,7 +1,7 @@\n # master ../.git tag tag-one tag tag-three\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\ttag 'tag-one' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\t\ttag 'tag-three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\t\ttag 'tag-three' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_branches-default b/t/t5515/fetch.master_branches-default\nindex 603d6d2..2eedd3b 100644\n--- a/t/t5515/fetch.master_branches-default\n+++ b/t/t5515/fetch.master_branches-default\n@@ -1,8 +1,8 @@\n # master branches-default\n 754b754407bf032e9a2f9d5a9ad05ca79a6b228f\t\tbranch 'master' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_branches-one b/t/t5515/fetch.master_branches-one\nindex fe9bb0b..901ce21 100644\n--- a/t/t5515/fetch.master_branches-one\n+++ b/t/t5515/fetch.master_branches-one\n@@ -1,8 +1,8 @@\n # master branches-one\n 8e32a6d901327a23ef831511badce7bf3bf46689\t\tbranch 'one' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_config-explicit b/t/t5515/fetch.master_config-explicit\nindex 4be97c7..251c826 100644\n--- a/t/t5515/fetch.master_config-explicit\n+++ b/t/t5515/fetch.master_config-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_config-glob b/t/t5515/fetch.master_config-glob\nindex cb0726f..27c158e 100644\n--- a/t/t5515/fetch.master_config-glob\n+++ b/t/t5515/fetch.master_config-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_remote-explicit b/t/t5515/fetch.master_remote-explicit\nindex 44a1ca8..b3cfe6b 100644\n--- a/t/t5515/fetch.master_remote-explicit\n+++ b/t/t5515/fetch.master_remote-explicit\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\ndiff --git a/t/t5515/fetch.master_remote-glob b/t/t5515/fetch.master_remote-glob\nindex 724e8db..118befd 100644\n--- a/t/t5515/fetch.master_remote-glob\n+++ b/t/t5515/fetch.master_remote-glob\n@@ -3,9 +3,9 @@\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\tbranch 'one' of ../\n 0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\tbranch 'three' of ../\n 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\tbranch 'two' of ../\n-754b754407bf032e9a2f9d5a9ad05ca79a6b228f\tnot-for-merge\ttag 'tag-master' of ../\n+6c9dec2b923228c9ff994c6cfe4ae16c12408dc5\tnot-for-merge\ttag 'tag-master' of ../\n 8e32a6d901327a23ef831511badce7bf3bf46689\tnot-for-merge\ttag 'tag-one' of ../\n 22feea448b023a2d864ef94b013735af34d238ba\tnot-for-merge\ttag 'tag-one-tree' of ../\n-0567da4d5edd2ff4bb292a465ba9e64dcad9536b\tnot-for-merge\ttag 'tag-three' of ../\n+c61a82b60967180544e3c19f819ddbd0c9f89899\tnot-for-merge\ttag 'tag-three' of ../\n 0e3b14047d3ee365f4f2a1b673db059c3972589c\tnot-for-merge\ttag 'tag-three-file' of ../\n-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8\tnot-for-merge\ttag 'tag-two' of ../\n+525b7fb068d59950d185a8779dc957c77eed73ba\tnot-for-merge\ttag 'tag-two' of ../\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179175","messageId":"1320800523-5407-4-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 03/17] merge: notice local merging of tags and keep it unwrapped","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:49Z","receivedAt":"2011-11-09T01:01:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This also updates the autogenerated merge title message from \"merge commit X\"\nto \"merge tag X\", and its effect can be seen in the changes to the test suite.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/merge.c                 |    5 +++++\n t/t4202-log.sh                  |    4 ++--\n t/t7600-merge.sh                |    6 +++---\n t/t7604-merge-custom-message.sh |    2 +-\n t/t7608-merge-messages.sh       |    4 ++--\n 5 files changed, 13 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex dffd5ec..6a44b6d 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -441,6 +441,11 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t\t\t\t    sha1_to_hex(branch_head), remote);\n \t\t\tgoto cleanup;\n \t\t}\n+\t\tif (!prefixcmp(found_ref, \"refs/tags/\")) {\n+\t\t\tstrbuf_addf(msg, \"%s\\t\\ttag '%s' of .\\n\",\n+\t\t\t\t    sha1_to_hex(branch_head), remote);\n+\t\t\tgoto cleanup;\n+\t\t}\n \t\tif (!prefixcmp(found_ref, \"refs/remotes/\")) {\n \t\t\tstrbuf_addf(msg, \"%s\\t\\tremote-tracking branch '%s' of .\\n\",\n \t\t\t\t    sha1_to_hex(branch_head), remote);\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 983e34b..222f755 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -346,11 +346,11 @@ test_expect_success 'set up more tangled history' '\n '\n \n cat > expect <<\\EOF\n-*   Merge commit 'reach'\n+*   Merge tag 'reach'\n |\\\n | \\\n |  \\\n-*-. \\   Merge commit 'octopus-a'; commit 'octopus-b'\n+*-. \\   Merge tags 'octopus-a' and 'octopus-b'\n |\\ \\ \\\n * | | | seventh\n | | * | octopus-b\ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex 3008e4e..b91d022 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -38,8 +38,8 @@ printf '%s\\n' '1 X' 2 3 4 '5 X' 6 7 8 '9 X' >result.1-5-9\n >empty\n \n create_merge_msgs () {\n-\techo \"Merge commit 'c2'\" >msg.1-5 &&\n-\techo \"Merge commit 'c2'; commit 'c3'\" >msg.1-5-9 &&\n+\techo \"Merge tag 'c2'\" >msg.1-5 &&\n+\techo \"Merge tags 'c2' and 'c3'\" >msg.1-5-9 &&\n \t{\n \t\techo \"Squashed commit of the following:\" &&\n \t\techo &&\n@@ -57,7 +57,7 @@ create_merge_msgs () {\n \t} >squash.1-5-9 &&\n \techo >msg.nolog &&\n \t{\n-\t\techo \"* commit 'c3':\" &&\n+\t\techo \"* tag 'c3':\" &&\n \t\techo \"  commit 3\" &&\n \t\techo\n \t} >msg.log\ndiff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh\nindex 9114785..89619cf 100755\n--- a/t/t7604-merge-custom-message.sh\n+++ b/t/t7604-merge-custom-message.sh\n@@ -11,7 +11,7 @@ create_merge_msgs() {\n \n \tcp exp.subject exp.log &&\n \techo >>exp.log \"\" &&\n-\techo >>exp.log \"* commit 'c2':\" &&\n+\techo >>exp.log \"* tag 'c2':\" &&\n \techo >>exp.log \"  c2\"\n }\n \ndiff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh\nindex 9225fa6..8e7e0a5 100755\n--- a/t/t7608-merge-messages.sh\n+++ b/t/t7608-merge-messages.sh\n@@ -35,7 +35,7 @@ test_expect_success 'merge tag' '\n \tgit checkout master &&\n \ttest_commit master-3 &&\n \tgit merge tag-1 &&\n-\tcheck_oneline \"Merge commit Qtag-1Q\"\n+\tcheck_oneline \"Merge tag Qtag-1Q\"\n '\n \n test_expect_success 'ambiguous tag' '\n@@ -44,7 +44,7 @@ test_expect_success 'ambiguous tag' '\n \tgit checkout master &&\n \ttest_commit master-4 &&\n \tgit merge ambiguous &&\n-\tcheck_oneline \"Merge commit QambiguousQ\"\n+\tcheck_oneline \"Merge tag QambiguousQ\"\n '\n \n test_expect_success 'remote-tracking branch' '\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179191","messageId":"1320800523-5407-5-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 04/17] fetch: allow \"git fetch $there v1.0\" to fetch a tag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:50Z","receivedAt":"2011-11-09T01:01:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"You can already do so with \"git fetch $there tags/v1.0\" but if it is not\nambiguous there is no reason to force users to type more.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n refs.c |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex cab4394..ff20eeb 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -998,6 +998,7 @@ const char *ref_rev_parse_rules[] = {\n const char *ref_fetch_rules[] = {\n \t\"%.*s\",\n \t\"refs/%.*s\",\n+\t\"refs/tags/%.*s\",\n \t\"refs/heads/%.*s\",\n \tNULL\n };\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179190","messageId":"1320800523-5407-6-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 05/17] refs DWIMmery: use the same rule for both \"git fetch\" and others","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:51Z","receivedAt":"2011-11-09T01:01:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git log frotz\" can DWIM to \"refs/remotes/frotz/HEAD\", but in the remote\naccess context, \"git fetch frotz\" to fetch what the other side happened to\nhave fetched from what it calls 'frotz' (which may not have any relation\nto what we consider is 'frotz') the last time would not make much sense,\nso the fetch rules table did not include \"refs/remotes/%.*s/HEAD\".\n\nWhen the user really wants to, \"git fetch $there remotes/frotz/HEAD\" would\nlet her do so anyway, so this is not about safety or security; it merely\nis about confusion avoidance and discouraging meaningless usage.\n\nSpecifically, it is _not_ about ambiguity avoidance. A name that would\nbecome ambiguous if we use the same rules table for both fetch and local\nrev-parse would be ambiguous locally at the remote side.\n\nSo for the same reason as we added rule to allow \"git fetch $there v1.0\"\ninstead of \"git fetch $there tags/v1.0\" in the previous commit, here is a\nbit longer rope for the users, which incidentally simplifies our code.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n cache.h          |    2 +-\n refs.c           |    8 --------\n t/t5510-fetch.sh |    5 ++---\n 3 files changed, 3 insertions(+), 12 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex be07ec7..26322dd 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -873,7 +873,7 @@ extern int get_sha1_mb(const char *str, unsigned char *sha1);\n \n extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);\n extern const char *ref_rev_parse_rules[];\n-extern const char *ref_fetch_rules[];\n+#define ref_fetch_rules ref_rev_parse_rules\n \n extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg);\n extern int validate_headref(const char *ref);\ndiff --git a/refs.c b/refs.c\nindex ff20eeb..026c7ea 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -995,14 +995,6 @@ const char *ref_rev_parse_rules[] = {\n \tNULL\n };\n \n-const char *ref_fetch_rules[] = {\n-\t\"%.*s\",\n-\t\"refs/%.*s\",\n-\t\"refs/tags/%.*s\",\n-\t\"refs/heads/%.*s\",\n-\tNULL\n-};\n-\n int refname_match(const char *abbrev_name, const char *full_name, const char **rules)\n {\n \tconst char **p;\ndiff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\nindex 7e433b1..251d138 100755\n--- a/t/t5510-fetch.sh\n+++ b/t/t5510-fetch.sh\n@@ -116,7 +116,7 @@ test_expect_success 'fetch must not resolve short tag name' '\n \n '\n \n-test_expect_success 'fetch must not resolve short remote name' '\n+test_expect_success 'fetch can now resolve short remote name' '\n \n \tcd \"$D\" &&\n \tgit update-ref refs/remotes/six/HEAD HEAD &&\n@@ -125,8 +125,7 @@ test_expect_success 'fetch must not resolve short remote name' '\n \tcd six &&\n \tgit init &&\n \n-\ttest_must_fail git fetch .. six:six\n-\n+\tgit fetch .. six:six\n '\n \n test_expect_success 'create bundle 1' '\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179178","messageId":"1320800523-5407-7-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 06/17] fmt-merge-msg: avoid early returns","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:52Z","receivedAt":"2011-11-09T01:01:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"In various places in the codepath, the program tries to return early\nassuming there is no more work needed. That is generally untrue when\nover time new features are added.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/fmt-merge-msg.c |   20 ++++++++++----------\n 1 files changed, 10 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex 7e2f225..7b492f9 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -26,6 +26,7 @@ static int fmt_merge_msg_config(const char *key, const char *value, void *cb)\n \treturn 0;\n }\n \n+/* merge data per repository where the merged tips came from */\n struct src_data {\n \tstruct string_list branch, tag, r_branch, generic;\n \tint head_status;\n@@ -71,6 +72,11 @@ static int handle_line(char *line)\n \t\tline[len - 1] = 0;\n \tline += 42;\n \n+\t/*\n+\t * At this point, line points at the beginning of comment e.g.\n+\t * \"branch 'frotz' of git://that/repository.git\".\n+\t * Find the repository name and point it with src.\n+\t */\n \tsrc = strstr(line, \" of \");\n \tif (src) {\n \t\t*src = 0;\n@@ -283,10 +289,7 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,\n \t\t\tdie (\"Error in line %d: %.*s\", i, len, p);\n \t}\n \n-\tif (!srcs.nr)\n-\t\treturn 0;\n-\n-\tif (merge_title)\n+\tif (merge_title && srcs.nr)\n \t\tdo_fmt_merge_msg_title(out, current_branch);\n \n \tif (shortlog_len) {\n@@ -306,6 +309,8 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,\n \t\t\tshortlog(origins.items[i].string, origins.items[i].util,\n \t\t\t\t\thead, &rev, shortlog_len, out);\n \t}\n+\tif (out->len && out->buf[out->len-1] != '\\n')\n+\t\tstrbuf_addch(out, '\\n');\n \treturn 0;\n }\n \n@@ -341,12 +346,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \t\t\t     0);\n \tif (argc > 0)\n \t\tusage_with_options(fmt_merge_msg_usage, options);\n-\tif (message && !shortlog_len) {\n-\t\tchar nl = '\\n';\n-\t\twrite_in_full(STDOUT_FILENO, message, strlen(message));\n-\t\twrite_in_full(STDOUT_FILENO, &nl, 1);\n-\t\treturn 0;\n-\t}\n+\n \tif (shortlog_len < 0)\n \t\tdie(\"Negative --log=%d\", shortlog_len);\n \n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179177","messageId":"1320800523-5407-8-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 07/17] fmt-merge-msg: package options into a structure","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:53Z","receivedAt":"2011-11-09T01:01:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This way new features can be added more easily\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin.h               |    8 +++++++-\n builtin/fmt-merge-msg.c |   29 ++++++++++++++---------------\n builtin/merge.c         |    8 ++++++--\n 3 files changed, 27 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin.h b/builtin.h\nindex 0e9da90..e94a5dc 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -14,8 +14,14 @@ extern const char git_usage_string[];\n extern const char git_more_info_string[];\n \n extern void prune_packed_objects(int);\n+\n+struct fmt_merge_msg_opts {\n+\tunsigned add_title:1;\n+\tint shortlog_len;\n+};\n+\n extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n-\t\t\t int merge_title, int shortlog_len);\n+\t\t\t struct fmt_merge_msg_opts *);\n extern void commit_notes(struct notes_tree *t, const char *msg);\n \n struct notes_rewrite_cfg {\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex 7b492f9..3ff9564 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -209,7 +209,7 @@ static void shortlog(const char *name, unsigned char *sha1,\n \tstring_list_clear(&subjects, 0);\n }\n \n-static void do_fmt_merge_msg_title(struct strbuf *out,\n+static void fmt_merge_msg_title(struct strbuf *out,\n \tconst char *current_branch) {\n \tint i = 0;\n \tchar *sep = \"\";\n@@ -262,8 +262,9 @@ static void do_fmt_merge_msg_title(struct strbuf *out,\n \t\tstrbuf_addf(out, \" into %s\\n\", current_branch);\n }\n \n-static int do_fmt_merge_msg(int merge_title, struct strbuf *in,\n-\tstruct strbuf *out, int shortlog_len) {\n+int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n+\t\t  struct fmt_merge_msg_opts *opts)\n+{\n \tint i = 0, pos = 0;\n \tunsigned char head_sha1[20];\n \tconst char *current_branch;\n@@ -289,10 +290,10 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,\n \t\t\tdie (\"Error in line %d: %.*s\", i, len, p);\n \t}\n \n-\tif (merge_title && srcs.nr)\n-\t\tdo_fmt_merge_msg_title(out, current_branch);\n+\tif (opts->add_title && srcs.nr)\n+\t\tfmt_merge_msg_title(out, current_branch);\n \n-\tif (shortlog_len) {\n+\tif (opts->shortlog_len) {\n \t\tstruct commit *head;\n \t\tstruct rev_info rev;\n \n@@ -307,18 +308,13 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,\n \n \t\tfor (i = 0; i < origins.nr; i++)\n \t\t\tshortlog(origins.items[i].string, origins.items[i].util,\n-\t\t\t\t\thead, &rev, shortlog_len, out);\n+\t\t\t\t head, &rev, opts->shortlog_len, out);\n \t}\n \tif (out->len && out->buf[out->len-1] != '\\n')\n \t\tstrbuf_addch(out, '\\n');\n \treturn 0;\n }\n \n-int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n-\t\t  int merge_title, int shortlog_len) {\n-\treturn do_fmt_merge_msg(merge_title, in, out, shortlog_len);\n-}\n-\n int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n {\n \tconst char *inpath = NULL;\n@@ -340,6 +336,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \tFILE *in = stdin;\n \tstruct strbuf input = STRBUF_INIT, output = STRBUF_INIT;\n \tint ret;\n+\tstruct fmt_merge_msg_opts opts;\n \n \tgit_config(fmt_merge_msg_config, NULL);\n \targc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,\n@@ -361,10 +358,12 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \n \tif (message)\n \t\tstrbuf_addstr(&output, message);\n-\tret = fmt_merge_msg(&input, &output,\n-\t\t\t    message ? 0 : 1,\n-\t\t\t    shortlog_len);\n \n+\tmemset(&opts, 0, sizeof(opts));\n+\topts.add_title = !message;\n+\topts.shortlog_len = shortlog_len;\n+\n+\tret = fmt_merge_msg(&input, &output, &opts);\n \tif (ret)\n \t\treturn ret;\n \twrite_in_full(STDOUT_FILENO, output.buf, output.len);\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 6a44b6d..48e7f00 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1229,8 +1229,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t\tmerge_name(argv[i], &merge_names);\n \n \t\tif (!have_message || shortlog_len) {\n-\t\t\tfmt_merge_msg(&merge_names, &merge_msg, !have_message,\n-\t\t\t\t      shortlog_len);\n+\t\t\tstruct fmt_merge_msg_opts opts;\n+\t\t\tmemset(&opts, 0, sizeof(opts));\n+\t\t\topts.add_title = !have_message;\n+\t\t\topts.shortlog_len = shortlog_len;\n+\n+\t\t\tfmt_merge_msg(&merge_names, &merge_msg, &opts);\n \t\t\tif (merge_msg.len)\n \t\t\t\tstrbuf_setlen(&merge_msg, merge_msg.len - 1);\n \t\t}\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179180","messageId":"1320800523-5407-9-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 08/17] fmt-merge-msg: Add contents of merged tag in the merge message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:54Z","receivedAt":"2011-11-09T01:01:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When a contributor asks the integrator to merge her history, a signed tag\ncan be a good vehicle to communicate the authenticity of the request while\nconveying other information such as the purpose of the topic.\n\nE.g. a signed tag \"for-linus\" can be created, and the integrator can run:\n\n   $ git pull git://example.com/work.git/ for-linus\n\nThis would allow the integrator to run \"git verify-tag FETCH_HEAD\" to\nvalidate the signed tag.\n\nUpdate fmt-merge-msg so that it pre-fills the merge message template with\nthe body (but not signature) of the tag object to help the integrator write\na better merge message, in the same spirit as the existing merge.log summary\nlines.\n\nThe message that comes from GPG signature validation is also included in\nthe merge message template to help the integrator verify it, but they are\nprefixed with \"#\" to make them comments.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/fmt-merge-msg.c |   72 +++++++++++++++++++++++++++++++++++++++++++++-\n strbuf.c                |   14 +++++++++\n strbuf.h                |    8 +++++\n 3 files changed, 92 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex 3ff9564..7dae846 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -5,6 +5,7 @@\n #include \"revision.h\"\n #include \"tag.h\"\n #include \"string-list.h\"\n+#include \"gpg-interface.h\"\n \n static const char * const fmt_merge_msg_usage[] = {\n \t\"git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]\",\n@@ -262,6 +263,70 @@ static void fmt_merge_msg_title(struct strbuf *out,\n \t\tstrbuf_addf(out, \" into %s\\n\", current_branch);\n }\n \n+static void fmt_tag_signature(struct strbuf *tagbuf,\n+\t\t\t      struct strbuf *sig,\n+\t\t\t      const char *buf,\n+\t\t\t      unsigned long len)\n+{\n+\tconst char *tag_body = strstr(buf, \"\\n\\n\");\n+\tif (tag_body) {\n+\t\ttag_body += 2;\n+\t\tstrbuf_add(tagbuf, tag_body, buf + len - tag_body);\n+\t}\n+\tstrbuf_complete_line(tagbuf);\n+\tstrbuf_add_lines(tagbuf, \"# \", sig->buf, sig->len);\n+}\n+\n+static void fmt_merge_msg_sigs(struct strbuf *out)\n+{\n+\tint i, tag_number = 0, first_tag = 0;\n+\tstruct strbuf tagbuf = STRBUF_INIT;\n+\n+\tfor (i = 0; i < origins.nr; i++) {\n+\t\tunsigned char *sha1 = origins.items[i].util;\n+\t\tenum object_type type;\n+\t\tunsigned long size, len;\n+\t\tchar *buf = read_sha1_file(sha1, &type, &size);\n+\t\tstruct strbuf sig = STRBUF_INIT;\n+\n+\t\tif (!buf || type != OBJ_TAG)\n+\t\t\tgoto next;\n+\t\tlen = parse_signature(buf, size);\n+\n+\t\tif (size == len)\n+\t\t\t; /* merely annotated */\n+\t\telse if (verify_signed_buffer(buf, len, buf + len, size - len, &sig)) {\n+\t\t\tif (!sig.len)\n+\t\t\t\tstrbuf_addstr(&sig, \"gpg verification failed.\\n\");\n+\t\t}\n+\n+\t\tif (!tag_number++) {\n+\t\t\tfmt_tag_signature(&tagbuf, &sig, buf, len);\n+\t\t\tfirst_tag = i;\n+\t\t} else {\n+\t\t\tif (tag_number == 2) {\n+\t\t\t\tstruct strbuf tagline = STRBUF_INIT;\n+\t\t\t\tstrbuf_addf(&tagline, \"\\n# %s\\n\",\n+\t\t\t\t\t    origins.items[first_tag].string);\n+\t\t\t\tstrbuf_insert(&tagbuf, 0, tagline.buf,\n+\t\t\t\t\t      tagline.len);\n+\t\t\t\tstrbuf_release(&tagline);\n+\t\t\t}\n+\t\t\tstrbuf_addf(&tagbuf, \"\\n# %s\\n\",\n+\t\t\t\t    origins.items[i].string);\n+\t\t\tfmt_tag_signature(&tagbuf, &sig, buf, len);\n+\t\t}\n+\t\tstrbuf_release(&sig);\n+\tnext:\n+\t\tfree(buf);\n+\t}\n+\tif (tagbuf.len) {\n+\t\tstrbuf_addch(out, '\\n');\n+\t\tstrbuf_addbuf(out, &tagbuf);\n+\t}\n+\tstrbuf_release(&tagbuf);\n+}\n+\n int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n \t\t  struct fmt_merge_msg_opts *opts)\n {\n@@ -293,6 +358,9 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n \tif (opts->add_title && srcs.nr)\n \t\tfmt_merge_msg_title(out, current_branch);\n \n+\tif (origins.nr)\n+\t\tfmt_merge_msg_sigs(out);\n+\n \tif (opts->shortlog_len) {\n \t\tstruct commit *head;\n \t\tstruct rev_info rev;\n@@ -310,8 +378,8 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n \t\t\tshortlog(origins.items[i].string, origins.items[i].util,\n \t\t\t\t head, &rev, opts->shortlog_len, out);\n \t}\n-\tif (out->len && out->buf[out->len-1] != '\\n')\n-\t\tstrbuf_addch(out, '\\n');\n+\n+\tstrbuf_complete_line(out);\n \treturn 0;\n }\n \ndiff --git a/strbuf.c b/strbuf.c\nindex 3ad2cc0..a849705 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -397,3 +397,17 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)\n \n \treturn len;\n }\n+\n+void strbuf_add_lines(struct strbuf *out, const char *prefix,\n+\t\t      const char *buf, size_t size)\n+{\n+\twhile (size) {\n+\t\tconst char *next = memchr(buf, '\\n', size);\n+\t\tnext = next ? (next + 1) : (buf + size);\n+\t\tstrbuf_addstr(out, prefix);\n+\t\tstrbuf_add(out, buf, next - buf);\n+\t\tsize -= next - buf;\n+\t\tbuf = next;\n+\t}\n+\tstrbuf_complete_line(out);\n+}\ndiff --git a/strbuf.h b/strbuf.h\nindex 46a33f8..08fc13d 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -100,6 +100,14 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);\n __attribute__((format (printf,2,0)))\n extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);\n \n+extern void strbuf_add_lines(struct strbuf *sb, const char *prefix, const char *buf, size_t size);\n+\n+static inline void strbuf_complete_line(struct strbuf *sb)\n+{\n+\tif (sb->len && sb->buf[sb->len - 1] != '\\n')\n+\t\tstrbuf_addch(sb, '\\n');\n+}\n+\n extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);\n /* XXX: if read fails, any partial read is undone */\n extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179182","messageId":"1320800523-5407-10-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 09/17] merge: make usage of commit->util more extensible","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:55Z","receivedAt":"2011-11-09T01:01:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The merge-recursive code uses the commit->util field directly to annotate\nthe commit objects given from the command line, i.e. the remote heads to\nbe merged, with a single string to be used to describe it in its trace\nmessages and conflict markers.\n\nCorrect this short-signtedness by redefining the field to be a pointer to\na structure \"struct merge_remote_desc\" that later enhancements can add\nmore information. Store the original objects we were told to merge in a\nfield \"obj\" in this struct, so that we can recover the tag we were told to\nmerge.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/merge.c   |   63 +++++++++++++++++++---------------------------------\n commit.c          |   19 ++++++++++++++++\n commit.h          |   13 +++++++++++\n merge-recursive.c |   13 +++++------\n 4 files changed, 61 insertions(+), 47 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 48e7f00..8d4eb4e 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -406,20 +406,10 @@ static void finish(struct commit *head_commit,\n \tstrbuf_release(&reflog_message);\n }\n \n-static struct object *want_commit(const char *name)\n-{\n-\tstruct object *obj;\n-\tunsigned char sha1[20];\n-\tif (get_sha1(name, sha1))\n-\t\treturn NULL;\n-\tobj = parse_object(sha1);\n-\treturn peel_to_type(name, 0, obj, OBJ_COMMIT);\n-}\n-\n /* Get the name for the merge commit's message. */\n static void merge_name(const char *remote, struct strbuf *msg)\n {\n-\tstruct object *remote_head;\n+\tstruct commit *remote_head;\n \tunsigned char branch_head[20], buf_sha[20];\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct strbuf bname = STRBUF_INIT;\n@@ -431,7 +421,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \tremote = bname.buf;\n \n \tmemset(branch_head, 0, sizeof(branch_head));\n-\tremote_head = want_commit(remote);\n+\tremote_head = get_merge_parent(remote);\n \tif (!remote_head)\n \t\tdie(_(\"'%s' does not point to a commit\"), remote);\n \n@@ -487,7 +477,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t\tif (resolve_ref(truname.buf, buf_sha, 1, NULL)) {\n \t\t\tstrbuf_addf(msg,\n \t\t\t\t    \"%s\\t\\tbranch '%s'%s of .\\n\",\n-\t\t\t\t    sha1_to_hex(remote_head->sha1),\n+\t\t\t\t    sha1_to_hex(remote_head->object.sha1),\n \t\t\t\t    truname.buf + 11,\n \t\t\t\t    (early ? \" (early part)\" : \"\"));\n \t\t\tstrbuf_release(&truname);\n@@ -515,7 +505,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t\tgoto cleanup;\n \t}\n \tstrbuf_addf(msg, \"%s\\t\\tcommit '%s'\\n\",\n-\t\tsha1_to_hex(remote_head->sha1), remote);\n+\t\tsha1_to_hex(remote_head->object.sha1), remote);\n cleanup:\n \tstrbuf_release(&buf);\n \tstrbuf_release(&bname);\n@@ -719,7 +709,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \t\t\t\tdie(_(\"Unknown option for merge-recursive: -X%s\"), xopts[x]);\n \n \t\to.branch1 = head_arg;\n-\t\to.branch2 = remoteheads->item->util;\n+\t\to.branch2 = merge_remote_util(remoteheads->item)->name;\n \n \t\tfor (j = common; j; j = j->next)\n \t\t\tcommit_list_insert(j->item, &reversed);\n@@ -1190,7 +1180,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\targv += 2;\n \t\targc -= 2;\n \t} else if (!head_commit) {\n-\t\tstruct object *remote_head;\n+\t\tstruct commit *remote_head;\n \t\t/*\n \t\t * If the merged head is a valid one there is no reason\n \t\t * to forbid \"git merge\" into a branch yet to be born.\n@@ -1204,12 +1194,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tif (!allow_fast_forward)\n \t\t\tdie(_(\"Non-fast-forward commit does not make sense into \"\n \t\t\t    \"an empty head\"));\n-\t\tremote_head = want_commit(argv[0]);\n+\t\tremote_head = get_merge_parent(argv[0]);\n \t\tif (!remote_head)\n \t\t\tdie(_(\"%s - not something we can merge\"), argv[0]);\n-\t\tread_empty(remote_head->sha1, 0);\n-\t\tupdate_ref(\"initial pull\", \"HEAD\", remote_head->sha1, NULL, 0,\n-\t\t\t\tDIE_ON_ERR);\n+\t\tread_empty(remote_head->object.sha1, 0);\n+\t\tupdate_ref(\"initial pull\", \"HEAD\", remote_head->object.sha1,\n+\t\t\t   NULL, 0, DIE_ON_ERR);\n \t\treturn 0;\n \t} else {\n \t\tstruct strbuf merge_names = STRBUF_INIT;\n@@ -1218,12 +1208,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\thead_arg = \"HEAD\";\n \n \t\t/*\n-\t\t * All the rest are the commits being merged;\n-\t\t * prepare the standard merge summary message to\n-\t\t * be appended to the given message.  If remote\n-\t\t * is invalid we will die later in the common\n-\t\t * codepath so we discard the error in this\n-\t\t * loop.\n+\t\t * All the rest are the commits being merged; prepare\n+\t\t * the standard merge summary message to be appended\n+\t\t * to the given message.\n \t\t */\n \t\tfor (i = 0; i < argc; i++)\n \t\t\tmerge_name(argv[i], &merge_names);\n@@ -1251,17 +1238,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \tstrbuf_reset(&buf);\n \n \tfor (i = 0; i < argc; i++) {\n-\t\tstruct object *o;\n-\t\tstruct commit *commit;\n-\n-\t\to = want_commit(argv[i]);\n-\t\tif (!o)\n+\t\tstruct commit *commit = get_merge_parent(argv[i]);\n+\t\tif (!commit)\n \t\t\tdie(_(\"%s - not something we can merge\"), argv[i]);\n-\t\tcommit = lookup_commit(o->sha1);\n-\t\tcommit->util = (void *)argv[i];\n \t\tremotes = &commit_list_insert(commit, remotes)->next;\n-\n-\t\tstrbuf_addf(&buf, \"GITHEAD_%s\", sha1_to_hex(o->sha1));\n+\t\tstrbuf_addf(&buf, \"GITHEAD_%s\",\n+\t\t\t    sha1_to_hex(commit->object.sha1));\n \t\tsetenv(buf.buf, argv[i], 1);\n \t\tstrbuf_reset(&buf);\n \t}\n@@ -1307,7 +1289,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t\t!hashcmp(common->item->object.sha1, head_commit->object.sha1)) {\n \t\t/* Again the most common case of merging one remote. */\n \t\tstruct strbuf msg = STRBUF_INIT;\n-\t\tstruct object *o;\n+\t\tstruct commit *commit;\n \t\tchar hex[41];\n \n \t\tstrcpy(hex, find_unique_abbrev(head_commit->object.sha1, DEFAULT_ABBREV));\n@@ -1321,14 +1303,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tif (have_message)\n \t\t\tstrbuf_addstr(&msg,\n \t\t\t\t\" (no commit created; -m option ignored)\");\n-\t\to = want_commit(sha1_to_hex(remoteheads->item->object.sha1));\n-\t\tif (!o)\n+\t\tcommit = remoteheads->item;\n+\t\tif (!commit)\n \t\t\treturn 1;\n \n-\t\tif (checkout_fast_forward(head_commit->object.sha1, remoteheads->item->object.sha1))\n+\t\tif (checkout_fast_forward(head_commit->object.sha1,\n+\t\t\t\t\t  commit->object.sha1))\n \t\t\treturn 1;\n \n-\t\tfinish(head_commit, o->sha1, msg.buf);\n+\t\tfinish(head_commit, commit->object.sha1, msg.buf);\n \t\tdrop_save();\n \t\treturn 0;\n \t} else if (!remoteheads->next && common->next)\ndiff --git a/commit.c b/commit.c\nindex 73b7e00..83ff503 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -894,3 +894,22 @@ int commit_tree(const char *msg, unsigned char *tree,\n \tstrbuf_release(&buffer);\n \treturn result;\n }\n+\n+struct commit *get_merge_parent(const char *name)\n+{\n+\tstruct object *obj;\n+\tstruct commit *commit;\n+\tunsigned char sha1[20];\n+\tif (get_sha1(name, sha1))\n+\t\treturn NULL;\n+\tobj = parse_object(sha1);\n+\tcommit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);\n+\tif (commit && !commit->util) {\n+\t\tstruct merge_remote_desc *desc;\n+\t\tdesc = xmalloc(sizeof(*desc));\n+\t\tdesc->obj = obj;\n+\t\tdesc->name = strdup(name);\n+\t\tcommit->util = desc;\n+\t}\n+\treturn commit;\n+}\ndiff --git a/commit.h b/commit.h\nindex 009b113..5b57eab 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -185,4 +185,17 @@ extern int commit_tree(const char *msg, unsigned char *tree,\n \t\tstruct commit_list *parents, unsigned char *ret,\n \t\tconst char *author);\n \n+struct merge_remote_desc {\n+\tstruct object *obj; /* the named object, could be a tag */\n+\tconst char *name;\n+};\n+#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))\n+\n+/*\n+ * Given \"name\" from the command line to merge, find the commit object\n+ * and return it, while storing merge_remote_desc in its ->util field,\n+ * to allow callers to tell if we are told to merge a tag.\n+ */\n+struct commit *get_merge_parent(const char *name);\n+\n #endif /* COMMIT_H */\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex cc664c3..5a2db29 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -38,16 +38,15 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,\n \treturn lookup_tree(shifted);\n }\n \n-/*\n- * A virtual commit has (const char *)commit->util set to the name.\n- */\n-\n static struct commit *make_virtual_commit(struct tree *tree, const char *comment)\n {\n \tstruct commit *commit = xcalloc(1, sizeof(struct commit));\n+\tstruct merge_remote_desc *desc = xmalloc(sizeof(*desc));\n+\n+\tdesc->name = comment;\n+\tdesc->obj = (struct object *)commit;\n \tcommit->tree = tree;\n-\tcommit->util = (void*)comment;\n-\t/* avoid warnings */\n+\tcommit->util = desc;\n \tcommit->object.parsed = 1;\n \treturn commit;\n }\n@@ -184,7 +183,7 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)\n \tfor (i = o->call_depth; i--;)\n \t\tfputs(\"  \", stdout);\n \tif (commit->util)\n-\t\tprintf(\"virtual %s\\n\", (char *)commit->util);\n+\t\tprintf(\"virtual %s\\n\", merge_remote_util(commit)->name);\n \telse {\n \t\tprintf(\"%s \", find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));\n \t\tif (parse_commit(commit) != 0)\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179181","messageId":"1320800523-5407-11-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 10/17] merge: record tag objects without peeling in MERGE_HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:56Z","receivedAt":"2011-11-09T01:01:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Otherwise, \"git commit\" wouldn't have a way to tell that we were in the\nmiddle of merging an annotated or signed tag, not a plain commit, after\n\"git merge\" stops to ask the user to resolve conflicts.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/merge.c  |   13 ++++++++++---\n t/t7600-merge.sh |    6 +++++-\n 2 files changed, 15 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 8d4eb4e..7158e8e 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1045,9 +1045,16 @@ static void write_merge_state(void)\n \tstruct commit_list *j;\n \tstruct strbuf buf = STRBUF_INIT;\n \n-\tfor (j = remoteheads; j; j = j->next)\n-\t\tstrbuf_addf(&buf, \"%s\\n\",\n-\t\t\tsha1_to_hex(j->item->object.sha1));\n+\tfor (j = remoteheads; j; j = j->next) {\n+\t\tunsigned const char *sha1;\n+\t\tstruct commit *c = j->item;\n+\t\tif (c->util && merge_remote_util(c)->obj) {\n+\t\t\tsha1 = merge_remote_util(c)->obj->sha1;\n+\t\t} else {\n+\t\t\tsha1 = c->object.sha1;\n+\t\t}\n+\t\tstrbuf_addf(&buf, \"%s\\n\", sha1_to_hex(sha1));\n+\t}\n \tfd = open(git_path(\"MERGE_HEAD\"), O_WRONLY | O_CREAT, 0666);\n \tif (fd < 0)\n \t\tdie_errno(_(\"Could not open '%s' for writing\"),\ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex b91d022..5d8c428 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -96,7 +96,11 @@ verify_parents () {\n \n verify_mergeheads () {\n \tprintf '%s\\n' \"$@\" >mergehead.expected &&\n-\ttest_cmp mergehead.expected .git/MERGE_HEAD\n+\twhile read sha1 rest\n+\tdo\n+\t\tgit rev-parse $sha1\n+\tdone <.git/MERGE_HEAD >mergehead.actual &&\n+\ttest_cmp mergehead.expected mergehead.actual\n }\n \n verify_no_mergehead () {\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179183","messageId":"1320800523-5407-12-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 11/17] commit: copy merged signed tags to headers of merge commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:57Z","receivedAt":"2011-11-09T01:01:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Now MERGE_HEAD records the tag objects without peeling, we could record\nthe result of manual conflict resolution via \"git commit\" without losing\nthe tag information. Introduce a new \"mergetag\" multi-line header field to\nthe commit object, and use it to store the entire contents of each signed\ntag merged.\n\nA commit header that has a multi-line payload begins with the header tag\n(e.g. \"mergetag\" in this case), SP, the first line of payload, LF, and all\nthe remaining lines have a SP inserted at the beginning.\n\nIn hindsight, it would have been better to make \"merge --continue\" as the\nway to continue from such an interrupted merge, not \"commit\", but this is\na backward compatibility baggage we would need to carry around for now.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/commit.c |   10 +++---\n commit.c         |   95 +++++++++++++++++++++++++++++++++++++++++++++++++++--\n commit.h         |   21 +++++++++++-\n 3 files changed, 115 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex c46f2d1..4688a73 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1425,7 +1425,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\t\tpptr = &commit_list_insert(c->item, pptr)->next;\n \t} else if (whence == FROM_MERGE) {\n \t\tstruct strbuf m = STRBUF_INIT;\n-\t\tstruct commit *commit;\n \t\tFILE *fp;\n \n \t\tif (!reflog_msg)\n@@ -1436,11 +1435,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\t\tdie_errno(_(\"could not open '%s' for reading\"),\n \t\t\t\t  git_path(\"MERGE_HEAD\"));\n \t\twhile (strbuf_getline(&m, fp, '\\n') != EOF) {\n-\t\t\tunsigned char sha1[20];\n-\t\t\tif (get_sha1_hex(m.buf, sha1) < 0)\n+\t\t\tstruct commit *parent;\n+\n+\t\t\tparent = get_merge_parent(m.buf);\n+\t\t\tif (!parent)\n \t\t\t\tdie(_(\"Corrupt MERGE_HEAD file (%s)\"), m.buf);\n-\t\t\tcommit = lookup_commit_or_die(sha1, \"MERGE_HEAD\");\n-\t\t\tpptr = &commit_list_insert(commit, pptr)->next;\n+\t\t\tpptr = &commit_list_insert(parent, pptr)->next;\n \t\t}\n \t\tfclose(fp);\n \t\tstrbuf_release(&m);\ndiff --git a/commit.c b/commit.c\nindex 83ff503..ee12eff 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -840,14 +840,94 @@ struct commit_list *reduce_heads(struct commit_list *heads)\n \treturn result;\n }\n \n+static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail)\n+{\n+\tstruct merge_remote_desc *desc;\n+\tstruct commit_extra_header *mergetag;\n+\tchar *buf;\n+\tunsigned long size, len;\n+\tenum object_type type;\n+\n+\tdesc = merge_remote_util(parent);\n+\tif (!desc || !desc->obj)\n+\t\treturn;\n+\tbuf = read_sha1_file(desc->obj->sha1, &type, &size);\n+\tif (!buf || type != OBJ_TAG)\n+\t\tgoto free_return;\n+\tlen = parse_signature(buf, size);\n+\tif (size == len)\n+\t\tgoto free_return;\n+\t/*\n+\t * We could verify this signature and either omit the tag when\n+\t * it does not validate, but the integrator may not have the\n+\t * public key of the signer of the tag he is merging, while a\n+\t * later auditor may have it while auditing, so let's not run\n+\t * verify-signed-buffer here for now...\n+\t *\n+\t * if (verify_signed_buffer(buf, len, buf + len, size - len, ...))\n+\t *\twarn(\"warning: signed tag unverified.\");\n+\t */\n+\tmergetag = xcalloc(1, sizeof(*mergetag));\n+\tmergetag->key = \"mergetag\";\n+\tmergetag->value = buf;\n+\tmergetag->len = size;\n+\n+\t**tail = mergetag;\n+\t*tail = &mergetag->next;\n+\treturn;\n+\n+free_return:\n+\tfree(buf);\n+}\n+\n+void append_merge_tag_headers(struct commit_list *parents,\n+\t\t\t      struct commit_extra_header ***tail)\n+{\n+\twhile (parents) {\n+\t\tstruct commit *parent = parents->item;\n+\t\thandle_signed_tag(parent, tail);\n+\t\tparents = parents->next;\n+\t}\n+}\n+\n+static void add_extra_header(struct strbuf *buffer,\n+\t\t\t     struct commit_extra_header *extra)\n+{\n+\tstrbuf_addstr(buffer, extra->key);\n+\tstrbuf_add_lines(buffer, \" \", extra->value, extra->len);\n+}\n+\n+void free_commit_extra_headers(struct commit_extra_header *extra)\n+{\n+\twhile (extra) {\n+\t\tstruct commit_extra_header *next = extra->next;\n+\t\tfree(extra->value);\n+\t\tfree(extra);\n+\t\textra = next;\n+\t}\n+}\n+\n+int commit_tree(const char *msg, unsigned char *tree,\n+\t\tstruct commit_list *parents, unsigned char *ret,\n+\t\tconst char *author)\n+{\n+\tstruct commit_extra_header *extra = NULL, **tail = &extra;\n+\tint result;\n+\n+\tappend_merge_tag_headers(parents, &tail);\n+\tresult = commit_tree_extended(msg, tree, parents, ret, author, extra);\n+\tfree_commit_extra_headers(extra);\n+\treturn result;\n+}\n+\n static const char commit_utf8_warn[] =\n \"Warning: commit message does not conform to UTF-8.\\n\"\n \"You may want to amend it after fixing the message, or set the config\\n\"\n \"variable i18n.commitencoding to the encoding your project uses.\\n\";\n \n-int commit_tree(const char *msg, unsigned char *tree,\n-\t\tstruct commit_list *parents, unsigned char *ret,\n-\t\tconst char *author)\n+int commit_tree_extended(const char *msg, unsigned char *tree,\n+\t\t\t struct commit_list *parents, unsigned char *ret,\n+\t\t\t const char *author, struct commit_extra_header *extra)\n {\n \tint result;\n \tint encoding_is_utf8;\n@@ -868,8 +948,10 @@ int commit_tree(const char *msg, unsigned char *tree,\n \t */\n \twhile (parents) {\n \t\tstruct commit_list *next = parents->next;\n+\t\tstruct commit *parent = parents->item;\n+\n \t\tstrbuf_addf(&buffer, \"parent %s\\n\",\n-\t\t\tsha1_to_hex(parents->item->object.sha1));\n+\t\t\t    sha1_to_hex(parent->object.sha1));\n \t\tfree(parents);\n \t\tparents = next;\n \t}\n@@ -881,6 +963,11 @@ int commit_tree(const char *msg, unsigned char *tree,\n \tstrbuf_addf(&buffer, \"committer %s\\n\", git_committer_info(IDENT_ERROR_ON_NO_NAME));\n \tif (!encoding_is_utf8)\n \t\tstrbuf_addf(&buffer, \"encoding %s\\n\", git_commit_encoding);\n+\n+\twhile (extra) {\n+\t\tadd_extra_header(&buffer, extra);\n+\t\textra = extra->next;\n+\t}\n \tstrbuf_addch(&buffer, '\\n');\n \n \t/* And add the comment */\ndiff --git a/commit.h b/commit.h\nindex 5b57eab..c1a723e 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -181,9 +181,26 @@ static inline int single_parent(struct commit *commit)\n \n struct commit_list *reduce_heads(struct commit_list *heads);\n \n+struct commit_extra_header {\n+\tstruct commit_extra_header *next;\n+\tchar *key;\n+\tchar *value;\n+\tsize_t len;\n+};\n+\n+extern void append_merge_tag_headers(struct commit_list *parents,\n+\t\t\t\t     struct commit_extra_header ***tail);\n+\n extern int commit_tree(const char *msg, unsigned char *tree,\n-\t\tstruct commit_list *parents, unsigned char *ret,\n-\t\tconst char *author);\n+\t\t       struct commit_list *parents, unsigned char *ret,\n+\t\t       const char *author);\n+\n+extern int commit_tree_extended(const char *msg, unsigned char *tree,\n+\t\t\t\tstruct commit_list *parents, unsigned char *ret,\n+\t\t\t\tconst char *author,\n+\t\t\t\tstruct commit_extra_header *);\n+\n+extern void free_commit_extra_headers(struct commit_extra_header *extra);\n \n struct merge_remote_desc {\n \tstruct object *obj; /* the named object, could be a tag */\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179189","messageId":"1320800523-5407-13-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 12/17] merge: force edit mode when merging a tag object","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:58Z","receivedAt":"2011-11-09T01:01:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Now that we allow pulling a tag from the remote site to validate the\nauthenticity, we should give the user the final chance to verify and\nedit the merge message.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/merge.c |    4 ++++\n 1 files changed, 4 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 7158e8e..3b3e374 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1253,6 +1253,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t\t    sha1_to_hex(commit->object.sha1));\n \t\tsetenv(buf.buf, argv[i], 1);\n \t\tstrbuf_reset(&buf);\n+\t\tif (merge_remote_util(commit) &&\n+\t\t    merge_remote_util(commit)->obj &&\n+\t\t    merge_remote_util(commit)->obj->type == OBJ_TAG)\n+\t\t\toption_edit = 1;\n \t}\n \n \tif (!use_strategies) {\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179186","messageId":"1320800523-5407-14-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 13/17] commit: teach --amend to carry forward extra headers","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:01:59Z","receivedAt":"2011-11-09T01:01:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"After running \"git pull $there for-linus\" to merge a signed tag, the\nintegrator may need to amend the resulting merge commit to fix typoes\nin it. Teach --amend option to read the existing extra headers, and\ncarry them forward.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/commit.c |    9 ++++++-\n commit.c         |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n commit.h         |    3 ++\n 3 files changed, 70 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 4688a73..fca7ea0 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1382,6 +1382,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \tint allow_fast_forward = 1;\n \tstruct wt_status s;\n \tstruct commit *current_head = NULL;\n+\tstruct commit_extra_header *extra = NULL;\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_commit_usage, builtin_commit_options);\n@@ -1483,12 +1484,16 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\texit(1);\n \t}\n \n-\tif (commit_tree(sb.buf, active_cache_tree->sha1, parents, sha1,\n-\t\t\tauthor_ident.buf)) {\n+\tif (amend)\n+\t\textra = read_commit_extra_headers(current_head);\n+\n+\tif (commit_tree_extended(sb.buf, active_cache_tree->sha1, parents, sha1,\n+\t\t\t\t author_ident.buf, extra)) {\n \t\trollback_index_files();\n \t\tdie(_(\"failed to write commit object\"));\n \t}\n \tstrbuf_release(&author_ident);\n+\tfree_commit_extra_headers(extra);\n \n \tref_lock = lock_any_ref_for_update(\"HEAD\",\n \t\t\t\t\t   !current_head\ndiff --git a/commit.c b/commit.c\nindex ee12eff..1c05879 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -897,6 +897,66 @@ static void add_extra_header(struct strbuf *buffer,\n \tstrbuf_add_lines(buffer, \" \", extra->value, extra->len);\n }\n \n+struct commit_extra_header *read_commit_extra_headers(struct commit *commit)\n+{\n+\tstruct commit_extra_header *extra = NULL;\n+\tsize_t size;\n+\tenum object_type type;\n+\tchar *buffer = read_sha1_file(commit->object.sha1, &type, &size);\n+\tif (buffer && type == OBJ_COMMIT)\n+\t\textra = read_commit_extra_header_lines(buffer, size);\n+\tfree(buffer);\n+\treturn extra;\n+}\n+\n+static inline int standard_header_field(const char *field, size_t len)\n+{\n+\treturn ((len == 4 && !memcmp(field, \"tree \", 5)) ||\n+\t\t(len == 6 && !memcmp(field, \"parent \", 7)) ||\n+\t\t(len == 6 && !memcmp(field, \"author \", 7)) ||\n+\t\t(len == 9 && !memcmp(field, \"committer \", 10)) ||\n+\t\t(len == 8 && !memcmp(field, \"encoding \", 9)));\n+}\n+\n+struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, size_t size)\n+{\n+\tstruct commit_extra_header *extra = NULL, **tail = &extra, *it = NULL;\n+\tconst char *line, *next, *eof, *eob;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\n+\tfor (line = buffer, eob = line + size;\n+\t     line < eob && *line != '\\n';\n+\t     line = next) {\n+\t\tnext = memchr(line, '\\n', eob - line);\n+\t\tnext = next ? next + 1 : eob;\n+\t\tif (*line == ' ') {\n+\t\t\t/* continuation */\n+\t\t\tstrbuf_add(&buf, line + 1, next - (line + 1));\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (it)\n+\t\t\tit->value = strbuf_detach(&buf, &it->len);\n+\t\tstrbuf_reset(&buf);\n+\t\tit = NULL;\n+\n+\t\teof = strchr(line, ' ');\n+\t\tif (next <= eof)\n+\t\t\tcontinue; /* malformed */\n+\n+\t\tif (standard_header_field(line, eof - line))\n+\t\t\tcontinue;\n+\n+\t\tit = xcalloc(1, sizeof(*it));\n+\t\tit->key = xmemdupz(line, eof-line);\n+\t\t*tail = it;\n+\t\ttail = &it->next;\n+\t\tstrbuf_add(&buf, eof + 1, next - (eof + 1));\n+\t}\n+\tif (it)\n+\t\tit->value = strbuf_detach(&buf, &it->len);\n+\treturn extra;\n+}\n+\n void free_commit_extra_headers(struct commit_extra_header *extra)\n {\n \twhile (extra) {\ndiff --git a/commit.h b/commit.h\nindex c1a723e..3745f12 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -200,6 +200,9 @@ extern int commit_tree_extended(const char *msg, unsigned char *tree,\n \t\t\t\tconst char *author,\n \t\t\t\tstruct commit_extra_header *);\n \n+extern struct commit_extra_header *read_commit_extra_headers(struct commit *);\n+extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len);\n+\n extern void free_commit_extra_headers(struct commit_extra_header *extra);\n \n struct merge_remote_desc {\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179185","messageId":"1320800523-5407-15-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 14/17] commit: teach --gpg-sign option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:02:00Z","receivedAt":"2011-11-09T01:02:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This uses the gpg-interface.[ch] to allow signing the commit, i.e.\n\n    $ git commit --gpg-sign -m foo\n    You need a passphrase to unlock the secret key for\n    user: \"Junio C Hamano <gitster@pobox.com>\"\n    4096-bit RSA key, ID 96AFE6CB, created 2011-10-03 (main key ID 713660A7)\n\n    [master 8457d13] foo\n     1 files changed, 1 insertions(+), 0 deletions(-)\n\nThe lines of GPG detached signature are placed in a new multi-line header\nfield, instead of tucking the signature block at the end of the commit log\nmessage text (similar to how signed tag is done), for multiple reasons:\n\n - The signature won't clutter output from \"git log\" and friends if it is\n   in the extra header. If we place it at the end of the log message, we\n   would need to teach \"git log\" and friends to strip the signature block\n   with an option.\n\n - Teaching new versions of \"git log\" and \"gitk\" to optionally verify and\n   show signatures is cleaner if we structurally know where the signature\n   block is (instead of scanning in the commit log message).\n\n - The signature needs to be stripped upon various commit rewriting\n   operations, e.g. rebase, filter-branch, etc. They all already ignore\n   unknown headers, but if we place signature in the log message, all of\n   these tools (and third-party tools) also need to learn how a signature\n   block would look like.\n\n - When we added the optional encoding header, all the tools (both in tree\n   and third-party) that acts on the raw commit object should have been\n   fixed to ignore headers they do not understand, so it is not like that\n   new header would be more likely to break than extra text in the commit.\n\nA commit made with the above sample sequence would look like this:\n\n    $ git cat-file commit HEAD\n    tree 3cd71d90e3db4136e5260ab54599791c4f883b9d\n    parent b87755351a47b09cb27d6913e6e0e17e6254a4d4\n    author Junio C Hamano <gitster@pobox.com> 1317862251 -0700\n    committer Junio C Hamano <gitster@pobox.com> 1317862251 -0700\n    gpgsig -----BEGIN PGP SIGNATURE-----\n     Version: GnuPG v1.4.10 (GNU/Linux)\n\n     iQIcBAABAgAGBQJOjPtrAAoJELC16IaWr+bL4TMP/RSe2Y/jYnCkds9unO5JEnfG\n     ...\n     =dt98\n     -----END PGP SIGNATURE-----\n\n    foo\n\nbut \"git log\" (unless you ask for it with --pretty=raw) output is not\ncluttered with the signature information.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/commit-tree.c |   24 +++++++++++++++++++++---\n builtin/commit.c      |   11 ++++++++++-\n builtin/merge.c       |   16 ++++++++++++++--\n commit.c              |   48 +++++++++++++++++++++++++++++++++++++++++++++---\n commit.h              |    4 ++--\n notes-cache.c         |    2 +-\n notes-merge.c         |    2 +-\n 7 files changed, 94 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/commit-tree.c b/builtin/commit-tree.c\nindex d083795..a17811f 100644\n--- a/builtin/commit-tree.c\n+++ b/builtin/commit-tree.c\n@@ -8,8 +8,9 @@\n #include \"tree.h\"\n #include \"builtin.h\"\n #include \"utf8.h\"\n+#include \"gpg-interface.h\"\n \n-static const char commit_tree_usage[] = \"git commit-tree <sha1> [(-p <sha1>)...] < changelog\";\n+static const char commit_tree_usage[] = \"git commit-tree [-S<signer>] <sha1> [(-p <sha1>)...] < changelog\";\n \n static void new_parent(struct commit *parent, struct commit_list **parents_p)\n {\n@@ -25,6 +26,14 @@ static void new_parent(struct commit *parent, struct commit_list **parents_p)\n \tcommit_list_insert(parent, parents_p);\n }\n \n+static int commit_tree_config(const char *var, const char *value, void *cb)\n+{\n+\tint status = git_gpg_config(var, value, NULL);\n+\tif (status)\n+\t\treturn status;\n+\treturn git_default_config(var, value, cb);\n+}\n+\n int cmd_commit_tree(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n@@ -32,11 +41,19 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)\n \tunsigned char tree_sha1[20];\n \tunsigned char commit_sha1[20];\n \tstruct strbuf buffer = STRBUF_INIT;\n+\tconst char *sign_commit = NULL;\n \n-\tgit_config(git_default_config, NULL);\n+\tgit_config(commit_tree_config, NULL);\n \n \tif (argc < 2 || !strcmp(argv[1], \"-h\"))\n \t\tusage(commit_tree_usage);\n+\n+\tif (!memcmp(argv[1], \"-S\", 2)) {\n+\t\tsign_commit = argv[1] + 2;\n+\t\targv++;\n+\t\targc--;\n+\t}\n+\n \tif (get_sha1(argv[1], tree_sha1))\n \t\tdie(\"Not a valid object name %s\", argv[1]);\n \n@@ -56,7 +73,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)\n \tif (strbuf_read(&buffer, 0, 0) < 0)\n \t\tdie_errno(\"git commit-tree: failed to read\");\n \n-\tif (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {\n+\tif (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1,\n+\t\t\tNULL, sign_commit)) {\n \t\tstrbuf_release(&buffer);\n \t\treturn 1;\n \t}\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex fca7ea0..7e8a1cf 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -26,6 +26,7 @@\n #include \"unpack-trees.h\"\n #include \"quote.h\"\n #include \"submodule.h\"\n+#include \"gpg-interface.h\"\n \n static const char * const builtin_commit_usage[] = {\n \t\"git commit [options] [--] <filepattern>...\",\n@@ -85,6 +86,8 @@ static int all, edit_flag, also, interactive, patch_interactive, only, amend, si\n static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;\n static int no_post_rewrite, allow_empty_message;\n static char *untracked_files_arg, *force_date, *ignore_submodule_arg;\n+static char *sign_commit;\n+\n /*\n  * The default commit message cleanup mode will remove the lines\n  * beginning with # (shell comments) and leading and trailing\n@@ -144,6 +147,8 @@ static struct option builtin_commit_options[] = {\n \tOPT_BOOLEAN('e', \"edit\", &edit_flag, \"force edit of commit\"),\n \tOPT_STRING(0, \"cleanup\", &cleanup_arg, \"default\", \"how to strip spaces and #comments from message\"),\n \tOPT_BOOLEAN(0, \"status\", &include_status, \"include status in commit message template\"),\n+\t{ OPTION_STRING, 'S', \"gpg-sign\", &sign_commit, \"key id\",\n+\t  \"GPG sign commit\", PARSE_OPT_OPTARG, NULL, (intptr_t) \"\" },\n \t/* end commit message options */\n \n \tOPT_GROUP(\"Commit contents options\"),\n@@ -1324,6 +1329,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1,\n static int git_commit_config(const char *k, const char *v, void *cb)\n {\n \tstruct wt_status *s = cb;\n+\tint status;\n \n \tif (!strcmp(k, \"commit.template\"))\n \t\treturn git_config_pathname(&template_file, k, v);\n@@ -1332,6 +1338,9 @@ static int git_commit_config(const char *k, const char *v, void *cb)\n \t\treturn 0;\n \t}\n \n+\tstatus = git_gpg_config(k, v, NULL);\n+\tif (status)\n+\t\treturn status;\n \treturn git_status_config(k, v, s);\n }\n \n@@ -1488,7 +1497,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\textra = read_commit_extra_headers(current_head);\n \n \tif (commit_tree_extended(sb.buf, active_cache_tree->sha1, parents, sha1,\n-\t\t\t\t author_ident.buf, extra)) {\n+\t\t\t\t author_ident.buf, sign_commit, extra)) {\n \t\trollback_index_files();\n \t\tdie(_(\"failed to write commit object\"));\n \t}\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 3b3e374..b810e2e 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -26,6 +26,7 @@\n #include \"merge-recursive.h\"\n #include \"resolve-undo.h\"\n #include \"remote.h\"\n+#include \"gpg-interface.h\"\n \n #define DEFAULT_TWOHEAD (1<<0)\n #define DEFAULT_OCTOPUS (1<<1)\n@@ -62,6 +63,7 @@ static int allow_rerere_auto;\n static int abort_current_merge;\n static int show_progress = -1;\n static int default_to_upstream;\n+static const char *sign_commit;\n \n static struct strategy all_strategy[] = {\n \t{ \"recursive\",  DEFAULT_TWOHEAD | NO_TRIVIAL },\n@@ -207,6 +209,8 @@ static struct option builtin_merge_options[] = {\n \tOPT_BOOLEAN(0, \"abort\", &abort_current_merge,\n \t\t\"abort the current in-progress merge\"),\n \tOPT_SET_INT(0, \"progress\", &show_progress, \"force progress reporting\", 1),\n+\t{ OPTION_STRING, 'S', \"gpg-sign\", &sign_commit, \"key id\",\n+\t  \"GPG sign commit\", PARSE_OPT_OPTARG, NULL, (intptr_t) \"\" },\n \tOPT_END()\n };\n \n@@ -533,6 +537,8 @@ static void parse_branch_merge_options(char *bmo)\n \n static int git_merge_config(const char *k, const char *v, void *cb)\n {\n+\tint status;\n+\n \tif (branch && !prefixcmp(k, \"branch.\") &&\n \t\t!prefixcmp(k + 7, branch) &&\n \t\t!strcmp(k + 7 + strlen(branch), \".mergeoptions\")) {\n@@ -570,6 +576,10 @@ static int git_merge_config(const char *k, const char *v, void *cb)\n \t\tdefault_to_upstream = git_config_bool(k, v);\n \t\treturn 0;\n \t}\n+\n+\tstatus = git_gpg_config(k, v, NULL);\n+\tif (status)\n+\t\treturn status;\n \treturn git_diff_ui_config(k, v, cb);\n }\n \n@@ -902,7 +912,8 @@ static int merge_trivial(struct commit *head)\n \tparent->next->item = remoteheads->item;\n \tparent->next->next = NULL;\n \tprepare_to_commit();\n-\tcommit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);\n+\tcommit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL,\n+\t\t    sign_commit);\n \tfinish(head, result_commit, \"In-index merge\");\n \tdrop_save();\n \treturn 0;\n@@ -933,7 +944,8 @@ static int finish_automerge(struct commit *head,\n \tstrbuf_addch(&merge_msg, '\\n');\n \tprepare_to_commit();\n \tfree_commit_list(remoteheads);\n-\tcommit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);\n+\tcommit_tree(merge_msg.buf, result_tree, parents, result_commit,\n+\t\t    NULL, sign_commit);\n \tstrbuf_addf(&buf, \"Merge made by the '%s' strategy.\", wt_strategy);\n \tfinish(head, result_commit, buf.buf);\n \tstrbuf_release(&buf);\ndiff --git a/commit.c b/commit.c\nindex 1c05879..a5c53b3 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -6,6 +6,7 @@\n #include \"diff.h\"\n #include \"revision.h\"\n #include \"notes.h\"\n+#include \"gpg-interface.h\"\n \n int save_commit_buffer = 1;\n \n@@ -840,6 +841,42 @@ struct commit_list *reduce_heads(struct commit_list *heads)\n \treturn result;\n }\n \n+static const char gpg_sig_header[] = \"gpgsig\";\n+static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;\n+\n+static int do_sign_commit(struct strbuf *buf, const char *keyid)\n+{\n+\tstruct strbuf sig = STRBUF_INIT;\n+\tint inspos, copypos;\n+\n+\t/* find the end of the header */\n+\tinspos = strstr(buf->buf, \"\\n\\n\") - buf->buf + 1;\n+\n+\tif (!keyid || !*keyid)\n+\t\tkeyid = get_signing_key();\n+\tif (sign_buffer(buf, &sig, keyid)) {\n+\t\tstrbuf_release(&sig);\n+\t\treturn -1;\n+\t}\n+\n+\tfor (copypos = 0; sig.buf[copypos]; ) {\n+\t\tconst char *bol = sig.buf + copypos;\n+\t\tconst char *eol = strchrnul(bol, '\\n');\n+\t\tint len = (eol - bol) + !!*eol;\n+\n+\t\tif (!copypos) {\n+\t\t\tstrbuf_insert(buf, inspos, gpg_sig_header, gpg_sig_header_len);\n+\t\t\tinspos += gpg_sig_header_len;\n+\t\t}\n+\t\tstrbuf_insert(buf, inspos++, \" \", 1);\n+\t\tstrbuf_insert(buf, inspos, bol, len);\n+\t\tinspos += len;\n+\t\tcopypos += len;\n+\t}\n+\tstrbuf_release(&sig);\n+\treturn 0;\n+}\n+\n static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail)\n {\n \tstruct merge_remote_desc *desc;\n@@ -969,13 +1006,14 @@ void free_commit_extra_headers(struct commit_extra_header *extra)\n \n int commit_tree(const char *msg, unsigned char *tree,\n \t\tstruct commit_list *parents, unsigned char *ret,\n-\t\tconst char *author)\n+\t\tconst char *author, const char *sign_commit)\n {\n \tstruct commit_extra_header *extra = NULL, **tail = &extra;\n \tint result;\n \n \tappend_merge_tag_headers(parents, &tail);\n-\tresult = commit_tree_extended(msg, tree, parents, ret, author, extra);\n+\tresult = commit_tree_extended(msg, tree, parents, ret,\n+\t\t\t\t      author, sign_commit, extra);\n \tfree_commit_extra_headers(extra);\n \treturn result;\n }\n@@ -987,7 +1025,8 @@ static const char commit_utf8_warn[] =\n \n int commit_tree_extended(const char *msg, unsigned char *tree,\n \t\t\t struct commit_list *parents, unsigned char *ret,\n-\t\t\t const char *author, struct commit_extra_header *extra)\n+\t\t\t const char *author, const char *sign_commit,\n+\t\t\t struct commit_extra_header *extra)\n {\n \tint result;\n \tint encoding_is_utf8;\n@@ -1037,6 +1076,9 @@ int commit_tree_extended(const char *msg, unsigned char *tree,\n \tif (encoding_is_utf8 && !is_utf8(buffer.buf))\n \t\tfprintf(stderr, commit_utf8_warn);\n \n+\tif (sign_commit && do_sign_commit(&buffer, sign_commit))\n+\t\treturn -1;\n+\n \tresult = write_sha1_file(buffer.buf, buffer.len, commit_type, ret);\n \tstrbuf_release(&buffer);\n \treturn result;\ndiff --git a/commit.h b/commit.h\nindex 3745f12..d2c3e65 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -193,11 +193,11 @@ extern void append_merge_tag_headers(struct commit_list *parents,\n \n extern int commit_tree(const char *msg, unsigned char *tree,\n \t\t       struct commit_list *parents, unsigned char *ret,\n-\t\t       const char *author);\n+\t\t       const char *author, const char *sign_commit);\n \n extern int commit_tree_extended(const char *msg, unsigned char *tree,\n \t\t\t\tstruct commit_list *parents, unsigned char *ret,\n-\t\t\t\tconst char *author,\n+\t\t\t\tconst char *author, const char *sign_commit,\n \t\t\t\tstruct commit_extra_header *);\n \n extern struct commit_extra_header *read_commit_extra_headers(struct commit *);\ndiff --git a/notes-cache.c b/notes-cache.c\nindex 4c8984e..c36a960 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -56,7 +56,7 @@ int notes_cache_write(struct notes_cache *c)\n \n \tif (write_notes_tree(&c->tree, tree_sha1))\n \t\treturn -1;\n-\tif (commit_tree(c->validity, tree_sha1, NULL, commit_sha1, NULL) < 0)\n+\tif (commit_tree(c->validity, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0)\n \t\treturn -1;\n \tif (update_ref(\"update notes cache\", c->tree.ref, commit_sha1, NULL,\n \t\t       0, QUIET_ON_ERR) < 0)\ndiff --git a/notes-merge.c b/notes-merge.c\nindex e9e4199..61cf18e 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -546,7 +546,7 @@ void create_notes_commit(struct notes_tree *t, struct commit_list *parents,\n \t\t/* else: t->ref points to nothing, assume root/orphan commit */\n \t}\n \n-\tif (commit_tree(msg, tree_sha1, parents, result_sha1, NULL))\n+\tif (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))\n \t\tdie(\"Failed to commit notes tree to database\");\n }\n \n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179184","messageId":"1320800523-5407-16-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 15/17] log: --show-signature","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:02:01Z","receivedAt":"2011-11-09T01:02:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This teaches the \"log\" family of commands to pass the GPG signature in the\ncommit objects to \"gpg --verify\" via the verify_signed_buffer() interface\nused to verify signed tag objects. E.g.\n\n    $ git show --show-signature -s HEAD\n\nshows GPG output in the header part of the output.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n commit.c   |   44 ++++++++++++++++++++++++++++++++++++++++++++\n commit.h   |    2 ++\n log-tree.c |   39 +++++++++++++++++++++++++++++++++++++++\n revision.c |    2 ++\n revision.h |    1 +\n 5 files changed, 88 insertions(+), 0 deletions(-)\n\ndiff --git a/commit.c b/commit.c\nindex a5c53b3..7fb1830 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -877,6 +877,50 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)\n \treturn 0;\n }\n \n+int parse_signed_commit(const unsigned char *sha1,\n+\t\t\tstruct strbuf *payload, struct strbuf *signature)\n+{\n+\tunsigned long size;\n+\tenum object_type type;\n+\tchar *buffer = read_sha1_file(sha1, &type, &size);\n+\tint in_signature, saw_signature = -1;\n+\tchar *line, *tail;\n+\n+\tif (!buffer || type != OBJ_COMMIT)\n+\t\tgoto cleanup;\n+\n+\tline = buffer;\n+\ttail = buffer + size;\n+\tin_signature = 0;\n+\tsaw_signature = 0;\n+\twhile (line < tail) {\n+\t\tconst char *sig = NULL;\n+\t\tchar *next = memchr(line, '\\n', tail - line);\n+\n+\t\tnext = next ? next + 1 : tail;\n+\t\tif (in_signature && line[0] == ' ')\n+\t\t\tsig = line + 1;\n+\t\telse if (!prefixcmp(line, gpg_sig_header) &&\n+\t\t\t line[gpg_sig_header_len] == ' ')\n+\t\t\tsig = line + gpg_sig_header_len + 1;\n+\t\tif (sig) {\n+\t\t\tstrbuf_add(signature, sig, next - sig);\n+\t\t\tsaw_signature = 1;\n+\t\t\tin_signature = 1;\n+\t\t} else {\n+\t\t\tif (*line == '\\n')\n+\t\t\t\t/* dump the whole remainder of the buffer */\n+\t\t\t\tnext = tail;\n+\t\t\tstrbuf_add(payload, line, next - line);\n+\t\t\tin_signature = 0;\n+\t\t}\n+\t\tline = next;\n+\t}\n+ cleanup:\n+\tfree(buffer);\n+\treturn saw_signature;\n+}\n+\n static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail)\n {\n \tstruct merge_remote_desc *desc;\ndiff --git a/commit.h b/commit.h\nindex d2c3e65..6107648 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -218,4 +218,6 @@ struct merge_remote_desc {\n  */\n struct commit *get_merge_parent(const char *name);\n \n+extern int parse_signed_commit(const unsigned char *sha1,\n+\t\t\t       struct strbuf *message, struct strbuf *signature);\n #endif /* COMMIT_H */\ndiff --git a/log-tree.c b/log-tree.c\nindex e7694a3..142ba51 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -8,6 +8,7 @@\n #include \"refs.h\"\n #include \"string-list.h\"\n #include \"color.h\"\n+#include \"gpg-interface.h\"\n \n struct decoration name_decoration = { \"object names\" };\n \n@@ -403,6 +404,41 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,\n \t*extra_headers_p = extra_headers;\n }\n \n+static void show_signature(struct rev_info *opt, struct commit *commit)\n+{\n+\tstruct strbuf payload = STRBUF_INIT;\n+\tstruct strbuf signature = STRBUF_INIT;\n+\tstruct strbuf gpg_output = STRBUF_INIT;\n+\tint status;\n+\tconst char *color, *reset, *bol, *eol;\n+\n+\tif (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0)\n+\t\tgoto out;\n+\n+\tstatus = verify_signed_buffer(payload.buf, payload.len,\n+\t\t\t\t      signature.buf, signature.len,\n+\t\t\t\t      &gpg_output);\n+\tif (status && !gpg_output.len)\n+\t\tstrbuf_addstr(&gpg_output, \"No signature\\n\");\n+\n+\tcolor = diff_get_color_opt(&opt->diffopt,\n+\t\t\t\t   status ? DIFF_WHITESPACE : DIFF_FRAGINFO);\n+\treset = diff_get_color_opt(&opt->diffopt, DIFF_RESET);\n+\n+\tbol = gpg_output.buf;\n+\twhile (*bol) {\n+\t\teol = strchrnul(bol, '\\n');\n+\t\tprintf(\"%s%.*s%s%s\", color, (int)(eol - bol), bol, reset,\n+\t\t       *eol ? \"\\n\" : \"\");\n+\t\tbol = (*eol) ? (eol + 1) : eol;\n+\t}\n+\n+ out:\n+\tstrbuf_release(&gpg_output);\n+\tstrbuf_release(&payload);\n+\tstrbuf_release(&signature);\n+}\n+\n void show_log(struct rev_info *opt)\n {\n \tstruct strbuf msgbuf = STRBUF_INIT;\n@@ -514,6 +550,9 @@ void show_log(struct rev_info *opt)\n \t\t}\n \t}\n \n+\tif (opt->show_signature)\n+\t\tshow_signature(opt, commit);\n+\n \tif (!commit->buffer)\n \t\treturn;\n \ndiff --git a/revision.c b/revision.c\nindex 8764dde..064e351 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1469,6 +1469,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\n \t\trevs->notes_opt.use_default_notes = 1;\n+\t} else if (!strcmp(arg, \"--show-signature\")) {\n+\t\trevs->show_signature = 1;\n \t} else if (!prefixcmp(arg, \"--show-notes=\") ||\n \t\t   !prefixcmp(arg, \"--notes=\")) {\n \t\tstruct strbuf buf = STRBUF_INIT;\ndiff --git a/revision.h b/revision.h\nindex 6aa53d1..b8e9223 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -110,6 +110,7 @@ struct rev_info {\n \t\t\tshow_merge:1,\n \t\t\tshow_notes:1,\n \t\t\tshow_notes_given:1,\n+\t\t\tshow_signature:1,\n \t\t\tpretty_given:1,\n \t\t\tabbrev_commit:1,\n \t\t\tabbrev_commit_given:1,\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179188","messageId":"1320800523-5407-17-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 16/17] test \"commit -S\" and \"log --show-signature\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:02:02Z","receivedAt":"2011-11-09T01:02:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Signed-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t7510-signed-commit.sh |   71 ++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 71 insertions(+), 0 deletions(-)\n create mode 100755 t/t7510-signed-commit.sh\n\ndiff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh\nnew file mode 100755\nindex 0000000..30401ce\n--- /dev/null\n+++ b/t/t7510-signed-commit.sh\n@@ -0,0 +1,71 @@\n+#!/bin/sh\n+\n+test_description='signed commit tests'\n+. ./test-lib.sh\n+. \"$TEST_DIRECTORY/lib-gpg.sh\"\n+\n+test_expect_success GPG 'create signed commits' '\n+\techo 1 >file && git add file &&\n+\ttest_tick && git commit -S -m initial &&\n+\tgit tag initial &&\n+\tgit branch side &&\n+\n+\techo 2 >file && test_tick && git commit -a -S -m second &&\n+\tgit tag second &&\n+\n+\tgit checkout side &&\n+\techo 3 >elif && git add elif &&\n+\ttest_tick && git commit -m \"third on side\" &&\n+\n+\tgit checkout master &&\n+\ttest_tick && git merge -S side &&\n+\tgit tag merge &&\n+\n+\techo 4 >file && test_tick && git commit -a -m \"fourth unsigned\" &&\n+\tgit tag fourth-unsigned &&\n+\n+\ttest_tick && git commit --amend -S -m \"fourth signed\"\n+'\n+\n+test_expect_success GPG 'show signatures' '\n+\t(\n+\t\tfor commit in initial second merge master\n+\t\tdo\n+\t\t\tgit show --pretty=short --show-signature $commit >actual &&\n+\t\t\tgrep \"Good signature from\" actual || exit 1\n+\t\t\t! grep \"BAD signature from\" actual || exit 1\n+\t\t\techo $commit OK\n+\t\tdone\n+\t) &&\n+\t(\n+\t\tfor commit in merge^2 fourth-unsigned\n+\t\tdo\n+\t\t\tgit show --pretty=short --show-signature $commit >actual &&\n+\t\t\tgrep \"Good signature from\" actual && exit 1\n+\t\t\t! grep \"BAD signature from\" actual || exit 1\n+\t\t\techo $commit OK\n+\t\tdone\n+\t)\n+'\n+\n+test_expect_success GPG 'detect fudged signature' '\n+\tgit cat-file commit master >raw &&\n+\n+\tsed -e \"s/fourth signed/4th forged/\" raw >forged1 &&\n+\tgit hash-object -w -t commit forged1 >forged1.commit &&\n+\tgit show --pretty=short --show-signature $(cat forged1.commit) >actual1 &&\n+\tgrep \"BAD signature from\" actual1 &&\n+\t! grep \"Good signature from\" actual1\n+'\n+\n+test_expect_success GPG 'detect fudged signature with NUL' '\n+\tgit cat-file commit master >raw &&\n+\tcat raw >forged2 &&\n+\techo Qwik | tr \"Q\" \"\\000\" >>forged2 &&\n+\tgit hash-object -w -t commit forged2 >forged2.commit &&\n+\tgit show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&\n+\tgrep \"BAD signature from\" actual2 &&\n+\t! grep \"Good signature from\" actual2\n+'\n+\n+test_done\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179187","messageId":"1320800523-5407-18-git-send-email-gitster@pobox.com","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 17/17] pretty: %G[?GS] placeholders","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T01:02:03Z","receivedAt":"2011-11-09T01:02:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Add new placeholders related to the GPG signature on signed commits.\n\n - %GG to show the raw verification message from GPG;\n - %G? to show either \"G\" for Good, \"B\" for Bad;\n - %GS to show the name of the signer.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n pretty.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 86 insertions(+), 0 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex f45eb54..392d656 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -9,6 +9,7 @@\n #include \"notes.h\"\n #include \"color.h\"\n #include \"reflog-walk.h\"\n+#include \"gpg-interface.h\"\n \n static char *user_format;\n static struct cmt_fmt_map {\n@@ -640,6 +641,12 @@ struct format_commit_context {\n \tconst struct pretty_print_context *pretty_ctx;\n \tunsigned commit_header_parsed:1;\n \tunsigned commit_message_parsed:1;\n+\tunsigned commit_signature_parsed:1;\n+\tstruct {\n+\t\tchar *gpg_output;\n+\t\tchar good_bad;\n+\t\tchar *signer;\n+\t} signature;\n \tchar *message;\n \tsize_t width, indent1, indent2;\n \n@@ -822,6 +829,59 @@ static void rewrap_message_tail(struct strbuf *sb,\n \tc->indent2 = new_indent2;\n }\n \n+static struct {\n+\tchar result;\n+\tconst char *check;\n+} signature_check[] = {\n+\t{ 'G', \": Good signature from \" },\n+\t{ 'B', \": BAD signature from \" },\n+};\n+\n+static void parse_signature_lines(struct format_commit_context *ctx)\n+{\n+\tconst char *buf = ctx->signature.gpg_output;\n+\tint i;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(signature_check); i++) {\n+\t\tconst char *found = strstr(buf, signature_check[i].check);\n+\t\tconst char *next;\n+\t\tif (!found)\n+\t\t\tcontinue;\n+\t\tctx->signature.good_bad = signature_check[i].result;\n+\t\tfound += strlen(signature_check[i].check);\n+\t\tnext = strchrnul(found, '\\n');\n+\t\tctx->signature.signer = xmemdupz(found, next - found);\n+\t\tbreak;\n+\t}\n+}\n+\n+static void parse_commit_signature(struct format_commit_context *ctx)\n+{\n+\tstruct strbuf payload = STRBUF_INIT;\n+\tstruct strbuf signature = STRBUF_INIT;\n+\tstruct strbuf gpg_output = STRBUF_INIT;\n+\tint status;\n+\n+\tctx->commit_signature_parsed = 1;\n+\n+\tif (parse_signed_commit(ctx->commit->object.sha1,\n+\t\t\t\t&payload, &signature) <= 0)\n+\t\tgoto out;\n+\tstatus = verify_signed_buffer(payload.buf, payload.len,\n+\t\t\t\t      signature.buf, signature.len,\n+\t\t\t\t      &gpg_output);\n+\tif (status && !gpg_output.len)\n+\t\tgoto out;\n+\tctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);\n+\tparse_signature_lines(ctx);\n+\n+ out:\n+\tstrbuf_release(&gpg_output);\n+\tstrbuf_release(&payload);\n+\tstrbuf_release(&signature);\n+}\n+\n+\n static size_t format_commit_one(struct strbuf *sb, const char *placeholder,\n \t\t\t\tvoid *context)\n {\n@@ -974,6 +1034,30 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,\n \t\treturn 0;\n \t}\n \n+\tif (placeholder[0] == 'G') {\n+\t\tif (!c->commit_signature_parsed)\n+\t\t\tparse_commit_signature(c);\n+\t\tswitch (placeholder[1]) {\n+\t\tcase 'G':\n+\t\t\tif (c->signature.gpg_output)\n+\t\t\t\tstrbuf_addstr(sb, c->signature.gpg_output);\n+\t\t\tbreak;\n+\t\tcase '?':\n+\t\t\tswitch (c->signature.good_bad) {\n+\t\t\tcase 'G':\n+\t\t\tcase 'B':\n+\t\t\t\tstrbuf_addch(sb, c->signature.good_bad);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 'S':\n+\t\t\tif (c->signature.signer)\n+\t\t\t\tstrbuf_addstr(sb, c->signature.signer);\n+\t\t\tbreak;\n+\t\t}\n+\t\treturn 2;\n+\t}\n+\n+\n \t/* For the rest we have to parse the commit header. */\n \tif (!c->commit_header_parsed)\n \t\tparse_commit_header(c);\n@@ -1114,6 +1198,8 @@ void format_commit_message(const struct commit *commit,\n \n \tif (context.message != commit->buffer)\n \t\tfree(context.message);\n+\tfree(context.signature.gpg_output);\n+\tfree(context.signature.signer);\n }\n \n static void pp_header(const struct pretty_print_context *pp,\n-- \n1.7.8.rc1.82.g90e080\n"},{"id":"179199","messageId":"robbat2-20111109T103120-856282538Z@orbis-terrarum.net","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v3 00/17] Pulling signed tags","fromName":"Robin H. Johnson","fromEmail":"robbat2@gentoo.org","sentAt":"2011-11-09T10:32:32Z","receivedAt":"2011-11-09T10:32:32Z","isPatch":true,"sender":{"key":"robbat2@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/373898?v=4"},"body":"On Tue, Nov 08, 2011 at 05:01:46PM -0800,  Junio C Hamano wrote:\n> The third iteration of the fourth approach to give more confidence on the\n> authenticity of history, but the third approach of giving GPG signature to\n> individual commits is independently useful and has been rebased on top.\nLooks good at initial visual review, I'll give a deep inspection in a\nday or two (at ApacheCon this week).\n\nThanks for the perseverance!\n\n-- \nRobin Hugh Johnson\nGentoo Linux: Developer, Trustee & Infrastructure Lead\nE-Mail     : robbat2@gentoo.org\nGnuPG FP   : 11AC BA4F 4778 E3F6 E4ED  F38E B27B 944E 3488 4E85\n"},{"id":"179206","messageId":"7v8vnpwhxl.fsf@alter.siamese.dyndns.org","threadId":"28891","inReplyTo":"1320800523-5407-1-git-send-email-gitster@pobox.com","subject":"[PATCH 18/17] request-pull: use the annotated tag contents","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T13:20:54Z","receivedAt":"2011-11-09T13:20:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The integrator tool will start allowing to pull signed or an annotated\ntag, i.e.\n\n    $ git pull $there tags/for-linus\n\nand the description in the tag is used to convey a meaningful message from\nthe lieutenant to the integrator to justify the history being pulled.\n\nInclude the message in the pull request e-mail, as the same information is\nuseful in this context, too. It would encourage the lieutenants to write\nmeaningful messages in their signed tags.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * Goes on top of jc/request-pull-show-head-4 that has been cooking in\n   the 'next' branch.\n\n git-request-pull.sh     |   14 ++++++++++++++\n t/t5150-request-pull.sh |    4 ++++\n 2 files changed, 18 insertions(+), 0 deletions(-)\n\ndiff --git a/git-request-pull.sh b/git-request-pull.sh\nindex 626cf25..c6a5b7a 100755\n--- a/git-request-pull.sh\n+++ b/git-request-pull.sh\n@@ -48,6 +48,8 @@ then\n \tfi\n fi\n \n+tag_name=$(git describe --exact \"$head^0\" 2>/dev/null)\n+\n test -n \"$base\" && test -n \"$url\" || usage\n baserev=$(git rev-parse --verify \"$base\"^0) &&\n headrev=$(git rev-parse --verify \"$head\"^0) || exit\n@@ -82,8 +84,20 @@ then\n \techo \"(from the branch description for $branch local branch)\"\n \techo\n \tgit config \"branch.$branch_name.description\"\n+fi &&\n+\n+if test -n \"$tag_name\"\n+then\n+\tgit cat-file tag \"$tag_name\" |\n+\tsed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p\n+\techo\n+fi &&\n+\n+if test -n \"$branch_name\" || test -n \"$tag_name\"\n+then\n \techo \"----------------------------------------------------------------\"\n fi &&\n+\n git shortlog ^$baserev $headrev &&\n git diff -M --stat --summary $patch $merge_base..$headrev || status=1\n \ndiff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh\nindex 5bd1682..ea6f692 100755\n--- a/t/t5150-request-pull.sh\n+++ b/t/t5150-request-pull.sh\n@@ -86,6 +86,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '\n \ts/$downstream_url_for_sed/URL/g\n \ts/for-upstream/BRANCH/g\n \ts/mnemonic.txt/FILENAME/g\n+\ts/^version [0-9]/VERSION/\n \t/^ FILENAME | *[0-9]* [-+]*\\$/ b diffstat\n \t/^AUTHOR ([0-9]*):\\$/ b shortlog\n \tp\n@@ -201,6 +202,9 @@ test_expect_success 'pull request format' '\n \t  SUBJECT (DATE)\n \n \t----------------------------------------------------------------\n+\tVERSION\n+\n+\t----------------------------------------------------------------\n \tSHORTLOG\n \n \tDIFFSTAT\n-- \n1.7.8.rc1.82.gde0f9\n"},{"id":"179208","messageId":"7v39dxwh2j.fsf_-_@alter.siamese.dyndns.org","threadId":"28891","inReplyTo":"7v8vnpwhxl.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 19/17] merge: do not fast-forward when merging a tag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-09T13:39:32Z","receivedAt":"2011-11-09T13:39:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Merging a signed or an annotated tag is meant to trigger the editor for\nthe integrator to leave a meaningful merge commit log in the history.\nDisallow fast-forwarding the merge in such a case to ensure that a merge\ncommit is always recorded.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/merge.c |    4 +++-\n 1 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 3b3e374..99f1429 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1255,8 +1255,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tstrbuf_reset(&buf);\n \t\tif (merge_remote_util(commit) &&\n \t\t    merge_remote_util(commit)->obj &&\n-\t\t    merge_remote_util(commit)->obj->type == OBJ_TAG)\n+\t\t    merge_remote_util(commit)->obj->type == OBJ_TAG) {\n \t\t\toption_edit = 1;\n+\t\t\tallow_fast_forward = 0;\n+\t\t}\n \t}\n \n \tif (!use_strategies) {\n"}]}