{"thread":{"id":"1943","subject":"Add \"git-update-ref\" to update the HEAD (or other) ref","startedAt":"2005-09-25T18:43:05Z","lastAt":"2005-09-29T16:07:50Z","messageCount":19,"participants":["Linus Torvalds","Junio C Hamano","Fredrik Kuivinen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"9265","messageId":"Pine.LNX.4.58.0509251134480.3308@g5.osdl.org","threadId":"1943","inReplyTo":null,"subject":"Add \"git-update-ref\" to update the HEAD (or other) ref","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-25T18:43:05Z","receivedAt":"2005-09-25T18:43:05Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nThis is a careful version of the script stuff that currently just\nblindly writes HEAD with a new value.\n\nYou can use\n\n\tgit-update-ref HEAD <newhead>\n\nor\n\n\tgit-update-ref HEAD <newhead> <oldhead>\n\nwhere the latter version verifies that the old value of HEAD matches\noldhead.\n\nIt basically allows a \"ref\" file to be a symbolic pointer to another ref\nfile by starting with the four-byte header sequence of \"ref:\".\n\nMore importantly, it allows the update of a ref file to follow these \nsymbolic pointers, whether they are symlinks or these \"regular file \nsymbolic refs\".\n\nNOTE! It follows _real_ symlinks only if they start with \"refs/\": \notherwise it will just try to read them and update them as a regular file \n(ie it will allow the filesystem to follow them, but will overwrite such a \nsymlink to somewhere else with a regular filename).\n\nIn general, using\n\n\tgit-update-ref HEAD \"$head\"\n\nshould be a _lot_ safer than doing\n\n\techo \"$head\" > \"$GIT_DIR/HEAD\"\n\nboth from a symlink following standpoint _and_ an error checking\nstandpoint.  The \"refs/\" rule for symlinks means that symlinks that point\nto \"outside\" the tree are safe: they'll be followed for reading but not \nfor writing (so we'll never write through a ref symlink to some other \ntree, if you have copied a whole archive by creating a symlink tree).\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\nThis is independent of my previous patch, but in the same basic series. It \nis useful regardless of whether you use the new symbolic refs or not \nbecause of the much improved error checking.\n\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -114,6 +114,7 @@ PROGRAMS = \\\n \tgit-ssh-upload git-tar-tree git-unpack-file \\\n \tgit-unpack-objects git-update-index git-update-server-info \\\n \tgit-upload-pack git-verify-pack git-write-tree \\\n+\tgit-update-ref \\\n \t$(SIMPLE_PROGRAMS)\n \n # Backward compatibility -- to be removed in 0.99.8\ndiff --git a/update-ref.c b/update-ref.c\nnew file mode 100644\n--- /dev/null\n+++ b/update-ref.c\n@@ -0,0 +1,124 @@\n+#include \"cache.h\"\n+#include \"refs.h\"\n+\n+static const char git_update_ref_usage[] = \"git-update-ref <refname> <value> [<oldval>]\";\n+\n+#define MAXDEPTH 5\n+\n+const char *resolve_ref(const char *path, unsigned char *sha1)\n+{\n+\tint depth = MAXDEPTH, len;\n+\tchar buffer[256];\n+\n+\tfor (;;) {\n+\t\tstruct stat st;\n+\t\tchar *buf;\n+\t\tint fd;\n+\n+\t\tif (--depth < 0)\n+\t\t\treturn NULL;\n+\n+\t\t/* Special case: non-existing file */\n+\t\tif (lstat(path, &st) < 0) {\n+\t\t\tif (errno != ENOENT)\n+\t\t\t\treturn NULL;\n+\t\t\tmemset(sha1, 0, 20);\n+\t\t\treturn path;\n+\t\t}\n+\n+\t\t/* Follow \"normalized\" - ie \"refs/..\" symlinks by hand */\n+\t\tif (S_ISLNK(st.st_mode)) {\n+\t\t\tlen = readlink(path, buffer, sizeof(buffer)-1);\n+\t\t\tif (len >= 5 && !memcmp(\"refs/\", buffer, 5)) {\n+\t\t\t\tpath = git_path(\"%.*s\", len, buffer);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/*\n+\t\t * Anything else, just open it and try to use it as\n+\t\t * a ref\n+\t\t */\n+\t\tfd = open(path, O_RDONLY);\n+\t\tif (fd < 0)\n+\t\t\treturn NULL;\n+\t\tlen = read(fd, buffer, sizeof(buffer)-1);\n+\t\tclose(fd);\n+\n+\t\t/*\n+\t\t * Is it a symbolic ref?\n+\t\t */\n+\t\tif (len < 4 || memcmp(\"ref:\", buffer, 4))\n+\t\t\tbreak;\n+\t\tbuf = buffer + 4;\n+\t\tlen -= 4;\n+\t\twhile (len && isspace(*buf))\n+\t\t\tbuf++, len--;\n+\t\twhile (len && isspace(buf[len-1]))\n+\t\t\tbuf[--len] = 0;\n+\t\tpath = git_path(\"%.*s\", len, buf);\n+\t}\n+\tif (len < 40 || get_sha1_hex(buffer, sha1))\n+\t\treturn NULL;\n+\treturn path;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tchar *hex;\n+\tconst char *refname, *value, *oldval, *path, *lockpath;\n+\tunsigned char sha1[20], oldsha1[20], currsha1[20];\n+\tint fd, written;\n+\n+\tsetup_git_directory();\n+\tif (argc < 3 || argc > 4)\n+\t\tusage(git_update_ref_usage);\n+\n+\trefname = argv[1];\n+\tvalue = argv[2];\n+\toldval = argv[3];\n+\tif (get_sha1(value, sha1) < 0)\n+\t\tdie(\"%s: not a valid SHA1\", value);\n+\tmemset(oldsha1, 0, 20);\n+\tif (oldval && get_sha1(oldval, oldsha1) < 0)\n+\t\tdie(\"%s: not a valid old SHA1\", oldval);\n+\n+\tpath = resolve_ref(git_path(\"%s\", refname), currsha1);\n+\tif (!path)\n+\t\tdie(\"No such ref: %s\", refname);\n+\n+\tif (oldval) {\n+\t\tif (memcmp(currsha1, oldsha1, 20))\n+\t\t\tdie(\"Ref %s changed to %s\", refname, sha1_to_hex(currsha1));\n+\t\t/* Nothing to do? */\n+\t\tif (!memcmp(oldsha1, sha1, 20))\n+\t\t\texit(0);\n+\t}\n+\tpath = strdup(path);\n+\tlockpath = mkpath(\"%s.lock\", path);\n+\n+\tfd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);\n+\tif (fd < 0)\n+\t\tdie(\"Unable to create %s\", lockpath);\n+\thex = sha1_to_hex(sha1);\n+\thex[40] = '\\n';\n+\twritten = write(fd, hex, 41);\n+\tclose(fd);\n+\tif (written != 41) {\n+\t\tunlink(lockpath);\n+\t\tdie(\"Unable to write to %s\", lockpath);\n+\t}\n+\t\t\n+\t/*\n+\t * FIXME!\n+\t *\n+\t * We should re-read the old ref here, and re-verify that it\n+\t * matches \"oldsha1\". Otherwise there's a small race.\n+\t */\n+\n+\tif (rename(lockpath, path) < 0) {\n+\t\tunlink(lockpath);\n+\t\tdie(\"Unable to create %s\", path);\n+\t}\n+\treturn 0;\n+}\n"},{"id":"9268","messageId":"Pine.LNX.4.58.0509251153090.3308@g5.osdl.org","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509251134480.3308@g5.osdl.org","subject":"Re: Add \"git-update-ref\" to update the HEAD (or other) ref","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-25T19:05:35Z","receivedAt":"2005-09-25T19:05:35Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 25 Sep 2005, Linus Torvalds wrote:\n>\n> This is a careful version of the script stuff that currently just\n> blindly writes HEAD with a new value.\n\nBtw, in case it wasn't clear from the patch, this only introduced \nmechanism, it didn't actually use it in any script.\n\nBut the point of the exercise is to move towards using git-update-ref in \nplaces like git-fetch.sh, which currently are doing some of it by hand \n(and not handling symlinks etc).\n\nSo you should be able to do something like\n\n\t..\n\told=$(git-rev-parse --verify \"$refname^0\") >& /dev/null\n\tif [ \"$old\" ]; then\n\t\tmb=$(git-merge-base $new $old)\n\t\tif [ \"$mb\" != \"$old\" ]; then\n\t\t\techo \"$new is not a fast-forward of $old\"\n\t\t\t[ \"$force\" ] || exit 1\n\t\t\told=\n\t\tfi\n\tfi\n\tgit-update-ref \"$refname\" $new $old\n\nand the actual update phase will re-verify that \"old\" is still valid (if \nit exists at all).\n\nDoing it by hand works, of course, but for example, if we have two\nsymlinks pointing to the same ref, the current locking in git-fetch.sh is\nbroken - it may lock the _symlink_, but since the other one _also_ points \nto the same thing, there's no locking of the _target_.\n\ngit-update-ref should do things like that right. Famous last words ;)\n\n\t\t\tLinus\n"},{"id":"9284","messageId":"7v64soojub.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509251153090.3308@g5.osdl.org","subject":"Re: Add \"git-update-ref\" to update the HEAD (or other) ref","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-25T22:37:00Z","receivedAt":"2005-09-25T22:37:00Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Btw, in case it wasn't clear from the patch, this only introduced \n> mechanism, it didn't actually use it in any script.\n\nNo I understood it perfectly well thanks -- I am just slow\nbecause I am somewhat sick today.\n"},{"id":"9286","messageId":"7vhdc8n2xb.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509251134480.3308@g5.osdl.org","subject":"Re: Add \"git-update-ref\" to update the HEAD (or other) ref","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-25T23:27:44Z","receivedAt":"2005-09-25T23:27:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> +\t * FIXME!\n\nIs something like the one at the end acceptable?\n\nI'd like to take these patches in two stages (I am not asking\nyou for a resend):\n\n - Drop the emulated symlink part from the update-ref.c; have it\n   graduate to \"master\" branch and use it in existing scripts.\n\n - Take the read_ref() change, along with a patch to re-add the\n   emulated symlink part to update-ref.c (after making its\n   interpretation to match that of read_ref() -- which requires\n   the prefix to be exactly \"ref: \" five bytes); keep it in \"pu\"\n   branch a bit longer.\n\n\n---\ndiff --git a/update-ref.c b/update-ref.c\n--- a/update-ref.c\n+++ b/update-ref.c\n@@ -97,11 +97,13 @@ int main(int argc, char **argv)\n \t}\n \n \t/*\n-\t * FIXME!\n-\t *\n-\t * We should re-read the old ref here, and re-verify that it\n+\t * We re-read the old ref here, and re-verify that it\n \t * matches \"oldsha1\". Otherwise there's a small race.\n \t */\n+\tif (!resolve_ref(git_path(\"%s\", refname), oldsha1))\n+\t\tdie(\"Cannot verify ref: %s\", refname); \n+\tif (memcmp(oldsha1, currsha1, 20))\n+\t\tdie(\"Ref %s changed to %s\", refname, sha1_to_hex(oldsha1));\n \n \tif (rename(lockpath, path) < 0) {\n \t\tunlink(lockpath);\n"},{"id":"9290","messageId":"Pine.LNX.4.58.0509251747290.3308@g5.osdl.org","threadId":"1943","inReplyTo":"7vhdc8n2xb.fsf@assigned-by-dhcp.cox.net","subject":"Re: Add \"git-update-ref\" to update the HEAD (or other) ref","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-26T00:50:33Z","receivedAt":"2005-09-26T00:50:33Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 25 Sep 2005, Junio C Hamano wrote:\n> \n> I'd like to take these patches in two stages (I am not asking\n> you for a resend):\n> \n>  - Drop the emulated symlink part from the update-ref.c; have it\n>    graduate to \"master\" branch and use it in existing scripts.\n\nSure.\n\n>  - Take the read_ref() change, along with a patch to re-add the\n>    emulated symlink part to update-ref.c (after making its\n>    interpretation to match that of read_ref() -- which requires\n>    the prefix to be exactly \"ref: \" five bytes); keep it in \"pu\"\n>    branch a bit longer.\n\nI was actually thinking of maybe entirely replacing \"read_ref()\" with the\nmore powerful \"resolve_ref()\" - moving resolve_ref() into refs.c.\n\nThat way there's only one place that knows about the \"ref:\" thing.\n\nBut yes, forcing the format to be \"ref: \" instead of \"ref:<whitespace>*\" \nsounds fine.\n\n\t\tLinus\n"},{"id":"9291","messageId":"Pine.LNX.4.58.0509251753460.3308@g5.osdl.org","threadId":"1943","inReplyTo":"7vhdc8n2xb.fsf@assigned-by-dhcp.cox.net","subject":"Re: Add \"git-update-ref\" to update the HEAD (or other) ref","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-26T01:07:37Z","receivedAt":"2005-09-26T01:07:37Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 25 Sep 2005, Junio C Hamano wrote:\n> \n> Is something like the one at the end acceptable?\n\nLooking at the patch closer, no, that's incorrect.\n\n\"oldsha\" doesn't necessarily exist, since there has to be some way to \nforce the new one. So if \"oldval\" is NULL, we shouldn't re-verify \nanything.\n\nAlso, independently of that your patch is buggy because calling\n\"resolve_ref()\" again will overwrite the lockpath, since it's re-used by\nthe static buffer in git_path(). That's why the \"strdup()\" is there.\n\nYeah, yeah, static buffers are evil, but they are also simple and \nefficient. \n\nBut something like this (on top of my original one) might work.\n\n\t\tLinus\n----\ndiff --git a/update-ref.c b/update-ref.c\n--- a/update-ref.c\n+++ b/update-ref.c\n@@ -63,6 +63,19 @@ const char *resolve_ref(const char *path\n \treturn path;\n }\n \n+static int re_verify(const char *path, unsigned char *oldsha1, unsigned char *currsha1)\n+{\n+\tchar buf[40];\n+\tint fd = open(path, O_RDONLY), nr;\n+\tif (fd < 0)\n+\t\treturn -1;\n+\tnr = read(fd, buf, 40);\n+\tclose(fd);\n+\tif (nr != 40 || get_sha1_hex(buf, currsha1) < 0)\n+\t\treturn -1;\n+\treturn memcmp(oldsha1, currsha1, 20) ? -1 : 0;\n+}\n+\n int main(int argc, char **argv)\n {\n \tchar *hex;\n@@ -108,14 +121,18 @@ int main(int argc, char **argv)\n \t\tunlink(lockpath);\n \t\tdie(\"Unable to write to %s\", lockpath);\n \t}\n-\t\t\n+\n \t/*\n-\t * FIXME!\n-\t *\n-\t * We should re-read the old ref here, and re-verify that it\n-\t * matches \"oldsha1\". Otherwise there's a small race.\n+\t * Re-read the ref after getting the lock to verify\n \t */\n+\tif (oldval && re_verify(path, oldsha1, currsha1) < 0) {\n+\t\tunlink(lockpath);\n+\t\tdie(\"Ref lock failed\");\n+\t}\n \n+\t/*\n+\t * Finally, replace the old ref with the new one\n+\t */\n \tif (rename(lockpath, path) < 0) {\n \t\tunlink(lockpath);\n \t\tdie(\"Unable to create %s\", path);\n"},{"id":"9292","messageId":"7vd5mwlakj.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509251747290.3308@g5.osdl.org","subject":"Re: Add \"git-update-ref\" to update the HEAD (or other) ref","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-26T04:25:32Z","receivedAt":"2005-09-26T04:25:32Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> I was actually thinking of maybe entirely replacing \"read_ref()\" with the\n> more powerful \"resolve_ref()\" - moving resolve_ref() into refs.c.\n>\n> That way there's only one place that knows about the \"ref:\" thing.\n\nThat would make sense.  But I am feeling a bit too weak tonight\nand am going to crash now.\n"},{"id":"9414","messageId":"7vpsqtykor.fsf_-_@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509251153090.3308@g5.osdl.org","subject":"[PATCH] Use git-update-ref in scripts.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-28T02:45:24Z","receivedAt":"2005-09-28T02:45:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This uses the git-update-ref command in scripts for safer updates.\nAlso places where we used to read HEAD ref by using \"cat\" were fixed\nto use git-rev-parse.  This will matter when we start using symbolic\nreferences.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n * Requesting extra sets of eyeballs from the list for stupid\n   mistakes.\n\n git-applypatch.sh |    5 +++--\n git-commit.sh     |    4 +++-\n git-fetch.sh      |   34 ++++++++++++++++++----------------\n git-merge.sh      |    9 +++++----\n git-octopus.sh    |    2 +-\n git-pull.sh       |    6 +++---\n git-rebase.sh     |    5 +++--\n git-reset.sh      |    2 +-\n git-resolve.sh    |    4 ++--\n 9 files changed, 39 insertions(+), 32 deletions(-)\n\n7bae83d5754a1afb8e64f9de17f1dc34d0022f0a\ndiff --git a/git-applypatch.sh b/git-applypatch.sh\n--- a/git-applypatch.sh\n+++ b/git-applypatch.sh\n@@ -108,9 +108,10 @@ fi\n \n tree=$(git-write-tree) || exit 1\n echo Wrote tree $tree\n-commit=$(git-commit-tree $tree -p $(cat \"$GIT_DIR\"/HEAD) < \"$final\") || exit 1\n+parent=$(git-rev-parse --verify HEAD) &&\n+commit=$(git-commit-tree $tree -p $parent <\"$final\") || exit 1\n echo Committed: $commit\n-echo $commit > \"$GIT_DIR\"/HEAD\n+git-update-ref HEAD $commit $parent || exit\n \n if test -x \"$GIT_DIR\"/hooks/post-applypatch\n then\ndiff --git a/git-commit.sh b/git-commit.sh\n--- a/git-commit.sh\n+++ b/git-commit.sh\n@@ -159,7 +159,9 @@ if [ ! -r \"$GIT_DIR/HEAD\" ]; then\n \t\texit 1\n \tfi\n \tPARENTS=\"\"\n+\tcurrent=\n else\n+\tcurrent=$(git-rev-parse --verify HEAD)\n \tif [ -f \"$GIT_DIR/MERGE_HEAD\" ]; then\n \t\tPARENTS=\"-p HEAD \"`sed -e 's/^/-p /' \"$GIT_DIR/MERGE_HEAD\"`\n \tfi\n@@ -220,7 +222,7 @@ if test -s .cmitchk\n then\n \ttree=$(git-write-tree) &&\n \tcommit=$(cat .cmitmsg | git-commit-tree $tree $PARENTS) &&\n-\techo $commit > \"$GIT_DIR/HEAD\" &&\n+\tgit-update-ref HEAD $commit $current &&\n \trm -f -- \"$GIT_DIR/MERGE_HEAD\"\n else\n \techo >&2 \"* no commit message?  aborting commit.\"\ndiff --git a/git-fetch.sh b/git-fetch.sh\n--- a/git-fetch.sh\n+++ b/git-fetch.sh\n@@ -105,14 +105,16 @@ fast_forward_local () {\n \telse\n \t\techo >&2 \"* $1: storing $3\"\n \tfi\n-\techo \"$2\" >\"$GIT_DIR/$1\" ;;\n+\tgit-update-ref \"$1\" \"$2\" \n+\t;;\n \n     refs/heads/*)\n-\t# NEEDSWORK: use the same cmpxchg protocol here.\n-\techo \"$2\" >\"$GIT_DIR/$1.lock\"\n-\tif test -f \"$GIT_DIR/$1\"\n+\t# $1 is the ref being updated.\n+\t# $2 is the new value for the ref.\n+\tlocal=$(git-rev-parse --verify \"$1^0\" 2>/dev/null)\n+\tif test \"$local\"\n \tthen\n-\t    local=$(git-rev-parse --verify \"$1^0\") &&\n+\t    # Require fast-forward.\n \t    mb=$(git-merge-base \"$local\" \"$2\") &&\n \t    case \"$2,$mb\" in\n \t    $local,*)\n@@ -120,34 +122,34 @@ fast_forward_local () {\n \t\t;;\n \t    *,$local)\n \t\techo >&2 \"* $1: fast forward to $3\"\n+\t\tgit-update-ref \"$1\" \"$2\" \"$local\"\n \t\t;;\n \t    *)\n \t\tfalse\n \t\t;;\n \t    esac || {\n \t\techo >&2 \"* $1: does not fast forward to $3;\"\n-\t\tcase \"$force,$single_force\" in\n-\t\tt,* | *,t)\n+\t\tcase \",$force,$single_force,\" in\n+\t\t*,t,*)\n \t\t\techo >&2 \"  forcing update.\"\n+\t\t\tgit-update-ref \"$1\" \"$2\" \"$local\"\n \t\t\t;;\n \t\t*)\n-\t\t\tmv \"$GIT_DIR/$1.lock\" \"$GIT_DIR/$1.remote\"\n-\t\t\techo >&2 \"  leaving it in '$1.remote'\"\n+\t\t\techo >&2 \"  not updating.\"\n \t\t\t;;\n \t\tesac\n \t    }\n \telse\n-\t\techo >&2 \"* $1: storing $3\"\n+\t    echo >&2 \"* $1: storing $3\"\n+\t    git-update-ref \"$1\" \"$2\"\n \tfi\n-\ttest -f \"$GIT_DIR/$1.lock\" &&\n-\t    mv \"$GIT_DIR/$1.lock\" \"$GIT_DIR/$1\"\n \t;;\n     esac\n }\n \n case \"$update_head_ok\" in\n '')\n-\torig_head=$(cat \"$GIT_DIR/HEAD\" 2>/dev/null)\n+\torig_head=$(git-rev-parse --verify HEAD 2>/dev/null)\n \t;;\n esac\n \n@@ -184,7 +186,7 @@ do\n     rsync://*)\n \tTMP_HEAD=\"$GIT_DIR/TMP_HEAD\"\n \trsync -L -q \"$remote/$remote_name\" \"$TMP_HEAD\" || exit 1\n-\thead=$(git-rev-parse TMP_HEAD)\n+\thead=$(git-rev-parse --verify TMP_HEAD)\n \trm -f \"$TMP_HEAD\"\n \ttest \"$rsync_slurped_objects\" || {\n \t    rsync -av --ignore-existing --exclude info \\\n@@ -261,10 +263,10 @@ case \",$update_head_ok,$orig_head,\" in\n *,, | t,* )\n \t;;\n *)\n-\tcurr_head=$(cat \"$GIT_DIR/HEAD\" 2>/dev/null)\n+\tcurr_head=$(git-rev-parse --verify HEAD 2>/dev/null)\n \tif test \"$curr_head\" != \"$orig_head\"\n \tthen\n-\t\techo \"$orig_head\" >$GIT_DIR/HEAD\n+\t    \tgit-update-ref HEAD \"$orig_head\"\n \t\tdie \"Cannot fetch into the current branch.\"\n \tfi\n \t;;\ndiff --git a/git-merge.sh b/git-merge.sh\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -114,8 +114,9 @@ case \"$#,$common\" in\n \t# Again the most common case of merging one remote.\n \techo \"Updating from $head to $1.\"\n \tgit-update-index --refresh 2>/dev/null\n-\tgit-read-tree -u -m $head \"$1\" || exit 1\n-\tgit-rev-parse --verify \"$1^0\" > \"$GIT_DIR/HEAD\"\n+\tgit-read-tree -u -m $head \"$1\" &&\n+\tnew_head=$(git-rev-parse --verify \"$1^0\") &&\n+\tgit-update-ref HEAD \"$new_head\" \"$head\" || exit 1\n \tsummary \"$1\"\n \tdropsave\n \texit 0\n@@ -218,9 +219,9 @@ then\n     do\n         parents=\"$parents -p $remote\"\n     done\n-    result_commit=$(echo \"$merge_msg\" | git-commit-tree $result_tree $parents)\n+    result_commit=$(echo \"$merge_msg\" | git-commit-tree $result_tree $parents) || exit\n     echo \"Committed merge $result_commit, made by $wt_strategy.\"\n-    echo $result_commit >\"$GIT_DIR/HEAD\"\n+    git-update-ref HEAD $result_commit $head\n     summary $result_commit\n     dropsave\n     exit 0\ndiff --git a/git-octopus.sh b/git-octopus.sh\n--- a/git-octopus.sh\n+++ b/git-octopus.sh\n@@ -86,5 +86,5 @@ esac\n result_commit=$(git-fmt-merge-msg <\"$GIT_DIR/FETCH_HEAD\" |\n \t\tgit-commit-tree $MRT $PARENT)\n echo \"Committed merge $result_commit\"\n-echo $result_commit >\"$GIT_DIR\"/HEAD\n+git-update-ref HEAD $result_commit $head\n git-diff-tree -p $head $result_commit | git-apply --stat\ndiff --git a/git-pull.sh b/git-pull.sh\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -6,10 +6,10 @@\n \n . git-sh-setup || die \"Not a git archive\"\n \n-orig_head=$(cat \"$GIT_DIR/HEAD\") || die \"Pulling into a black hole?\"\n+orig_head=$(git-rev-parse --verify HEAD) || die \"Pulling into a black hole?\"\n git-fetch --update-head-ok \"$@\" || exit 1\n \n-curr_head=$(cat \"$GIT_DIR/HEAD\")\n+curr_head=$(git-rev-parse --verify HEAD)\n if test \"$curr_head\" != \"$orig_head\"\n then\n \t# The fetch involved updating the current branch.\n@@ -38,4 +38,4 @@ case \"$merge_head\" in\n esac\n \n merge_name=$(git-fmt-merge-msg <\"$GIT_DIR/FETCH_HEAD\")\n-git-resolve \"$(cat \"$GIT_DIR\"/HEAD)\" $merge_head \"$merge_name\"\n+git-resolve \"$curr_head\" $merge_head \"$merge_name\"\ndiff --git a/git-rebase.sh b/git-rebase.sh\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -33,7 +33,8 @@ test \"$different1$different2\" = \"\" ||\n die \"Your working tree does not match $ours_symbolic.\"\n \n git-read-tree -m -u $ours $upstream &&\n-git-rev-parse --verify \"$upstream^0\" >\"$GIT_DIR/HEAD\" || exit\n+new_head=$(git-rev-parse --verify \"$upstream^0\") &&\n+git-update-ref HEAD \"$new_head\" || exit\n \n tmp=.rebase-tmp$$\n fail=$tmp-fail\n@@ -50,7 +51,7 @@ do\n \t\tcontinue ;;\n \tesac\n \techo >&2 \"* Applying: $msg\"\n-\tS=`cat \"$GIT_DIR/HEAD\"` &&\n+\tS=$(git-rev-parse --verify HEAD) &&\n \tgit-cherry-pick --replay $commit || {\n \t\techo >&2 \"* Not applying the patch and continuing.\"\n \t\techo $commit >>$fail\ndiff --git a/git-reset.sh b/git-reset.sh\n--- a/git-reset.sh\n+++ b/git-reset.sh\n@@ -60,7 +60,7 @@ then\n else\n \trm -f \"$GIT_DIR/ORIG_HEAD\"\n fi\n-echo \"$rev\" >\"$GIT_DIR/HEAD\"\n+git-update-ref HEAD \"$rev\"\n \n case \"$reset_type\" in\n --hard )\ndiff --git a/git-resolve.sh b/git-resolve.sh\n--- a/git-resolve.sh\n+++ b/git-resolve.sh\n@@ -45,7 +45,7 @@ case \"$common\" in\n \"$head\")\n \techo \"Updating from $head to $merge.\"\n \tgit-read-tree -u -m $head $merge || exit 1\n-\techo $merge > \"$GIT_DIR\"/HEAD\n+\tgit-update-ref HEAD \"$merge\"\n \tgit-diff-tree -p $head $merge | git-apply --stat\n \tdropheads\n \texit 0\n@@ -99,6 +99,6 @@ if [ $? -ne 0 ]; then\n fi\n result_commit=$(echo \"$merge_msg\" | git-commit-tree $result_tree -p $head -p $merge)\n echo \"Committed merge $result_commit\"\n-echo $result_commit > \"$GIT_DIR\"/HEAD\n+git-update-ref HEAD \"$result_commit\"\n git-diff-tree -p $head $result_commit | git-apply --stat\n dropheads\n"},{"id":"9425","messageId":"Pine.LNX.4.58.0509280819000.3308@g5.osdl.org","threadId":"1943","inReplyTo":"7vpsqtykor.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-28T15:21:40Z","receivedAt":"2005-09-28T15:21:40Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 27 Sep 2005, Junio C Hamano wrote:\n>\n> This uses the git-update-ref command in scripts for safer updates.\n\nLooks good.\n\ngit-resolve might want to verify the old head. On the other hand, it looks \nlike it's being phased out, so maybe nobody cares?\n\n\t\tLinus\n"},{"id":"9431","messageId":"7vek79w2ps.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509280819000.3308@g5.osdl.org","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-28T16:56:31Z","receivedAt":"2005-09-28T16:56:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> git-resolve might want to verify the old head. On the other hand, it looks \n> like it's being phased out, so maybe nobody cares?\n\nIt was my mistake -- git-merge does it, and I should do the\nsame in git-resolve.  Thanks for pointing it out.\n\nHave you had a chance to look at the git-merge change to remove\nthe stupid clean-tree requirements?  I have been planning to\ninflict the 'use git-merge instead of git-resolve' change on you\nsometime soonish (like today ;-).  Having said that, I myself\nwould vote against phasing out 'git-resolve' -- being able to\nsay 'git resolve master hold fast' to fast forward the master\nhead to topic branch head of 'hold' (my topic branches are often\nrebased to allow this) is quite useful.\n\nI have one unrelated request.\n\nCould I have a copy of .git/{branches,remotes,refs}/* from the\nprimary repository you do your kernel work please?\n"},{"id":"9432","messageId":"Pine.LNX.4.58.0509281007200.3308@g5.osdl.org","threadId":"1943","inReplyTo":"7vek79w2ps.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-28T17:13:17Z","receivedAt":"2005-09-28T17:13:17Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 28 Sep 2005, Junio C Hamano wrote:\n> \n> Have you had a chance to look at the git-merge change to remove\n> the stupid clean-tree requirements?  I have been planning to\n> inflict the 'use git-merge instead of git-resolve' change on you\n> sometime soonish (like today ;-).\n\nI don't like doing the diff before-hand, but it looked like the default \nwas to try just one strategy, and avoid the diff in that case.\n\nActually, my preference would be to have a unconditional simple case\nfirst. If there's only one possible base, and the trivial merge succeeds\n(ie no three-way merges needed at all, just a single git-read-tree), do\nthat part unconditionally.\n\nThat actually matches 90% of all merges I do, and I'd be much happier with \ngit-merge if it did that first and if it then does something more complex \n(including diffs etc) afterwards, I'm much less likely to worry.\n\n> Could I have a copy of .git/{branches,remotes,refs}/* from the\n> primary repository you do your kernel work please?\n\nHeh. My kernel has none of that. Well, it obviously has refs, but even \nthere it literally has just one head: \"master\". The rest are the standard \ntags you see in public.\n\nSo if you clone the public kernel,. you'll actually have a superset of \nwhat I have, since you'll have the \"origin\" thing ;)\n\n\t\t\tLinus\n"},{"id":"9435","messageId":"7v3bnpt81e.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509281007200.3308@g5.osdl.org","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-28T17:29:49Z","receivedAt":"2005-09-28T17:29:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Heh. My kernel has none of that. Well, it obviously has refs, but even \n> there it literally has just one head: \"master\". The rest are the standard \n> tags you see in public.\n\nI was wondering the URL shorthand you mentioned is being used in\npractice.  In theory, you do not \"have to write out in full\"\nanymore ;-).\n\nMessage-ID: <Pine.LNX.4.58.0507151529590.19183@g5.osdl.org>\nFrom: Linus Torvalds <torvalds@osdl.org>\nDate: Fri, 15 Jul 2005 15:42:42 -0700 (PDT)\n\nAnd it's not necessarily just the branch handling, but more of a generic\nshorthand: I'd love to be able to mix something like\n\n\tgit pull jgarzik/misc-2.6 upstream\n\nand \"jgarzik\" would be expanded (through something like .git/branches) to \n\"master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/\"), resulting in the \n_full_ path being expanded to\n\n\tmaster.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6 upstream\n\nwhich I have to write out in full (or, more commonly, cut-and-paste) right\nnow.\n"},{"id":"9437","messageId":"Pine.LNX.4.58.0509281106370.3308@g5.osdl.org","threadId":"1943","inReplyTo":"7v3bnpt81e.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-28T18:14:31Z","receivedAt":"2005-09-28T18:14:31Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 28 Sep 2005, Junio C Hamano wrote:\n>\n> I was wondering the URL shorthand you mentioned is being used in\n> practice.  In theory, you do not \"have to write out in full\"\n> anymore ;-).\n\nAlmost always, I end up cut-and-pasting the thing from an email.\n\nIn many ways, the most irritating part for me about that is that an email \nthat wants to give a publically accessible part has to be something like\n\n   \"Please pull from\n\n      rsync://rsync.kernel.org/path\n\n    to get the xyz updates\"\n\nand then I cut-and-paste it but have to delete the \"rsync://\", and replace \nthe \"rsync.kernel.org/\" with \"master.kernel.org:/\". \n\nSad.\n\nSo I've actually considered a totally Linus-only hack that does that \nautomatically, ie something like this untested patch.. (same goes for http \ntoo, for that matter)\n\n\t\tLinus\n\ndiff --git a/git-parse-remote.sh b/git-parse-remote.sh\n--- a/git-parse-remote.sh\n+++ b/git-parse-remote.sh\n@@ -32,7 +32,7 @@ get_remote_url () {\n \tdata_source=$(get_data_source \"$1\")\n \tcase \"$data_source\" in\n \t'')\n-\t\techo \"$1\" ;;\n+\t\techo \"$1\" | sed 's/rsync:[^/]*kernel.org/master.kernel.org:/ ;;\n \tremotes)\n \t\tsed -ne '/^URL: */{\n \t\t\ts///p\n"},{"id":"9438","messageId":"7vk6h1rr9l.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509281007200.3308@g5.osdl.org","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-28T18:17:26Z","receivedAt":"2005-09-28T18:17:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Wed, 28 Sep 2005, Junio C Hamano wrote:\n>> \n> I don't like doing the diff before-hand, but it looked like the default \n> was to try just one strategy, and avoid the diff in that case.\n\nBy 'diff before-hand' I take it to mean the savestate for later\nrounds to keep the pre-merge state.  You are correct that it is\nnot done in a single strategy case, and 'git pull' by default\nwould use only one of Daniel's git-merge-resolve or in the\nmulti-remote case git-merge-octopus, depending on the number of\nheads being merged.  BTW, I decided not to use diff, just in\ncase somebody has binary blob we cannot reproduce with diff and\npatch.\n\n> Actually, my preference would be to have a unconditional simple case\n> first. If there's only one possible base, and the trivial merge succeeds\n> (ie no three-way merges needed at all, just a single git-read-tree), do\n> that part unconditionally.\n>\n> That actually matches 90% of all merges I do, and I'd be much happier with \n> git-merge if it did that first and if it then does something more complex \n> (including diffs etc) afterwards, I'm much less likely to worry.\n\nHmph.  That sort of makes sense but to make the unconditional\nsimple case really fast it should use read-tree -m -u which\n_would_ smudge if things do not go well, which implies you need\nsavestate before that which would make it slower -- wouldn't it?\n\nI think using Daniel's git-merge-resolve and nothing else by\ndefault would be equivalent of having that unconditional simple\ncase upfront.\n"},{"id":"9439","messageId":"7vfyrprqr6.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"Pine.LNX.4.58.0509281106370.3308@g5.osdl.org","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-28T18:28:29Z","receivedAt":"2005-09-28T18:28:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> In many ways, the most irritating part for me about that is that an email \n> that wants to give a publically accessible part has to be something like\n>\n>    \"Please pull from\n>\n>       rsync://rsync.kernel.org/path\n>\n>     to get the xyz updates\"\n>\n> and then I cut-and-paste it but have to delete the \"rsync://\", and replace \n> the \"rsync.kernel.org/\" with \"master.kernel.org:/\". \n>\n> Sad.\n\nHopefully that would be rectified when git-daemon goes on-line,\nnow I've merged updates from HPA ;-).\n"},{"id":"9440","messageId":"7vek79q8jj.fsf@assigned-by-dhcp.cox.net","threadId":"1943","inReplyTo":"7vk6h1rr9l.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-28T19:47:12Z","receivedAt":"2005-09-28T19:47:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Linus Torvalds <torvalds@osdl.org> writes:\n>\n>> On Wed, 28 Sep 2005, Junio C Hamano wrote:\n>>> \n>> I don't like doing the diff before-hand, but it looked like the default \n>> was to try just one strategy, and avoid the diff in that case.\n>\n> By 'diff before-hand' I take it to mean the savestate for later\n> rounds to keep the pre-merge state.  You are correct that it is\n> not done in a single strategy case, and 'git pull' by default\n> would use only one of Daniel's git-merge-resolve or in the\n> multi-remote case git-merge-octopus, depending on the number of\n> heads being merged.  BTW, I decided not to use diff, just in\n> case somebody has binary blob we cannot reproduce with diff and\n> patch.\n\nI see two more diffs that turns out to be problematic in\ngit-merge.sh code.\n\n (1) As a safety measure I have a check to make sure the index\n     is in sync with $head.  This visibly hurts; on my slow disk\n     and CPU with a couple of locally modified paths in the\n     working tree, this check takes about a second in the kernel\n     tree with hot cache.\n\n     git-merge-resolve uses \"git-read-tree -u -m O A B\" form, so\n     this is totally unnecessary.  I am not so sure about\n     Fredrik's git-merge-recursive (I haven't looked at it for a\n     while).\n\n (2) savestate uses \"git diff $head\" to find out the list of\n     paths that have local modifications, but the current code\n     calls it after the check described above, so \"git-ls-files\n     -m\" is enough.  On a kernel tree with hot cache and index\n     in sync with HEAD, \"git-ls-files -m\" is about 3-4 times as\n     fast with a couple of locally modified files.\n\nKeeping (1) and using 'git-ls-files -m' in (2) is optimizing for\na wrong path.  On the other hand, (1) is a safety measure, and\nif it is kept (2) becomes a quite cheap operation.\n\nI am inclined to just remove the check in (1), and make it the\nresponsibility of merge strategies to make sure it does not\ncommit unrelated changes.\n\nComments?\n"},{"id":"9442","messageId":"20050928211926.GA3378@c165.ib.student.liu.se","threadId":"1943","inReplyTo":"7vek79q8jj.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Fredrik Kuivinen","fromEmail":"freku045@student.liu.se","sentAt":"2005-09-28T21:19:26Z","receivedAt":"2005-09-28T21:19:26Z","isPatch":true,"sender":{"key":"frekui@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13770967?v=4"},"body":"On Wed, Sep 28, 2005 at 12:47:12PM -0700, Junio C Hamano wrote:\n> Junio C Hamano <junkio@cox.net> writes:\n> \n> > Linus Torvalds <torvalds@osdl.org> writes:\n> >\n> >> On Wed, 28 Sep 2005, Junio C Hamano wrote:\n> >>> \n> >> I don't like doing the diff before-hand, but it looked like the default \n> >> was to try just one strategy, and avoid the diff in that case.\n> >\n> > By 'diff before-hand' I take it to mean the savestate for later\n> > rounds to keep the pre-merge state.  You are correct that it is\n> > not done in a single strategy case, and 'git pull' by default\n> > would use only one of Daniel's git-merge-resolve or in the\n> > multi-remote case git-merge-octopus, depending on the number of\n> > heads being merged.  BTW, I decided not to use diff, just in\n> > case somebody has binary blob we cannot reproduce with diff and\n> > patch.\n> \n> I see two more diffs that turns out to be problematic in\n> git-merge.sh code.\n> \n>  (1) As a safety measure I have a check to make sure the index\n>      is in sync with $head.  This visibly hurts; on my slow disk\n>      and CPU with a couple of locally modified paths in the\n>      working tree, this check takes about a second in the kernel\n>      tree with hot cache.\n> \n>      git-merge-resolve uses \"git-read-tree -u -m O A B\" form, so\n>      this is totally unnecessary.  I am not so sure about\n>      Fredrik's git-merge-recursive (I haven't looked at it for a\n>      while).\n> \n\ngit-merge-recursive also uses 'git-read-tree -u -m O A B' so it\nshouldn't have any problems with this change.\n\n\n>  (2) savestate uses \"git diff $head\" to find out the list of\n>      paths that have local modifications, but the current code\n>      calls it after the check described above, so \"git-ls-files\n>      -m\" is enough.  On a kernel tree with hot cache and index\n>      in sync with HEAD, \"git-ls-files -m\" is about 3-4 times as\n>      fast with a couple of locally modified files.\n> \n> Keeping (1) and using 'git-ls-files -m' in (2) is optimizing for\n> a wrong path.  On the other hand, (1) is a safety measure, and\n> if it is kept (2) becomes a quite cheap operation.\n> \n> I am inclined to just remove the check in (1), and make it the\n> responsibility of merge strategies to make sure it does not\n> commit unrelated changes.\n> \n> Comments?\n> \n\nLooks good to me.\n\n- Fredrik\n"},{"id":"9479","messageId":"Pine.LNX.4.58.0509290801230.3308@g5.osdl.org","threadId":"1943","inReplyTo":"7vk6h1rr9l.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-29T15:16:12Z","receivedAt":"2005-09-29T15:16:12Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 28 Sep 2005, Junio C Hamano wrote:\n> \n> Hmph.  That sort of makes sense but to make the unconditional\n> simple case really fast it should use read-tree -m -u which\n> _would_ smudge if things do not go well, which implies you need\n> savestate before that which would make it slower -- wouldn't it?\n\nYeah, we'd have to do something like this.. (untested, surprise, surprise)\n\nNOTE! Even if you don't take this, I noticed what looks like a missing \n\"continue\" in the \"--head\" case. That just can't work without it, afaik. \n\nNot that I know what \"--head\" is supposed to do.. \n\n\t\tLinus\n---\ndiff --git a/read-tree.c b/read-tree.c\n--- a/read-tree.c\n+++ b/read-tree.c\n@@ -13,6 +13,8 @@\n static int merge = 0;\n static int update = 0;\n static int index_only = 0;\n+static int nontrivial_merge = 0;\n+static int trivial_merges_only = 0;\n \n static int head_idx = -1;\n static int merge_size = 0;\n@@ -275,6 +277,9 @@ static int unpack_trees(merge_fn_t fn)\n \tif (unpack_trees_rec(posns, len, \"\", fn, &indpos))\n \t\treturn -1;\n \n+\tif (trivial_merges_only && nontrivial_merge)\n+\t\tdie(\"Merge requires file-level merging\");\n+\n \tcheck_updates(active_cache, active_nr);\n \treturn 0;\n }\n@@ -460,6 +465,8 @@ static int threeway_merge(struct cache_e\n \t\tverify_uptodate(index);\n \t}\n \n+\tnontrivial_merge = 1;\n+\n \t/* #2, #3, #4, #6, #7, #9, #11. */\n \tcount = 0;\n \tif (!head_match || !remote_match) {\n@@ -629,9 +636,15 @@ int main(int argc, char **argv)\n \t\t\tcontinue;\n \t\t}\n \n+\t\tif (!strcmp(arg, \"--trivial\")) {\n+\t\t\ttrivial_merges_only = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (!strcmp(arg, \"--head\")) {\n \t\t\thead_idx = stage - 1;\n \t\t\tfn = threeway_merge;\n+\t\t\tcontinue;\n \t\t}\n \n \t\t/* \"-m\" stands for \"merge\", meaning we start in stage 1 */\n"},{"id":"9482","messageId":"Pine.LNX.4.58.0509290907040.3308@g5.osdl.org","threadId":"1943","inReplyTo":"7vfyrprqr6.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Use git-update-ref in scripts.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-29T16:07:50Z","receivedAt":"2005-09-29T16:07:50Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 28 Sep 2005, Junio C Hamano wrote:\n> \n> Hopefully that would be rectified when git-daemon goes on-line,\n> now I've merged updates from HPA ;-).\n\nYes, the git-daemon will help. However, it won't fix the lag from \nmaster.kernel.org to the slaves, so I'd probably still have to re-write \nthings if there are mirror delays..\n\n\t\tLinus\n"}]}