{"thread":{"id":"39965","subject":"[PATCH v4 0/5] pseudorefs","startedAt":"2015-07-29T17:58:03Z","lastAt":"2015-07-30T03:45:50Z","messageCount":8,"participants":["David Turner","Junio C Hamano","Johan Herland"],"isPatch":true,"patchVersion":4,"patchTotal":5},"messages":[{"id":"267078","messageId":"1438192688-8048-1-git-send-email-dturner@twopensource.com","threadId":"39965","inReplyTo":null,"subject":"[PATCH v4 0/5] pseudorefs","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-29T17:58:03Z","receivedAt":"2015-07-29T17:58:03Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"This version removes the old patch 2/6, which changed notes to use\nnormal refs instead of pseudorefs.  We don't actually want to forbid\nper-worktree notes merge; instead, we want to either ensure that they\ndon't conflict, or use a completely different merge mechanism.  So we\nomit this patch.\n\nIn addition, this version fixes a style issue reported by Eric\nSunshine.  It also fixes a lock leak and removes some redundant code;\nEric also suggested both of these changes.\n\nIt also corrects the word \"rebase\" with \"bisect\" in a commit message;\nJunio noticed this one.\n"},{"id":"267080","messageId":"1438192688-8048-2-git-send-email-dturner@twopensource.com","threadId":"39965","inReplyTo":"1438192688-8048-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v4 1/5] refs: Introduce pseudoref and per-worktree ref concepts","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-29T17:58:04Z","receivedAt":"2015-07-29T17:58:04Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Add glossary entries for both concepts.\n\nPseudorefs and per-worktree refs do not yet have special handling,\nbecause the files refs backend already handles them correctly.  Later,\nwe will make the LMDB backend call out to the files backend to handle\nper-worktree refs.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n Documentation/glossary-content.txt | 21 +++++++++++++++++++++\n 1 file changed, 21 insertions(+)\n\ndiff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt\nindex ab18f4b..ff14079 100644\n--- a/Documentation/glossary-content.txt\n+++ b/Documentation/glossary-content.txt\n@@ -411,6 +411,27 @@ exclude;;\n \tcore Git. Porcelains expose more of a <<def_SCM,SCM>>\n \tinterface than the <<def_plumbing,plumbing>>.\n \n+[[def_per_worktree_ref]]per-worktree ref::\n+\tRefs that are per-<<def_worktree,worktree>>, rather than\n+\tglobal.  This is presently only <<def_HEAD,HEAD>>, but might\n+\tlater include other unusual refs.\n+\n+[[def_pseudoref]]pseudoref::\n+\tPseudorefs are a class of files under `$GIT_DIR` which behave\n+\tlike refs for the purposes of rev-parse, but which are treated\n+\tspecially by git.  Psuedorefs both have names that are all-caps,\n+\tand always start with a line consisting of a\n+\t<<def_sha1,SHA-1>> followed by whitespace.  So, HEAD is not a\n+\tpseudoref, because it is sometimes a symbolic ref.  They might\n+\toptionally contain some additional data.  `MERGE_HEAD` and\n+\t`CHERRY_PICK_HEAD` are examples.  Unlike\n+\t<<def_per_worktree_ref,per-worktree refs>>, these files cannot\n+\tbe symbolic refs, and never have reflogs.  They also cannot be\n+\tupdated through the normal ref update machinery.  Instead,\n+\tthey are updated by directly writing to the files.  However,\n+\tthey can be read as if they were refs, so `git rev-parse\n+\tMERGE_HEAD` will work.\n+\n [[def_pull]]pull::\n \tPulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and\n \t<<def_merge,merge>> it.  See also linkgit:git-pull[1].\n-- \n2.0.4.315.gad8727a-twtrsrc\n"},{"id":"267079","messageId":"1438192688-8048-3-git-send-email-dturner@twopensource.com","threadId":"39965","inReplyTo":"1438192688-8048-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v4 2/5] refs: add ref_type function","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-29T17:58:05Z","receivedAt":"2015-07-29T17:58:05Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Add a function ref_type, which categorizes refs as per-worktree,\npseudoref, or normal ref.\n\nLater, we will use this in refs.c to treat pseudorefs specially.\nAlternate ref backends may use it to treat both pseudorefs and\nper-worktree refs differently.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n refs.c | 26 ++++++++++++++++++++++++++\n refs.h |  8 ++++++++\n 2 files changed, 34 insertions(+)\n\ndiff --git a/refs.c b/refs.c\nindex 0b96ece..0f87884 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2848,6 +2848,32 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)\n \treturn 0;\n }\n \n+static int is_per_worktree_ref(const char *refname)\n+{\n+\treturn !strcmp(refname, \"HEAD\");\n+}\n+\n+static int is_pseudoref_syntax(const char *refname)\n+{\n+\tconst char *c;\n+\n+\tfor (c = refname; *c; c++) {\n+\t\tif (!isupper(*c) && *c != '-' && *c != '_')\n+\t\t\treturn 0;\n+\t}\n+\n+\treturn 1;\n+}\n+\n+enum ref_type ref_type(const char *refname)\n+{\n+\tif (is_per_worktree_ref(refname))\n+\t\treturn REF_TYPE_PER_WORKTREE;\n+\tif (is_pseudoref_syntax(refname))\n+\t\treturn REF_TYPE_PSEUDOREF;\n+       return REF_TYPE_NORMAL;\n+}\n+\n int delete_ref(const char *refname, const unsigned char *old_sha1,\n \t       unsigned int flags)\n {\ndiff --git a/refs.h b/refs.h\nindex e4e46c3..dca4fb5 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -445,6 +445,14 @@ extern int parse_hide_refs_config(const char *var, const char *value, const char\n \n extern int ref_is_hidden(const char *);\n \n+enum ref_type {\n+\tREF_TYPE_PER_WORKTREE,\n+\tREF_TYPE_PSEUDOREF,\n+\tREF_TYPE_NORMAL,\n+};\n+\n+enum ref_type ref_type(const char *refname);\n+\n enum expire_reflog_flags {\n \tEXPIRE_REFLOGS_DRY_RUN = 1 << 0,\n \tEXPIRE_REFLOGS_UPDATE_REF = 1 << 1,\n-- \n2.0.4.315.gad8727a-twtrsrc\n"},{"id":"267081","messageId":"1438192688-8048-4-git-send-email-dturner@twopensource.com","threadId":"39965","inReplyTo":"1438192688-8048-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v4 3/5] pseudorefs: create and use pseudoref update and delete functions","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-29T17:58:06Z","receivedAt":"2015-07-29T17:58:06Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Pseudorefs should not be updated through the ref transaction\nAPI, because alternate ref backends still need to store pseudorefs\nin GIT_DIR (instead of wherever they store refs).  Instead,\nchange update_ref and delete_ref to call pseudoref-specific\nfunctions.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n refs.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------\n 1 file changed, 93 insertions(+), 8 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 0f87884..e6fc3fe 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2874,12 +2874,88 @@ enum ref_type ref_type(const char *refname)\n        return REF_TYPE_NORMAL;\n }\n \n+static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,\n+\t\t\t   const unsigned char *old_sha1, struct strbuf *err)\n+{\n+\tconst char *filename;\n+\tint fd;\n+\tstatic struct lock_file lock;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tint ret = -1;\n+\n+\tstrbuf_addf(&buf, \"%s\\n\", sha1_to_hex(sha1));\n+\n+\tfilename = git_path(\"%s\", pseudoref);\n+\tfd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);\n+\tif (fd < 0) {\n+\t\tstrbuf_addf(err, \"Could not open '%s' for writing: %s\",\n+\t\t\t    filename, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\tif (old_sha1) {\n+\t\tunsigned char actual_old_sha1[20];\n+\t\tread_ref(pseudoref, actual_old_sha1);\n+\t\tif (hashcmp(actual_old_sha1, old_sha1)) {\n+\t\t\tstrbuf_addf(err, \"Unexpected sha1 when writing %s\", pseudoref);\n+\t\t\trollback_lock_file(&lock);\n+\t\t\tgoto done;\n+\t\t}\n+\t}\n+\n+\tif (write_in_full(fd, buf.buf, buf.len) != buf.len) {\n+\t\tstrbuf_addf(err, \"Could not write to '%s'\", filename);\n+\t\trollback_lock_file(&lock);\n+\t\tgoto done;\n+\t}\n+\n+\tcommit_lock_file(&lock);\n+\tret = 0;\n+done:\n+\tstrbuf_release(&buf);\n+\treturn ret;\n+}\n+\n+static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)\n+{\n+\tstatic struct lock_file lock;\n+\tconst char *filename;\n+\n+\tfilename = git_path(\"%s\", pseudoref);\n+\n+\tif (old_sha1 && !is_null_sha1(old_sha1)) {\n+\t\tint fd;\n+\t\tunsigned char actual_old_sha1[20];\n+\n+\t\tfd = hold_lock_file_for_update(&lock, filename,\n+\t\t\t\t\t       LOCK_DIE_ON_ERROR);\n+\t\tif (fd < 0)\n+\t\t\tdie_errno(_(\"Could not open '%s' for writing\"), filename);\n+\t\tread_ref(pseudoref, actual_old_sha1);\n+\t\tif (hashcmp(actual_old_sha1, old_sha1)) {\n+\t\t\twarning(\"Unexpected sha1 when deleting %s\", pseudoref);\n+\t\t\trollback_lock_file(&lock);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tunlink(filename);\n+\t\trollback_lock_file(&lock);\n+\t} else {\n+\t\tunlink(filename);\n+\t}\n+\n+\treturn 0;\n+}\n+\n int delete_ref(const char *refname, const unsigned char *old_sha1,\n \t       unsigned int flags)\n {\n \tstruct ref_transaction *transaction;\n \tstruct strbuf err = STRBUF_INIT;\n \n+\tif (ref_type(refname) == REF_TYPE_PSEUDOREF)\n+\t\treturn delete_pseudoref(refname, old_sha1);\n+\n \ttransaction = ref_transaction_begin(&err);\n \tif (!transaction ||\n \t    ref_transaction_delete(transaction, refname, old_sha1,\n@@ -3973,17 +4049,25 @@ int update_ref(const char *msg, const char *refname,\n \t       const unsigned char *new_sha1, const unsigned char *old_sha1,\n \t       unsigned int flags, enum action_on_err onerr)\n {\n-\tstruct ref_transaction *t;\n+\tstruct ref_transaction *t = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n+\tint ret = 0;\n \n-\tt = ref_transaction_begin(&err);\n-\tif (!t ||\n-\t    ref_transaction_update(t, refname, new_sha1, old_sha1,\n-\t\t\t\t   flags, msg, &err) ||\n-\t    ref_transaction_commit(t, &err)) {\n+\tif (ref_type(refname) == REF_TYPE_PSEUDOREF) {\n+\t\tret = write_pseudoref(refname, new_sha1, old_sha1, &err);\n+\t} else {\n+\t\tt = ref_transaction_begin(&err);\n+\t\tif (!t ||\n+\t\t    ref_transaction_update(t, refname, new_sha1, old_sha1,\n+\t\t\t\t\t   flags, msg, &err) ||\n+\t\t    ref_transaction_commit(t, &err)) {\n+\t\t\tret = 1;\n+\t\t\tref_transaction_free(t);\n+\t\t}\n+\t}\n+\tif (ret) {\n \t\tconst char *str = \"update_ref failed for ref '%s': %s\";\n \n-\t\tref_transaction_free(t);\n \t\tswitch (onerr) {\n \t\tcase UPDATE_REFS_MSG_ON_ERR:\n \t\t\terror(str, refname, err.buf);\n@@ -3998,7 +4082,8 @@ int update_ref(const char *msg, const char *refname,\n \t\treturn 1;\n \t}\n \tstrbuf_release(&err);\n-\tref_transaction_free(t);\n+\tif (t)\n+\t\tref_transaction_free(t);\n \treturn 0;\n }\n \n-- \n2.0.4.315.gad8727a-twtrsrc\n"},{"id":"267082","messageId":"1438192688-8048-5-git-send-email-dturner@twopensource.com","threadId":"39965","inReplyTo":"1438192688-8048-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v4 4/5] bisect: use update_ref","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-29T17:58:07Z","receivedAt":"2015-07-29T17:58:07Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Instead of manually writing a pseudoref (in one case) and shelling out\nto git update-ref (in another), use the update_ref function.  This\nis much simpler.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n bisect.c | 37 ++++++++-----------------------------\n 1 file changed, 8 insertions(+), 29 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 857cf59..33ac88d 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -19,7 +19,6 @@ static struct object_id *current_bad_oid;\n \n static const char *argv_checkout[] = {\"checkout\", \"-q\", NULL, \"--\", NULL};\n static const char *argv_show_branch[] = {\"show-branch\", NULL, NULL};\n-static const char *argv_update_ref[] = {\"update-ref\", \"--no-deref\", \"BISECT_HEAD\", NULL, NULL};\n \n static const char *term_bad;\n static const char *term_good;\n@@ -675,34 +674,16 @@ static int is_expected_rev(const struct object_id *oid)\n \treturn res;\n }\n \n-static void mark_expected_rev(char *bisect_rev_hex)\n-{\n-\tint len = strlen(bisect_rev_hex);\n-\tconst char *filename = git_path(\"BISECT_EXPECTED_REV\");\n-\tint fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);\n-\n-\tif (fd < 0)\n-\t\tdie_errno(\"could not create file '%s'\", filename);\n-\n-\tbisect_rev_hex[len] = '\\n';\n-\twrite_or_die(fd, bisect_rev_hex, len + 1);\n-\tbisect_rev_hex[len] = '\\0';\n-\n-\tif (close(fd) < 0)\n-\t\tdie(\"closing file %s: %s\", filename, strerror(errno));\n-}\n-\n-static int bisect_checkout(char *bisect_rev_hex, int no_checkout)\n+static int bisect_checkout(const unsigned char *bisect_rev, int no_checkout)\n {\n+\tchar bisect_rev_hex[GIT_SHA1_HEXSZ + 1];\n \n-\tmark_expected_rev(bisect_rev_hex);\n+\tmemcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);\n+\tupdate_ref(NULL, \"BISECT_EXPECTED_REV\", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);\n \n \targv_checkout[2] = bisect_rev_hex;\n \tif (no_checkout) {\n-\t\targv_update_ref[3] = bisect_rev_hex;\n-\t\tif (run_command_v_opt(argv_update_ref, RUN_GIT_CMD))\n-\t\t\tdie(\"update-ref --no-deref HEAD failed on %s\",\n-\t\t\t    bisect_rev_hex);\n+\t\tupdate_ref(NULL, \"BISECT_HEAD\", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);\n \t} else {\n \t\tint res;\n \t\tres = run_command_v_opt(argv_checkout, RUN_GIT_CMD);\n@@ -804,7 +785,7 @@ static void check_merge_bases(int no_checkout)\n \t\t\thandle_skipped_merge_base(mb);\n \t\t} else {\n \t\t\tprintf(\"Bisecting: a merge base must be tested\\n\");\n-\t\t\texit(bisect_checkout(sha1_to_hex(mb), no_checkout));\n+\t\t\texit(bisect_checkout(mb, no_checkout));\n \t\t}\n \t}\n \n@@ -948,7 +929,6 @@ int bisect_next_all(const char *prefix, int no_checkout)\n \tstruct commit_list *tried;\n \tint reaches = 0, all = 0, nr, steps;\n \tconst unsigned char *bisect_rev;\n-\tchar bisect_rev_hex[GIT_SHA1_HEXSZ + 1];\n \n \tread_bisect_terms(&term_bad, &term_good);\n \tif (read_bisect_refs())\n@@ -986,11 +966,10 @@ int bisect_next_all(const char *prefix, int no_checkout)\n \t}\n \n \tbisect_rev = revs.commits->item->object.sha1;\n-\tmemcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);\n \n \tif (!hashcmp(bisect_rev, current_bad_oid->hash)) {\n \t\texit_if_skipped_commits(tried, current_bad_oid);\n-\t\tprintf(\"%s is the first %s commit\\n\", bisect_rev_hex,\n+\t\tprintf(\"%s is the first %s commit\\n\", sha1_to_hex(bisect_rev),\n \t\t\tterm_bad);\n \t\tshow_diff_tree(prefix, revs.commits->item);\n \t\t/* This means the bisection process succeeded. */\n@@ -1003,7 +982,7 @@ int bisect_next_all(const char *prefix, int no_checkout)\n \t       \"(roughly %d step%s)\\n\", nr, (nr == 1 ? \"\" : \"s\"),\n \t       steps, (steps == 1 ? \"\" : \"s\"));\n \n-\treturn bisect_checkout(bisect_rev_hex, no_checkout);\n+\treturn bisect_checkout(bisect_rev, no_checkout);\n }\n \n static inline int log2i(int n)\n-- \n2.0.4.315.gad8727a-twtrsrc\n"},{"id":"267083","messageId":"1438192688-8048-6-git-send-email-dturner@twopensource.com","threadId":"39965","inReplyTo":"1438192688-8048-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v4 5/5] sequencer: replace write_cherry_pick_head with update_ref","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-29T17:58:08Z","receivedAt":"2015-07-29T17:58:08Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Now update_ref (via write_pseudoref) does almost exactly what\nwrite_cherry_pick_head did, so we can remove write_cherry_pick_head\nand just use update_ref.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n sequencer.c | 23 ++++-------------------\n 1 file changed, 4 insertions(+), 19 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex c4f4b7d..554a704 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -158,23 +158,6 @@ static void free_message(struct commit *commit, struct commit_message *msg)\n \tunuse_commit_buffer(commit, msg->message);\n }\n \n-static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)\n-{\n-\tconst char *filename;\n-\tint fd;\n-\tstruct strbuf buf = STRBUF_INIT;\n-\n-\tstrbuf_addf(&buf, \"%s\\n\", sha1_to_hex(commit->object.sha1));\n-\n-\tfilename = git_path(\"%s\", pseudoref);\n-\tfd = open(filename, O_WRONLY | O_CREAT, 0666);\n-\tif (fd < 0)\n-\t\tdie_errno(_(\"Could not open '%s' for writing\"), filename);\n-\tif (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))\n-\t\tdie_errno(_(\"Could not write to '%s'\"), filename);\n-\tstrbuf_release(&buf);\n-}\n-\n static void print_advice(int show_hint, struct replay_opts *opts)\n {\n \tchar *msg = getenv(\"GIT_CHERRY_PICK_HELP\");\n@@ -607,9 +590,11 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)\n \t * write it at all.\n \t */\n \tif (opts->action == REPLAY_PICK && !opts->no_commit && (res == 0 || res == 1))\n-\t\twrite_cherry_pick_head(commit, \"CHERRY_PICK_HEAD\");\n+\t\tupdate_ref(NULL, \"CHERRY_PICK_HEAD\", commit->object.sha1, NULL,\n+\t\t\t   REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);\n \tif (opts->action == REPLAY_REVERT && ((opts->no_commit && res == 0) || res == 1))\n-\t\twrite_cherry_pick_head(commit, \"REVERT_HEAD\");\n+\t\tupdate_ref(NULL, \"REVERT_HEAD\", commit->object.sha1, NULL,\n+\t\t\t   REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);\n \n \tif (res) {\n \t\terror(opts->action == REPLAY_REVERT\n-- \n2.0.4.315.gad8727a-twtrsrc\n"},{"id":"267104","messageId":"xmqq1tfq8y5w.fsf@gitster.dls.corp.google.com","threadId":"39965","inReplyTo":"1438192688-8048-2-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v4 1/5] refs: Introduce pseudoref and per-worktree ref concepts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-07-29T21:13:47Z","receivedAt":"2015-07-29T21:13:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"David Turner <dturner@twopensource.com> writes:\n\n> Add glossary entries for both concepts.\n>\n> Pseudorefs and per-worktree refs do not yet have special handling,\n> because the files refs backend already handles them correctly.  Later,\n> we will make the LMDB backend call out to the files backend to handle\n> per-worktree refs.\n>\n> Signed-off-by: David Turner <dturner@twopensource.com>\n> ---\n\nWill do s/refs: I/refs: i/; on the subject, and squash the following\nin to make the doc-toolchain happy (they are reported as missing\nlink targets), before pushing the results out on 'pu'.\n\nThanks.\n\n\n Documentation/glossary-content.txt | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt\nindex ff14079..edae9f5 100644\n--- a/Documentation/glossary-content.txt\n+++ b/Documentation/glossary-content.txt\n@@ -412,7 +412,7 @@ exclude;;\n \tinterface than the <<def_plumbing,plumbing>>.\n \n [[def_per_worktree_ref]]per-worktree ref::\n-\tRefs that are per-<<def_worktree,worktree>>, rather than\n+\tRefs that are per-<<def_working_tree,worktree>>, rather than\n \tglobal.  This is presently only <<def_HEAD,HEAD>>, but might\n \tlater include other unusual refs.\n \n@@ -421,7 +421,7 @@ exclude;;\n \tlike refs for the purposes of rev-parse, but which are treated\n \tspecially by git.  Psuedorefs both have names that are all-caps,\n \tand always start with a line consisting of a\n-\t<<def_sha1,SHA-1>> followed by whitespace.  So, HEAD is not a\n+\t<<def_SHA1,SHA-1>> followed by whitespace.  So, HEAD is not a\n \tpseudoref, because it is sometimes a symbolic ref.  They might\n \toptionally contain some additional data.  `MERGE_HEAD` and\n \t`CHERRY_PICK_HEAD` are examples.  Unlike\n"},{"id":"267117","messageId":"CALKQrgeswFaWD1Fb7z=iOpDQq_pW0KTYd+bZB1L7ZaHHoFmAww@mail.gmail.com","threadId":"39965","inReplyTo":"1438192688-8048-2-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v4 1/5] refs: Introduce pseudoref and per-worktree ref concepts","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2015-07-30T03:45:50Z","receivedAt":"2015-07-30T03:45:50Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Wed, Jul 29, 2015 at 7:58 PM, David Turner <dturner@twopensource.com> wrote:\n> +       specially by git.  Psuedorefs both have names that are all-caps,\n\ns/Psuedo/Pseudo/\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"}]}