{"thread":{"id":"6193","subject":"[PATCH] Detached HEAD (experimental)","startedAt":"2007-01-02T07:45:08Z","lastAt":"2007-01-11T09:45:26Z","messageCount":68,"participants":["Junio C Hamano","Edgar Toernig","Carl Worth","Jakub Narebski","Lars Hjemli","Shawn O. Pearce","Jeff King","J. Bruce Fields","Alan Chandler","Luben Tuikov","Linus Torvalds","Nicolas Pitre","Andy Parkins","Andreas Ericsson","Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"30659","messageId":"7vac11yirf.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":null,"subject":"[PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-02T07:45:08Z","receivedAt":"2007-01-02T07:45:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This allows \"git checkout -d v1.4.3\" to detach the HEAD from any\nbranch but point directly at the named commit.  After this, \"git\nbranch\" starts reporting that you are not on any branch.  You\ncan merge into \"current branch\" although there is not even such\na thing.\n\nYou can go back the normal state by switching to an existing\nbranch, say, \"git checkout master\" for example.  Another way to\nget out of this is \"git checkout -b newbranch\".\n\nThis is still experimental.  While I think it makes sense to\nallow commits on top of detached HEAD, it is rather dangerous\nunless you are careful and know what you are doing.  Next \"git\ncheckout master\" will obviously lose what you have done, so we\nmight want to require \"git checkout -f\" out of a detached HEAD\nif we find that the HEAD commit is not an ancestor of any other\nbranches.\n\nOn the other hand, the reason the user did not start the ad-hoc\nwork on a new branch with \"git checkout -b\" was probably because\nthe work was of a throw-away nature, so the convenience of not\nhaving that safety valve might be even better.  We'll see.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n builtin-branch.c |   36 ++++++++++++++++++++++++++----------\n cache.h          |    2 +-\n git-checkout.sh  |   22 +++++++++++++++++++---\n path.c           |   26 ++++++++++++++++++--------\n setup.c          |    5 +++--\n 5 files changed, 67 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 745ee04..71f88f2 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -299,7 +299,8 @@ static void print_ref_list(int kinds, int verbose, int abbrev)\n \tfree_ref_list(&ref_list);\n }\n \n-static void create_branch(const char *name, const char *start,\n+static void create_branch(const char *name, const char *start_name,\n+\t\t\t  unsigned char *start_sha1,\n \t\t\t  int force, int reflog)\n {\n \tstruct ref_lock *lock;\n@@ -318,9 +319,14 @@ static void create_branch(const char *name, const char *start,\n \t\t\tdie(\"Cannot force update the current branch.\");\n \t}\n \n-\tif (get_sha1(start, sha1) ||\n-\t    (commit = lookup_commit_reference(sha1)) == NULL)\n-\t\tdie(\"Not a valid branch point: '%s'.\", start);\n+\tif (start_sha1)\n+\t\t/* detached HEAD */\n+\t\thashcpy(sha1, start_sha1);\n+\telse if (get_sha1(start_name, sha1))\n+\t\tdie(\"Not a valid object name: '%s'.\", start_name);\n+\n+\tif ((commit = lookup_commit_reference(sha1)) == NULL)\n+\t\tdie(\"Not a valid branch point: '%s'.\", start_name);\n \thashcpy(sha1, commit->object.sha1);\n \n \tlock = lock_any_ref_for_update(ref, NULL);\n@@ -329,7 +335,8 @@ static void create_branch(const char *name, const char *start,\n \n \tif (reflog) {\n \t\tlog_all_ref_updates = 1;\n-\t\tsnprintf(msg, sizeof msg, \"branch: Created from %s\", start);\n+\t\tsnprintf(msg, sizeof msg, \"branch: Created from %s\",\n+\t\t\t start_name);\n \t}\n \n \tif (write_ref_sha1(lock, sha1, msg) < 0)\n@@ -341,6 +348,9 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \tchar oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100];\n \tunsigned char sha1[20];\n \n+\tif (!oldname)\n+\t\tdie(\"cannot rename the curren branch while not on any.\");\n+\n \tif (snprintf(oldref, sizeof(oldref), \"refs/heads/%s\", oldname) > sizeof(oldref))\n \t\tdie(\"Old branchname too long\");\n \n@@ -447,9 +457,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \thead = xstrdup(resolve_ref(\"HEAD\", head_sha1, 0, NULL));\n \tif (!head)\n \t\tdie(\"Failed to resolve HEAD as a valid ref.\");\n-\tif (strncmp(head, \"refs/heads/\", 11))\n-\t\tdie(\"HEAD not found below refs/heads!\");\n-\thead += 11;\n+\tif (!strcmp(head, \"HEAD\")) {\n+\t\t/* detached HEAD */\n+\t\t;\n+\t}\n+\telse {\n+\t\tif (strncmp(head, \"refs/heads/\", 11))\n+\t\t\tdie(\"HEAD not found below refs/heads!\");\n+\t\thead += 11;\n+\t}\n \n \tif (delete)\n \t\treturn delete_branches(argc - i, argv + i, force_delete, kinds);\n@@ -460,9 +476,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \telse if (rename && (i == argc - 2))\n \t\trename_branch(argv[i], argv[i + 1], force_rename);\n \telse if (i == argc - 1)\n-\t\tcreate_branch(argv[i], head, force_create, reflog);\n+\t\tcreate_branch(argv[i], head, head_sha1, force_create, reflog);\n \telse if (i == argc - 2)\n-\t\tcreate_branch(argv[i], argv[i + 1], force_create, reflog);\n+\t\tcreate_branch(argv[i], argv[i+1], NULL, force_create, reflog);\n \telse\n \t\tusage(builtin_branch_usage);\n \ndiff --git a/cache.h b/cache.h\nindex 29dd290..891045c 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -296,7 +296,7 @@ extern char *sha1_to_hex(const unsigned char *sha1);\t/* static buffer result! */\n extern int read_ref(const char *filename, unsigned char *sha1);\n extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);\n extern int create_symref(const char *ref, const char *refs_heads_master);\n-extern int validate_symref(const char *ref);\n+extern int validate_headref(const char *ref);\n \n extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);\n extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2);\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 92ec069..c50df28 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -1,6 +1,6 @@\n #!/bin/sh\n \n-USAGE='[-f] [-b <new_branch>] [-m] [<branch>] [<paths>...]'\n+USAGE='[-f] [-b <new_branch>] [-d] [-m] [<branch>] [<paths>...]'\n SUBDIRECTORY_OK=Sometimes\n . git-sh-setup\n \n@@ -12,6 +12,7 @@ force=\n branch=\n newbranch=\n newbranch_log=\n+detached=\n merge=\n while [ \"$#\" != \"0\" ]; do\n     arg=\"$1\"\n@@ -27,6 +28,9 @@ while [ \"$#\" != \"0\" ]; do\n \t\tgit-check-ref-format \"heads/$newbranch\" ||\n \t\t\tdie \"git checkout: we do not like '$newbranch' as a branch name.\"\n \t\t;;\n+\t-d)\n+\t\tdetached=1\n+\t\t;;\n \t\"-l\")\n \t\tnewbranch_log=1\n \t\t;;\n@@ -144,13 +148,25 @@ fi\n # are switching to, then we'd better just be checking out\n # what we already had\n \n-[ -z \"$branch$newbranch\" ] &&\n-\t[ \"$new\" != \"$old\" ] &&\n+if test -z \"$branch$newbranch\" && test \"$new\" != \"$old\"\n+then\n+\tcase \"$detached\" in\n+\t'')\n \tdie \"git checkout: provided reference cannot be checked out directly\n \n   You need -b to associate a new branch with the wanted checkout. Example:\n   git checkout -b <new_branch_name> $arg\n \"\n+\t\t;;\n+\t1)\n+\t\t# NEEDSWORK: we would want to have this command here\n+\t\t# that allows us to detach the HEAD atomically.\n+\t\t# git update-ref --detach HEAD \"$new\"\n+\t\trm -f \"$GIT_DIR/HEAD\"\n+\t\techo \"$new\" >\"$GIT_DIR/HEAD\"\n+\t\t;;\n+\tesac\n+fi\n \n if [ \"X$old\" = X ]\n then\ndiff --git a/path.c b/path.c\nindex 066f621..94ddd7e 100644\n--- a/path.c\n+++ b/path.c\n@@ -90,10 +90,11 @@ int git_mkstemp(char *path, size_t len, const char *template)\n }\n \n \n-int validate_symref(const char *path)\n+int validate_headref(const char *path)\n {\n \tstruct stat st;\n \tchar *buf, buffer[256];\n+\tunsigned char sha1[20];\n \tint len, fd;\n \n \tif (lstat(path, &st) < 0)\n@@ -119,14 +120,23 @@ int validate_symref(const char *path)\n \t/*\n \t * Is it a symbolic ref?\n \t */\n-\tif (len < 4 || memcmp(\"ref:\", buffer, 4))\n+\tif (len < 4)\n \t\treturn -1;\n-\tbuf = buffer + 4;\n-\tlen -= 4;\n-\twhile (len && isspace(*buf))\n-\t\tbuf++, len--;\n-\tif (len >= 5 && !memcmp(\"refs/\", buf, 5))\n+\tif (!memcmp(\"ref:\", buffer, 4)) {\n+\t\tbuf = buffer + 4;\n+\t\tlen -= 4;\n+\t\twhile (len && isspace(*buf))\n+\t\t\tbuf++, len--;\n+\t\tif (len >= 5 && !memcmp(\"refs/\", buf, 5))\n+\t\t\treturn 0;\n+\t}\n+\n+\t/*\n+\t * Is this a detached HEAD?\n+\t */\n+\tif (!get_sha1_hex(buffer, sha1))\n \t\treturn 0;\n+\n \treturn -1;\n }\n \n@@ -241,7 +251,7 @@ char *enter_repo(char *path, int strict)\n \t\treturn NULL;\n \n \tif (access(\"objects\", X_OK) == 0 && access(\"refs\", X_OK) == 0 &&\n-\t    validate_symref(\"HEAD\") == 0) {\n+\t    validate_headref(\"HEAD\") == 0) {\n \t\tputenv(\"GIT_DIR=.\");\n \t\tcheck_repository_format();\n \t\treturn path;\ndiff --git a/setup.c b/setup.c\nindex 2ae57f7..cc97f9f 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -138,7 +138,8 @@ const char **get_pathspec(const char *prefix, const char **pathspec)\n  *    GIT_OBJECT_DIRECTORY environment variable\n  *  - a refs/ directory\n  *  - either a HEAD symlink or a HEAD file that is formatted as\n- *    a proper \"ref:\".\n+ *    a proper \"ref:\", or a regular file HEAD that has a properly\n+ *    formatted sha1 object name.\n  */\n static int is_git_directory(const char *suspect)\n {\n@@ -161,7 +162,7 @@ static int is_git_directory(const char *suspect)\n \t\treturn 0;\n \n \tstrcpy(path + len, \"/HEAD\");\n-\tif (validate_symref(path))\n+\tif (validate_headref(path))\n \t\treturn 0;\n \n \treturn 1;\n-- \n1.5.0.rc0.gab5a\n"},{"id":"30690","messageId":"20070102205901.3f4a9f1e.froese@gmx.de","threadId":"6193","inReplyTo":"7vac11yirf.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2007-01-02T19:59:01Z","receivedAt":"2007-01-02T19:59:01Z","isPatch":true,"sender":{"key":"froese@gmx.de","avatar":null},"body":"[Note: casual git-user speaking]\n\nJunio C Hamano wrote:\n>\n> This allows \"git checkout -d v1.4.3\" to detach the HEAD from any\n> branch but point directly at the named commit.  After this, \"git\n> branch\" starts reporting that you are not on any branch.\n\nNice.  But why -d?  Create more confusion? [1]\n\n> You can go back the normal state by switching to an existing\n> branch, say, \"git checkout master\" for example.\n\nThis is fine.  Often you want to test a couple of tags, one\nafter another, so \"git checkout v1\", \"git checkout v2\", ...\nshould work.\n\n> Another way to get out of this is \"git checkout -b newbranch\".\n\nWth should this do?  I already noticed this line in your posting\nfrom 29.Dec: [slightly edited]\n\n\t$ git checkout v1.5.0\n\tChecking out a tag -- you are not on any branch now...\n\t$ <modify>\n\t$ git commit -m 'fix' -a\n\tYou cannot commit without a current branch.\n\t$ git checkout -b maint-1.5.0\n\t$ git commit -m 'fix' -a\n\nI assume it will create a new branch and modify HEAD so that\nthe current working dir/index gets committed into that branch.\n(Basically \"git branch main-1.5.0 &&\n            echo 'ref: refs/head/main-1.5.0' >.git/HEAD\")\nIf that's the case, I was looking for that incantation for\na long time and couldn't find it.  I'm using the git-branch\nand echo as shown above to get that.  The man-page isn't\nvery helpful for that special case of git-checkout.\n\nAnyway, if I want to commit and git tells me that I can't\nbecause I'm not on a branch, the _most unintuitive_ thing\nwould be calling 'git-checkout'.  I want to checkin!  No\nway that I call checkout and risk losing all my changes.\n\nWhat's wrong with a -b option to commit, similar to -b on\ncheckout?\n\n\t$ git checkout v1.5.0\n\tChecking out a tag -- you are not on any branch now...\n\t$ <modify>\n\t$ git commit -m 'fix' -a\n\tYou cannot commit without a current branch.\n\tGive '-b <newbranch>' to commit into a new branch. \n\t$ git commit -b maint-1.5.0 -m 'fix' -a\n\nAnother variant (the one I prefer): commit just updates HEAD and\ngit-branch can be used to give it a name (and switch to it!).\nSo these workflows would be possible:\n\nName after commit:\n\n\t$ git checkout v1.5.0\n\tChecking out a tag -- you are not on any branch now...\n\t$ git branch\n\t  master\n\t* (unnamed) c8ff51290518949225c832bae1e22b1bba6ab2cd\n\t$ <modify>\n\t$ git commit -m 'fix' -a\n\tWarning: data committed into unnamed branch.\n\tGive it a name now with \"git branch <newname>\"\n\t$ git branch\n\t  master\n\t* (unnamed) 13482f25863e5380cdd41065338e1709d469a605\n\t$ git branch maint-1.5.0\n\t$ git branch\n\t  master\n\t* main-1.5.0\n\nor name before commit:\n\n\t$ git checkout v1.5.0\n\tChecking out a tag -- you are not on any branch now...\n\t$ <modify>\n\t$ git branch\n\t  master\n\t* (unnamed) c8ff51290518949225c832bae1e22b1bba6ab2cd\n\t$ git branch maint-1.5.0\n\t$ git branch\n\t  master\n\t* maint-1.5.0\n\t$ git commit -m 'fix' -a\n\nYes, 'git branch <newname>' would get a new semantic:\nif no start-point is given the newname will become the\nnew current branch.\n\n[Btw, I would even do that when we are on some branch. How\noften did I do a checkout of a regular branch and only later\nnoticed, that I want to commit changes into a temp-branch:\n\n\t$ git checkout master\n\t$ <play around, fix compile issues, add debug stuff>\n\t$ git branch debug\n\t$ git branch\n\t  master\n\t* debug\n\t$ git commit -a -m \"Add foo debugging code\"\n]\n\nBut that special case is IMHO (M = my, a casual user's) much\nbetter than some weird checkout-incantations.\n\nCiao, ET.\n\n\n[1] My pet-peeve:\n\n\t$ git checkout foo\n\tfatal: Entry 'bar' not uptodate. Cannot merge.\n\n    What the heck?  Nobody asked for a merge!?!?!  What\n    is it trying to do?  Does it actually mean:\n\n\tfatal: Working dir is dirty.  Either give '-f'\n\tto force the checkout and lose your changes, or\n\tgive '-m' to merge 'foo' and your changes.\n\n   ?  But then, why does an 'rm bar' fixes that?  Now 'bar'\n   definitely isn't \"uptodate\".\n"},{"id":"30708","messageId":"87ps9xgkjo.wl%cworth@cworth.org","threadId":"6193","inReplyTo":"7vac11yirf.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2007-01-02T21:56:11Z","receivedAt":"2007-01-02T21:56:11Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Mon, 01 Jan 2007 23:45:08 -0800, Junio C Hamano wrote:\n> This allows \"git checkout -d v1.4.3\" to detach the HEAD from any\n> branch but point directly at the named commit.\n\nBeing able to perform \"checkout\" with a tag like this, (and no\nspecific branch), is something I've been wanting git to acquire for\nsome time. So, thanks for coding this up!\n\n> This is still experimental.  While I think it makes sense to\n> allow commits on top of detached HEAD, it is rather dangerous\n> unless you are careful and know what you are doing.\n\nThis part I don't understand. I don't see why it's useful to introduce\nnew danger to \"git checkout\" in that after this change it could cause\ncommits to become dangling. Currently, \"git checkout\" is entirely\nsafe, as are most git commands. The few commands that create dangling\ncommits require fairly explicit actions from the user, (such as\n\"--hard\" for git-reset or -D instead of -d for git-branch).\n\nSo I'd vote against this aspect. I'd rather see commits to a detached\nhead be disallowed with a message instructing the user to do \"git\ncheckout -b new-branch\" in order to do the commit.\n\nAnd with that new safer behavior, I think it would be a good idea to\njust drop the \"-d\" option from git-checkout.\n\nI want this new behavior not for people who know what they are doing,\nbut people who are using git only incidentally, (say they just want to\nacquire and build the latest version of some software). So I'd like\nthe sequence to work along the lines of your earlier post, (as quoted\nby another reply). Specifically, I wouldn't want to see any warning\nabout a \"missing branch\" until a commit was attempted.\n\nThis would allow a sequence like this to proceed without git ever\ntelling the user they were doing something \"wrong\":\n\n\t$ git clone git://git.kernel.org/pub/scm/git/git.git\n\t$ cd git\n\t$ git checkout v1.4.3\n\t$ make\n\nWith the recent improvements to the git-checkout error message\n(thanks!) this sequence is at least successful eventually after the\nuser reads and responds to the following:\n\n\tgit checkout: provided reference cannot be checked out directly\n\n\t  You need -b to associate a new branch with the wanted\n\t  checkout. Example:\n\t  git checkout -b <new_branch_name> v1.4.3\n\nBut the user is required to invent a name and deal with its existence\nlater. For example, after some time, imagine the same user wanting\nto update to the latest and build again:\n\n\tgit pull origin\n\tgit checkout v1.5.0\n\nNow the user has to invent _another_ unique branch name, (or learn\n\"git branch -d\" or \"git reset --hard\" or ...), while this branch\nconcept and these other commands aren't actually helping the user with\nthe task at hand, (just tracking the code and building the most recent\nversion).\n\nSimilarly, I think this use case of \"just tracking\" should support\nbranches disappearing from the remote repository without the user\nhaving to edit any config file. If there are entries that are\nautomatically added by git-clone that should be removed later, that\nshould happen automatically. A recent thread suggested adding an error\nmessage instructing the user to delete the entries. That's again\nunkind to a user who doesn't really want to learn git, but just wants\nto get at the most recent version of some code that happens to be\navailable through git.\n\nThat disappearing branches cause problems requiring manual cleanup of\nconfiguration files is one of the reasons that we are not using any\nfeature branches in the \"central\" cairo repository, for example, (we\ndo have branches for release maintenance). I'd really like to be able\nto put some feature branches there for shared work, (rather than\nforcing that work out to separate personal repositories as we do\nknow).\n\nMaybe the configuration file entries added by git-clone need to be\nmarked in some way to distinguish them from manually added entries, so\nthat we would feel more comfortable automatically removing them when a\nremote branch has disappeared.\n\n-Carl\n"},{"id":"30712","messageId":"enelha$n8g$3@sea.gmane.org","threadId":"6193","inReplyTo":"87ps9xgkjo.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-01-02T22:18:13Z","receivedAt":"2007-01-02T22:18:13Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Carl Worth wrote:\n\n> Similarly, I think this use case of \"just tracking\" should support\n> branches disappearing from the remote repository without the user\n> having to edit any config file. If there are entries that are\n> automatically added by git-clone that should be removed later, that\n> should happen automatically. A recent thread suggested adding an error\n> message instructing the user to delete the entries. That's again\n> unkind to a user who doesn't really want to learn git, but just wants\n> to get at the most recent version of some code that happens to be\n> available through git.\n> \n> That disappearing branches cause problems requiring manual cleanup of\n> configuration files is one of the reasons that we are not using any\n> feature branches in the \"central\" cairo repository, for example, (we\n> do have branches for release maintenance). I'd really like to be able\n> to put some feature branches there for shared work, (rather than\n> forcing that work out to separate personal repositories as we do\n> know).\n> \n> Maybe the configuration file entries added by git-clone need to be\n> marked in some way to distinguish them from manually added entries, so\n> that we would feel more comfortable automatically removing them when a\n> remote branch has disappeared.\n\nIs it still problem (the dissapearing remote branches) with the new\nwildcard remote.<name>.fetch generated by new git-clone? I think it\nshould not complain that some branches vanished, but it would not I think\nit would remove no longer needed tracking branches (local branches)\nfor us...\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"30717","messageId":"7virfprquo.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"87ps9xgkjo.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-02T22:44:31Z","receivedAt":"2007-01-02T22:44:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n> On Mon, 01 Jan 2007 23:45:08 -0800, Junio C Hamano wrote:\n>> This allows \"git checkout -d v1.4.3\" to detach the HEAD from any\n>> branch but point directly at the named commit.\n>\n> Being able to perform \"checkout\" with a tag like this, (and no\n> specific branch), is something I've been wanting git to acquire for\n> some time. So, thanks for coding this up!\n>\n>> This is still experimental.  While I think it makes sense to\n>> allow commits on top of detached HEAD, it is rather dangerous\n>> unless you are careful and know what you are doing.\n>\n> This part I don't understand. I don't see why it's useful to introduce\n> new danger to \"git checkout\"...\n\nI am not saying being risky is useful.  That's why I said it is\nexperimental.\n\nWe could do two things, and I think disallowing commits is not\nnecessarily a better option of the two.  We could allow commits\nand prevent the user from switching out of the detached HEAD\nstate without an explicit action instead.  If we go the first\nroute, you need to also prevent merges into the detached HEAD.\nIf we go the latter I think you only need to add a check in\n\"git-checkout\" but there may be other cases.  In either way, we\nneed a safety valve, which the experimental code does not have.\n\nAnd being able to merge into the detached HEAD turns out to be\nsomewhat useful.  I checked out the v1.4.4.3 and tried to see if\na topic is applicable by merging into that detached HEAD and\nrunning testsuite.  Of course, without any safety valve, I can\neasily lose the merge result by switching out of the detached\nHEAD state (say, \"git checkout master\"), but on the other hand,\ncreating a new branch at that point with \"git checkout -b\nv1.4.4.3-maint\" would let me continue from that point without\nlosing anything.\n\nBut this is only \"somewhat\" -- I do not have strong opinion\neither way, other than that we need a safety valve (which we\nagree).\n\nIn any case, I did this because I got tired of waiting for it to\nhappen (I thought you wanted to hack on this over the long\nweek^W yearend, so I deliberately stayed away from doing this)\nand I was bored.  This will not be in 'next' in the current\nshape.\n\nYou've thought about the issue long enough to write your\ncommentary and I agree to most of your points (including\nfavoring \"no commit allowed in this state\" over \"allow commits\nand merges to help advanced usage\" for its simplicity), so if\nyou code it up with a clean patch, I would not reject it on the\nbasis of its design.\n"},{"id":"30723","messageId":"1167780131528-git-send-email-hjemli@gmail.com","threadId":"6193","inReplyTo":"7vac11yirf.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] git-branch: show detached HEAD","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-01-02T23:22:11Z","receivedAt":"2007-01-02T23:22:11Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"This makes git-branch show a detached HEAD as '* (no branch)'.\n\nSigned-off-by: Lars Hjemli <hjemli@gmail.com>\n---\n\nThis might be a premature patch. But if/when we allow HEAD to be detached, \ngit-branch should tell us that HEAD is the current 'branch'.\n\n builtin-branch.c |  103 +++++++++++++++++++++++++++++-------------------------\n 1 files changed, 55 insertions(+), 48 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 71f88f2..16f86cc 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -231,29 +231,54 @@ static int ref_cmp(const void *r1, const void *r2)\n \treturn strcmp(c1->name, c2->name);\n }\n \n-static void print_ref_info(const unsigned char *sha1, int abbrev)\n+static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, \n+\t\t\t   int abbrev, int current)\n {\n+\tchar c;\n+\tint color;\n \tstruct commit *commit;\n \tchar subject[256];\n \n+\tswitch (item->kind) {\n+\tcase REF_LOCAL_BRANCH:\n+\t\tcolor = COLOR_BRANCH_LOCAL;\n+\t\tbreak;\n+\tcase REF_REMOTE_BRANCH:\n+\t\tcolor = COLOR_BRANCH_REMOTE;\n+\t\tbreak;\n+\tdefault:\n+\t\tcolor = COLOR_BRANCH_PLAIN;\n+\t\tbreak;\n+\t}\n \n-\tcommit = lookup_commit(sha1);\n-\tif (commit && !parse_commit(commit))\n-\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,\n-\t\t\t\t    subject, sizeof(subject), 0,\n-\t\t\t\t    NULL, NULL, 0);\n-\telse\n-\t\tstrcpy(subject, \" **** invalid ref ****\");\n+\tc = ' ';\n+\tif (current) {\n+\t\tc = '*';\n+\t\tcolor = COLOR_BRANCH_CURRENT;\n+\t}\n \n-\tprintf(\" %s %s\\n\", find_unique_abbrev(sha1, abbrev), subject);\n+\tif (verbose) {\n+\t\tcommit = lookup_commit(item->sha1);\n+\t\tif (commit && !parse_commit(commit))\n+\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,\n+\t\t\t\t\t    subject, sizeof(subject), 0,\n+\t\t\t\t\t    NULL, NULL, 0);\n+\t\telse\n+\t\t\tstrcpy(subject, \" **** invalid ref ****\");\n+\t\tprintf(\"%c %s%-*s%s %s %s\\n\", c, branch_get_color(color),\n+\t\t       maxwidth, item->name,\n+\t\t       branch_get_color(COLOR_BRANCH_RESET),\n+\t\t       find_unique_abbrev(item->sha1, abbrev), subject);\n+\t} else {\n+\t\tprintf(\"%c %s%s%s\\n\", c, branch_get_color(color), item->name,\n+\t\t       branch_get_color(COLOR_BRANCH_RESET));\n+\t}\n }\n \n-static void print_ref_list(int kinds, int verbose, int abbrev)\n+static void print_ref_list(int kinds, int verbose, int abbrev, int detached)\n {\n \tint i;\n-\tchar c;\n \tstruct ref_list ref_list;\n-\tint color;\n \n \tmemset(&ref_list, 0, sizeof(ref_list));\n \tref_list.kinds = kinds;\n@@ -261,39 +286,22 @@ static void print_ref_list(int kinds, int verbose, int abbrev)\n \n \tqsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);\n \n-\tfor (i = 0; i < ref_list.index; i++) {\n-\t\tswitch( ref_list.list[i].kind ) {\n-\t\t\tcase REF_LOCAL_BRANCH:\n-\t\t\t\tcolor = COLOR_BRANCH_LOCAL;\n-\t\t\t\tbreak;\n-\t\t\tcase REF_REMOTE_BRANCH:\n-\t\t\t\tcolor = COLOR_BRANCH_REMOTE;\n-\t\t\t\tbreak;\n-\t\t\tdefault:\n-\t\t\t\tcolor = COLOR_BRANCH_PLAIN;\n-\t\t\t\tbreak;\n-\t\t}\n-\n-\t\tc = ' ';\n-\t\tif (ref_list.list[i].kind == REF_LOCAL_BRANCH &&\n-\t\t\t\t!strcmp(ref_list.list[i].name, head)) {\n-\t\t\tc = '*';\n-\t\t\tcolor = COLOR_BRANCH_CURRENT;\n-\t\t}\n+\tif (detached && (kinds & REF_LOCAL_BRANCH)) {\n+\t\tstruct ref_item item;\n+\t\titem.name = \"(no branch)\";\n+\t\titem.kind = REF_LOCAL_BRANCH;\n+\t\thashcpy(item.sha1, head_sha1);\n+\t\tif (strlen(item.name) > ref_list.maxwidth)\n+\t\t\t      ref_list.maxwidth = strlen(item.name);\n+\t\tprint_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);\n+\t}\n \n-\t\tif (verbose) {\n-\t\t\tprintf(\"%c %s%-*s%s\", c,\n-\t\t\t\t\tbranch_get_color(color),\n-\t\t\t\t\tref_list.maxwidth,\n-\t\t\t\t\tref_list.list[i].name,\n-\t\t\t\t\tbranch_get_color(COLOR_BRANCH_RESET));\n-\t\t\tprint_ref_info(ref_list.list[i].sha1, abbrev);\n-\t\t}\n-\t\telse\n-\t\t\tprintf(\"%c %s%s%s\\n\", c,\n-\t\t\t\t\tbranch_get_color(color),\n-\t\t\t\t\tref_list.list[i].name,\n-\t\t\t\t\tbranch_get_color(COLOR_BRANCH_RESET));\n+\tfor (i = 0; i < ref_list.index; i++) {\n+\t\tint current = !(detached && (kinds & REF_LOCAL_BRANCH)) &&\n+\t\t\t(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&\n+\t\t\t!strcmp(ref_list.list[i].name, head);\n+\t\tprint_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, \n+\t\t\t       abbrev, current);\n \t}\n \n \tfree_ref_list(&ref_list);\n@@ -380,7 +388,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n {\n \tint delete = 0, force_delete = 0, force_create = 0;\n \tint rename = 0, force_rename = 0;\n-\tint verbose = 0, abbrev = DEFAULT_ABBREV;\n+\tint verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;\n \tint reflog = 0;\n \tint kinds = REF_LOCAL_BRANCH;\n \tint i;\n@@ -458,8 +466,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (!head)\n \t\tdie(\"Failed to resolve HEAD as a valid ref.\");\n \tif (!strcmp(head, \"HEAD\")) {\n-\t\t/* detached HEAD */\n-\t\t;\n+\t\tdetached = 1;\n \t}\n \telse {\n \t\tif (strncmp(head, \"refs/heads/\", 11))\n@@ -470,7 +477,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (delete)\n \t\treturn delete_branches(argc - i, argv + i, force_delete, kinds);\n \telse if (i == argc)\n-\t\tprint_ref_list(kinds, verbose, abbrev);\n+\t\tprint_ref_list(kinds, verbose, abbrev, detached);\n \telse if (rename && (i == argc - 1))\n \t\trename_branch(head, argv[i], force_rename);\n \telse if (rename && (i == argc - 2))\n-- \n1.5.0.rc0.g76033\n"},{"id":"30719","messageId":"87odphgfzz.wl%cworth@cworth.org","threadId":"6193","inReplyTo":"7virfprquo.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2007-01-02T23:34:24Z","receivedAt":"2007-01-02T23:34:24Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Tue, 02 Jan 2007 14:44:31 -0800, Junio C Hamano wrote:\n> We could do two things, and I think disallowing commits is not\n> necessarily a better option of the two.  We could allow commits\n> and prevent the user from switching out of the detached HEAD\n> state without an explicit action instead.\n\nYeah, that would be fine too. Personally, I'd be happy with either\napproach.\n\n> \"git-checkout\" but there may be other cases.  In either way, we\n> need a safety valve, which the experimental code does not have.\n\nOK. I guess I misinterpreted things. I was afraid that you were\nproposing a safety valve on _entering_ the detached state, (perhaps\nthe -d option to checkout itself). It was the requirement of something\nextra to checkout a tag (as opposed to checkout of a branch) that I\ndisliked.\n\n> In any case, I did this because I got tired of waiting for it to\n> happen (I thought you wanted to hack on this over the long\n> week^W yearend, so I deliberately stayed away from doing this)\n> and I was bored.  This will not be in 'next' in the current\n> shape.\n\nI'm glad you went ahead. I ended up almost not touching computers at\nall from December 23 to January 2 [*].\n\n> You've thought about the issue long enough to write your\n> commentary and I agree to most of your points (including\n> favoring \"no commit allowed in this state\" over \"allow commits\n> and merges to help advanced usage\" for its simplicity), so if\n> you code it up with a clean patch, I would not reject it on the\n> basis of its design.\n\nI don't actually prefer \"no commit allowed\". I just didn't want the\nuser to have to explicitly disable the safety before being able to\nperform a checkout based on a tag.\n\nI am still interested in this feature, so I will try to find time to\ncome back with a revised version of your patch with the missing safety\ncheck (and without requiring -d on checkout). Thanks again for this\ninitial take on the problem. (Though if anyone else beats me to it, I\ncertainly will not be offended.)\n\n-Carl\n\n[*] I did play some nice new (to me) board games, (Zendo and DVONN\nbeing standouts), but thats a topic for elsewhere I suppose.\n"},{"id":"30947","messageId":"87mz51gd7e.wl%cworth@cworth.org","threadId":"6193","inReplyTo":"enelha$n8g$3@sea.gmane.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2007-01-03T00:34:45Z","receivedAt":"2007-01-03T00:34:45Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Tue, 02 Jan 2007 23:18:13 +0100, Jakub Narebski wrote:\n> Is it still problem (the dissapearing remote branches) with the new\n> wildcard remote.<name>.fetch generated by new git-clone?\n\nAh, you're right. Sorry I missed that, (looks like it was in next but\nnot in master). I had said I was going to start running from next to\ntest this stuff.\n\nSo now I tried switching to next and hit a couple minor surprises,\n(not big issues---mostly just me really trying out separate-remotes\nfor the first time, and pretending to some extent that I don't know\nanything about it):\n\n\t$ git checkout next\n\terror: pathspec 'next' did not match any file(s) known to git.\n\tDid you forget to 'git add'?\n\nHere I'm using a branch name that cannot be resolved but I'm getting\nan error message based on a path name that cannot be resolved. It's\ntricky to know how to construct the correct error message here since\n\"git checkout\" can accept either a branch name or a path name. But I\nwould argue that the branch name is the primary thing for \"git\ncheckout\" to act on so the error message should talk about that if the\nargument cannot be resolved as either a branch or a path. (Regardless,\n\"git add\" would not be a helpful suggestion if someone were actually\ntrying to do \"git checkout file\").\n\nSo I know that \"git checkout next\" used to work, and I know that we're\nnow in a \"separate remotes\" world. But I don't know how everything\nabout how they work yet. Clearly just using \"next\" doesn't resolve to\nanything anymore. So let's see what we have to work with:\n\n\t$ git branch\n\t* master\n\nHmm... nothing to see here (though the fact that the remote-tracking\nbranches don't show up here is generally quite nice---I love the\nreduced noise). But maybe we want at least an indication of what's\nnot being shown? Maybe something like:\n\n\t$ git branch\n\t* master\n\t[and 8 remote branches: use -r to see them as well]\n\nThat might avoid some confusion for upgraders anyway.\n\nMoving on, I can see the \"missing\" branches with:\n\n\t$ git branch -r\n\t  origin/HEAD\n\t  origin/html\n\t  origin/maint\n\t  origin/man\n\t  origin/master\n\t  origin/next\n\t  origin/pu\n\t  origin/todo\n\nAnd now I try to check one out:\n\n\t$ git checkout origin/next\n\tgit checkout: provided reference cannot be checked out directly\n\n\t  You need -b to associate a new branch with the wanted checkout. Example:\n\t  git checkout -b <new_branch_name> origin/next\n\nAnd now I start getting confused. If git-checkout wants a branch, and\ngit-branch says that \"origin/next\" is a branch, then why won't this\nwork? OK, I know that something's special about origin/next, (it's a\n\"remote-tracking branch\" and I needed a -r option to get git-branch to\nlist it for me), but nothing in the git-checkout documentation would\nlead me to expect that \"git checkout origin/next\" wouldn't work.\n\nBut at least I'm given a very clear error message here, (a great\nimprovement, thanks!), and even a sample command. So I can do:\n\n\t$ git checkout -b next origin/next\n\nAnd I'm happy that works and I can build things.\n\nBut say in a couple of days I want to build the latest in Junio's\n\"next\". What's the easiest recipe for that now? If I'm understanding\nthings correctly, I can update my remote-tracking origin/next with\njust:\n\n\t$ git pull origin\n\nAnd that's thanks to this entry in .git/config:\n\n\t[remote \"origin\"]\n\t        url = git://git.kernel.org/pub/scm/git/git.git\n\t        fetch = +refs/heads/*:refs/remotes/origin/*\n\nI _think_ there's also a way for me to configure my local \"next\" to\nautomatically fast-forward to track what's happening in \"origin/next\"\non any invocation of \"git pull origin\", right? That is, configure\norigin/next as the thing to get merged into my local next when I\npull. How do I do that again?  Where's that documented?\n\nAh, if I look in .git/config I can see that I should be able to just\ncopy the block for the \"master\" branch and come up with:\n\n\t[branch \"next\"]\n\t        remote = origin\n\t        merge = refs/heads/next\n\nis that right? If so, it's really nice that what used to be hard-coded\nmagic, (first remote branch getting merged into current branch), is\nnow self-documented magic that can easily be applied to other branch\ncombinations. Another great improvement, well done!\n\nThe remaining question is whether it wouldn't make sense to just\ncreate that block when I did \"git checkout -b next origin/next\". I\nthink this has been proposed before and Junio said \"Maybe, if\neverything can be resolved unambiguously, but even then, not\nalways\". I'd be interested in hearing more about when that would be\nthe wrong thing to do. It seems it would be awfully convenient here,\n(and not doing it means it's easy to end up with a local \"next\" branch\nwithout realizing how stale it is).\n\nNow, if I'm only tracking/building what's in next and not actually\nplanning on committing anything, then I wouldn't even need the local\nbranch at all if I could just checkout the remote tracking-branch\ndirectly:\n\n\t$ git checkout origin/next\n\nIn fact, I'd greatly prefer this, since a lot of the advantage of\nseparate remotes is that \"git branch\" lists only stuff I'm actually\nworking on and not other noise from remote branches that I consider\nuninteresting. Forcing me to clutter up that list just to examine the\nstate of some remote branch is not helpful.\n\nOf course, this feature depends on the pending \"detached HEAD\" work\nthat started this thread, (wow, look at that, I wandered back on\ntopic!).\n\nAnd a further question from there is whether it makes sense to have\n\"git checkout\" look around in .git/refs/remotes/* so that I could\ncheckout origin/next by just using the name \"next\":\n\n\t$ git checkout next\n\nwhich could complain if that couldn't be resolved without ambiguity.\nWould that be a bad idea?\n\n-Carl\n"},{"id":"30721","messageId":"7vd55wsu8w.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"87odphgfzz.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-03T02:45:51Z","receivedAt":"2007-01-03T02:45:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n> I don't actually prefer \"no commit allowed\". I just didn't want the\n> user to have to explicitly disable the safety before being able to\n> perform a checkout based on a tag.\n\nOk, then I think we are in agreement that the safety should be\nat the point where the user might leave the detached state.\n\n> I am still interested in this feature, so I will try to find time to\n> come back with a revised version of your patch with the missing safety\n> check (and without requiring -d on checkout). Thanks again for this\n> initial take on the problem. (Though if anyone else beats me to it, I\n> certainly will not be offended.)\n\nSounds good.  \n\nI do not mind losing -d, but I would suggest that there should\nbe a message that says \"you are no longer on any branch\" after a\ncheckout that makes the head detached.  The user should be\nwarned about such an unusal situation.\n"},{"id":"30724","messageId":"20070103051811.GB23358@spearce.org","threadId":"6193","inReplyTo":"1167780131528-git-send-email-hjemli@gmail.com","subject":"Re: [PATCH] git-branch: show detached HEAD","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-03T05:18:11Z","receivedAt":"2007-01-03T05:18:11Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Lars Hjemli <hjemli@gmail.com> wrote:\n> This makes git-branch show a detached HEAD as '* (no branch)'.\n\nIt would be nicer if when you are on a remote tracking branch or\non a tag that the name of the tag or the remote tracking branch is\nshown rather than '* (no branch)'.\n\n-- \nShawn.\n"},{"id":"30728","messageId":"7v7iw4r47e.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"20070103051811.GB23358@spearce.org","subject":"Re: [PATCH] git-branch: show detached HEAD","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-03T06:53:41Z","receivedAt":"2007-01-03T06:53:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> writes:\n\n> Lars Hjemli <hjemli@gmail.com> wrote:\n>> This makes git-branch show a detached HEAD as '* (no branch)'.\n>\n> It would be nicer if when you are on a remote tracking branch or\n> on a tag that the name of the tag or the remote tracking branch is\n> shown rather than '* (no branch)'.\n\nThat would be utterly confusing if you are talking about the\nsame detached HEAD semantics as I and Carl discussed today.  I\nlike what Lars's patch does (although I felt that it was too big\nfor only doing this which made it harder to judge), but I would\neven make it stronger to say something like:\n\n\t* You are not on ANY branch right now.\n          master\n          next\n          pu\n          ...\n\nYou will never be _on_ a remote tracking branch.  So far we did\nnot allow HEAD to point at outside refs/heads/ and we still\ndon't.  When HEAD is detached from any branch, however, it can\nstore a bare 40-hex (plus LF) commit object name instead of\nbeing a symref.  You are not on any branch at that point.\n\nMost importantly, if we allow commits to be built on top of HEAD\nwhile it is detached from any branch, the commit will _not_\nadvance any branch.  So showing the remote tracking branch the\nway you suggest will be misleading.\n\nIf we do not allow commits to be built on top, we would still\nallow something to be done other than switching out of \"detached\nmode\" to be useful.  For example, reset to move around which\ncommit to look at would be a useful thing.  Another of my\nunstated desire is to get rid of the use of special \"bisect\"\nbranch during bisection using detached HEAD.  Again, if we\nhighlight remote tracking branch whose tip happens to be the\nsame commit as the current HEAD as you suggest, that would lead\nto quite confusing behaviour.  Sometimes it would say the same\nthing as you are _on_ that branch (which confuses you because\nyou are _not_ on that branch in reality), sometimes it would\nhighlight nothing to show you are not on any branch.\n"},{"id":"30729","messageId":"7v1wmcr3nz.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"1167780131528-git-send-email-hjemli@gmail.com","subject":"Re: [PATCH] git-branch: show detached HEAD","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-03T07:05:20Z","receivedAt":"2007-01-03T07:05:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lars Hjemli <hjemli@gmail.com> writes:\n\n> This makes git-branch show a detached HEAD as '* (no branch)'.\n>\n> Signed-off-by: Lars Hjemli <hjemli@gmail.com>\n> ---\n>\n> This might be a premature patch. But if/when we allow HEAD to be detached, \n> git-branch should tell us that HEAD is the current 'branch'.\n\nI fully agree with the motivation, but 100 lines of change to\nadjust only to detached HEAD seems too much.  What else is going\non in this patch, I wonder...\n\nCan we have two patches, one for loop restructuring without\ndetached HEAD support, and then another to add support for it?\n"},{"id":"30731","messageId":"8c5c35580701022337y6719883eyd907b89d0d6f7217@mail.gmail.com","threadId":"6193","inReplyTo":"7v1wmcr3nz.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-branch: show detached HEAD","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-01-03T07:37:02Z","receivedAt":"2007-01-03T07:37:02Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On 1/3/07, Junio C Hamano <junkio@cox.net> wrote:\n> Can we have two patches, one for loop restructuring without\n> detached HEAD support, and then another to add support for it?\n\nSure, I'll do it tonight\n\n-- \nlarsh\n"},{"id":"30732","messageId":"8c5c35580701022350n13742ec1n6f5fadcf1dfb18aa@mail.gmail.com","threadId":"6193","inReplyTo":"7v7iw4r47e.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-branch: show detached HEAD","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-01-03T07:50:50Z","receivedAt":"2007-01-03T07:50:50Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On 1/3/07, Junio C Hamano <junkio@cox.net> wrote:\n> I would even make it stronger to say something like:\n>\n>         * You are not on ANY branch right now.\n>           master\n>           next\n>           pu\n>           ...\n>\n\nHmm, that wouldn't be very nice for 'git-branch -v' (which suddenly\ngot extra useful with detached head).\n\n-- \nlarsh\n"},{"id":"30733","messageId":"7vslespmwa.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"8c5c35580701022350n13742ec1n6f5fadcf1dfb18aa@mail.gmail.com","subject":"Re: [PATCH] git-branch: show detached HEAD","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-03T07:52:53Z","receivedAt":"2007-01-03T07:52:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Lars Hjemli\" <hjemli@gmail.com> writes:\n\n> On 1/3/07, Junio C Hamano <junkio@cox.net> wrote:\n>> I would even make it stronger to say something like:\n>>\n>>         * You are not on ANY branch right now.\n>>           master\n>>           next\n>>           pu\n>>           ...\n>>\n>\n> Hmm, that wouldn't be very nice for 'git-branch -v' (which suddenly\n> got extra useful with detached head).\n\nAh, please scratch that.\n\nI did not remember that option, since I do not use it myself.\nThanks for injecting sanity.\n"},{"id":"30740","messageId":"20070103104620.GA27015@coredump.intra.peff.net","threadId":"6193","inReplyTo":"7virfprquo.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-01-03T10:46:20Z","receivedAt":"2007-01-03T10:46:20Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Jan 02, 2007 at 02:44:31PM -0800, Junio C Hamano wrote:\n\n> necessarily a better option of the two.  We could allow commits\n> and prevent the user from switching out of the detached HEAD\n> state without an explicit action instead.  If we go the first\n\nI think you should only enact this safety valve if there have actually\nbeen commits. Otherwise, people who are just tracking and do a\n\"git-checkout v1.4.0; look look look; git-checkout v1.5.0\" will get a\nconfusing message.\n\nPersonally, I like the \"don't allow commit without a branch\" approach,\nbut only if you can \"git-commit -b newbranch\" and \"git-merge -b\nnewbranch\" to make it convenient to create a branch. Making commits that\naren't on any branch seems like a broken state (and indeed, you have to\nuse special options to get out of the state); it makes more sense to me\nto never enter the state in the first place.\n\nAlso, the implementation should be conceptually simple. Put\nrefs/tags/v1.4.0 into HEAD on checkout. Disallow commit/merge unless\nHEAD points to refs/heads/*.\n\nJust my 2 cents...\n\n-Peff\n"},{"id":"30742","messageId":"20070103115924.GA11136@coredump.intra.peff.net","threadId":"6193","inReplyTo":"20070103104620.GA27015@coredump.intra.peff.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-01-03T11:59:24Z","receivedAt":"2007-01-03T11:59:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 03, 2007 at 05:46:20AM -0500, Jeff King wrote:\n\n> Also, the implementation should be conceptually simple. Put\n> refs/tags/v1.4.0 into HEAD on checkout. Disallow commit/merge unless\n> HEAD points to refs/heads/*.\n\nLet me take that back. It is actually still annoying to implement, since\nmany things (at least commit-tree, branch) are unhappy with a non-branch\nin HEAD. Moreover, it's not as flexible as simply putting the commit\nsha1 into the HEAD, as you suggested. My suggestion allows only\nnon-branch refs to be checked-out; however, it's likely somebody might\nwant to git-checkout HEAD~10 or some other unnamed thing.\n\n-Peff\n"},{"id":"30977","messageId":"20070106185836.GH4655@fieldses.org","threadId":"6193","inReplyTo":"87mz51gd7e.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2007-01-06T18:58:36Z","receivedAt":"2007-01-06T18:58:36Z","isPatch":true,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Tue, Jan 02, 2007 at 04:34:45PM -0800, Carl Worth wrote:\n> And now I start getting confused. If git-checkout wants a branch, and\n> git-branch says that \"origin/next\" is a branch, then why won't this\n> work? OK, I know that something's special about origin/next, (it's a\n> \"remote-tracking branch\" and I needed a -r option to get git-branch to\n> list it for me), but nothing in the git-checkout documentation would\n> lead me to expect that \"git checkout origin/next\" wouldn't work.\n\nIf we use the word \"branches\" for things that you can check out and\ncommit to, then \"remote-tracking branches\" are not actually branches.\nArgh!\n\nWhat would be better terminology here?\n\n--b.\n"},{"id":"30982","messageId":"200701062048.15163.alan@chandlerfamily.org.uk","threadId":"6193","inReplyTo":"20070106185836.GH4655@fieldses.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Alan Chandler","fromEmail":"alan@chandlerfamily.org.uk","sentAt":"2007-01-06T20:48:15Z","receivedAt":"2007-01-06T20:48:15Z","isPatch":true,"sender":{"key":"alan@chandlerfamily.org.uk","avatar":"https://gravatar.com/avatar/1862247e5ea8eac114c842f9dc3a5db6253754e24ef7171757cf97eedce48b8c?d=mp&s=160"},"body":"On Saturday 06 January 2007 18:58, J. Bruce Fields wrote:\n> If we use the word \"branches\" for things that you can check out and\n> commit to, then \"remote-tracking branches\" are not actually branches.\n> Argh!\n>\n> What would be better terminology here?\n\nWhy can't we use the terms 'local branch' and 'remote branch'.  We can \nonly commit to local branches - you need to push to remote ones.\n-- \nAlan Chandler\nhttp://www.chandlerfamily.org.uk\n"},{"id":"30985","messageId":"20070106225242.GJ4655@fieldses.org","threadId":"6193","inReplyTo":"200701062048.15163.alan@chandlerfamily.org.uk","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2007-01-06T22:52:42Z","receivedAt":"2007-01-06T22:52:42Z","isPatch":true,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Sat, Jan 06, 2007 at 08:48:15PM +0000, Alan Chandler wrote:\n> On Saturday 06 January 2007 18:58, J. Bruce Fields wrote:\n> > If we use the word \"branches\" for things that you can check out and\n> > commit to, then \"remote-tracking branches\" are not actually branches.\n> > Argh!\n> >\n> > What would be better terminology here?\n> \n> Why can't we use the terms 'local branch' and 'remote branch'.  We can \n> only commit to local branches - you need to push to remote ones.\n\nWe'd have to replace \"branch\" by \"local branch\" in a lot of\ndocumentation, but that could work.\n\nThough what do you call a branch in a remote repository then, if not a\nremote branch?  I suppose it doesn't matter.\n\n--b.\n"},{"id":"31128","messageId":"7vbql9ydd7.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"87odphgfzz.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-08T11:19:48Z","receivedAt":"2007-01-08T11:19:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n> On Tue, 02 Jan 2007 14:44:31 -0800, Junio C Hamano wrote:\n> ...\n>> In any case, I did this because I got tired of waiting for it to\n>> happen (I thought you wanted to hack on this over the long\n>> week^W yearend, so I deliberately stayed away from doing this)\n>> and I was bored.  This will not be in 'next' in the current\n>> shape.\n> ...\n> I don't actually prefer \"no commit allowed\". I just didn't want the\n> user to have to explicitly disable the safety before being able to\n> perform a checkout based on a tag.\n>\n> I am still interested in this feature,...\n\nI decided to fast-track this one.  With a handful fix-ups, this\nis now at the tip of 'next'.\n\nThe primary difference from the one we discussed, and then has\nbeen sitting in 'pu', is that coming back from the detached HEAD\nstate is allowed only with '-f' or to a branch that is a\nfast-forward of HEAD.\n\nSo you can do:\n\n\tgit checkout v1.2.0 ;# detach\n        ... look around ...\n        git checkout v1.4.0 ;# still detached\n        ... look around ...\n        git checkout master ;# Ok, because v1.4.0 is an ancestor of master\n\nbut you would be warned and asked to say -f if you do:\n\n        git checkout v1.4.0 ;# detach\n        edit ...\n        git commit -a -m 'some tweak'\n\tgit checkout master ;# Not Ok -- you may lose that commit.\n\nAn alternative exit in this case is to create a new branch at\nthat point.  So this does work:\n\n        git checkout v1.4.0 ;# detach\n        edit ...\n        git commit -a -m 'some tweak'\n\tgit checkout -b maint-1.4.0 ;# start the maint-1.4.0 branch\n\nHave fun.\n"},{"id":"31136","messageId":"20070108131735.GA2647@coredump.intra.peff.net","threadId":"6193","inReplyTo":"7vbql9ydd7.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-01-08T13:17:35Z","receivedAt":"2007-01-08T13:17:35Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Jan 08, 2007 at 03:19:48AM -0800, Junio C Hamano wrote:\n\n> I decided to fast-track this one.  With a handful fix-ups, this\n> is now at the tip of 'next'.\n\nI haven't seen the code, waiting for kernel.org to mirror, but I have a\nquestion...\n\n> The primary difference from the one we discussed, and then has\n> been sitting in 'pu', is that coming back from the detached HEAD\n> state is allowed only with '-f' or to a branch that is a\n> fast-forward of HEAD.\n\nHrm. So does that mean this doesn't work (without -f):\n\n  git checkout v1.4.0\n  ... look around ...\n  git checkout v1.2.0\n\nI think a better (but more expensive) check would be \"coming back from\nthe detached HEAD is allowed only with '-f' or if HEAD is an ancestor\nof any non-HEAD ref.\"\n\n-Peff\n"},{"id":"31170","messageId":"7vzm8tt5kf.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"20070108131735.GA2647@coredump.intra.peff.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-09T00:19:28Z","receivedAt":"2007-01-09T00:19:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Mon, Jan 08, 2007 at 03:19:48AM -0800, Junio C Hamano wrote:\n>\n>> I decided to fast-track this one.  With a handful fix-ups, this\n>> is now at the tip of 'next'.\n>\n> I haven't seen the code, waiting for kernel.org to mirror, but I have a\n> question...\n>\n>> The primary difference from the one we discussed, and then has\n>> been sitting in 'pu', is that coming back from the detached HEAD\n>> state is allowed only with '-f' or to a branch that is a\n>> fast-forward of HEAD.\n>\n> Hrm. So does that mean this doesn't work (without -f):\n>\n>   git checkout v1.4.0\n>   ... look around ...\n>   git checkout v1.2.0\n\nThat should work.\n\nThe first checkout, because there is no branch v1.4.0, makes the\nHEAD detached.  You are no longer on any branch at that point,\nand \"git checkout v1.2.0\" that follows do not trigger the check\nwhich is about \"coming back from the detached HEAD state\".\n\nBut I would probably do the second v1.2.0 \"checkout\" with \"git\nreset --hard\", if what I am doing is \"wandering, looking around\nto see different commits\".\n"},{"id":"31172","messageId":"87fyalyqqz.wl%cworth@cworth.org","threadId":"6193","inReplyTo":"7vzm8tt5kf.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2007-01-09T00:43:00Z","receivedAt":"2007-01-09T00:43:00Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Mon, 08 Jan 2007 16:19:28 -0800, Junio C Hamano wrote:\n> The first checkout, because there is no branch v1.4.0, makes the\n> HEAD detached.  You are no longer on any branch at that point,\n> and \"git checkout v1.2.0\" that follows do not trigger the check\n> which is about \"coming back from the detached HEAD state\".\n\nSo what's the final check? Is it \"can come from detached HEAD to a\nbranch only if the detached HEAD is reachable from the target branch\"?\n\nIf so, that's still a trap for people who are just exploring with \"git\ncheckout\" and never make any commits while detached.\n\n> But I would probably do the second v1.2.0 \"checkout\" with \"git\n> reset --hard\", if what I am doing is \"wandering, looking around\n> to see different commits\".\n\nYou would probably do this, yes, but is it what you would recommend\nin a tutorial for new users doing read-only exploration of old\nversions of some piece of software? One of the main reasons I'm\ninterested in the \"detached head\" stuff is so that such users can use\n\"git checkout\" to explore any revision and never have to worry about\ndoing anything \"wrong\", (never leave any commits dangling), nor ever\nhave to see any \"scary\" message, (ie. \"use checkout -f if you know\nwhat you are doing\").\n\n-Carl\n\nPS. Thanks for giving detached head some attention---I'm chronically\ninept at getting into actual git development like I'd really like to."},{"id":"31174","messageId":"7v7ivxt3ft.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"87fyalyqqz.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-09T01:05:26Z","receivedAt":"2007-01-09T01:05:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n> On Mon, 08 Jan 2007 16:19:28 -0800, Junio C Hamano wrote:\n>> The first checkout, because there is no branch v1.4.0, makes the\n>> HEAD detached.  You are no longer on any branch at that point,\n>> and \"git checkout v1.2.0\" that follows do not trigger the check\n>> which is about \"coming back from the detached HEAD state\".\n>\n> So what's the final check? Is it \"can come from detached HEAD to a\n> branch only if the detached HEAD is reachable from the target branch\"?\n>\n> If so, that's still a trap for people who are just exploring with \"git\n> checkout\" and never make any commits while detached.\n\nAn obvious alternative is not to allow building on top of a HEAD\nthat is detached at all, which I suggested initially.\n\nA non-alternative is to silently lose commits, which you seem to\nbe suggesting, but I would rather play it safe.\n\nThe wording used for current warning that says \"use checkout -f\"\nis horrible, and it needs to be reworded much better, but other\nthan that, I think playing safer is much better than making a\nworse trap of silently losing the commits they may make before\nthey come to understand how \"a branch\" works.\n"},{"id":"31176","messageId":"87d55pyp82.wl%cworth@cworth.org","threadId":"6193","inReplyTo":"7v7ivxt3ft.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2007-01-09T01:15:57Z","receivedAt":"2007-01-09T01:15:57Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Mon, 08 Jan 2007 17:05:26 -0800, Junio C Hamano wrote:\n> An obvious alternative is not to allow building on top of a HEAD\n> that is detached at all, which I suggested initially.\n\nThat sounds great to me. Let's just suggest \"checkout -b\" before\ncommit, (maybe even add new \"merge -b <newbranch>\" and \"commit -b\n<newbranch>\" so the suggest command could be even closer to what the\nuser wanted).\n\n> A non-alternative is to silently lose commits, which you seem to\n> be suggesting, but I would rather play it safe.\n\nNo, I would never want that. We both agreed earlier that a safety\nvalve is necessary.\n\nI just want to make sure that people that never actually need it don't\nhave to see the message. And I don't think that _that_ part would be\nfeasible with the safety valve at the point of \"leaving detached\nstate\". It would basically come down to having to do reachability\nanalysis for the current HEAD from all known branches or something\nequally horrific.\n\nSo let's put the safety valve where it's cheap to detect and where we\nknow it will distinguish between read-only and read-write use, (that\nis, put it precisely at the point where there's an attempt to create a\nnew commit object while in the detached state).\n\n-Carl\n"},{"id":"31183","messageId":"20070109032640.GB1904@spearce.org","threadId":"6193","inReplyTo":"87d55pyp82.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-09T03:26:40Z","receivedAt":"2007-01-09T03:26:40Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Carl Worth <cworth@cworth.org> wrote:\n> On Mon, 08 Jan 2007 17:05:26 -0800, Junio C Hamano wrote:\n> > An obvious alternative is not to allow building on top of a HEAD\n> > that is detached at all, which I suggested initially.\n> \n> I just want to make sure that people that never actually need it don't\n> have to see the message. And I don't think that _that_ part would be\n> feasible with the safety valve at the point of \"leaving detached\n> state\". It would basically come down to having to do reachability\n> analysis for the current HEAD from all known branches or something\n> equally horrific.\n\nThe common case is probably going to be where the argument to\n`git checkout` is a fast-foward of the detached HEAD.  And that's\npretty cheap to check.  So we perform that check, and if we fail\nthat then we search through every ref to determine if the detached\nHEAD is fully contained in any of those.  Currently that would be\npretty slow to do with the current tools, but a small modification\nof say git-merge-base (or git-describe) might make it cheap enough\nto run during this slightly less common case.\n\nNo need to complicate merge/am/rebase/revert/commit/applymbox\nwith a -b option.\n\n-- \nShawn.\n"},{"id":"31203","messageId":"7v3b6ksmo7.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"20070109032640.GB1904@spearce.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-09T07:07:36Z","receivedAt":"2007-01-09T07:07:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> writes:\n\n> The common case is probably going to be where the argument to\n> `git checkout` is a fast-foward of the detached HEAD.  And that's\n> pretty cheap to check.  So we perform that check, and if we fail\n> that then we search through every ref to determine if the detached\n> HEAD is fully contained in any of those.  Currently that would be\n> pretty slow to do with the current tools, but a small modification\n> of say git-merge-base (or git-describe) might make it cheap enough\n> to run during this slightly less common case.\n\nThe needed change to merge-base is quite minimum.  Let me come\nup with a patch...\n"},{"id":"31209","messageId":"588099.85369.qm@web31805.mail.mud.yahoo.com","threadId":"6193","inReplyTo":"87d55pyp82.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Luben Tuikov","fromEmail":"ltuikov@yahoo.com","sentAt":"2007-01-09T08:12:58Z","receivedAt":"2007-01-09T08:12:58Z","isPatch":true,"sender":{"key":"ltuikov@yahoo.com","avatar":null},"body":"--- Carl Worth <cworth@cworth.org> wrote:\n> \n> So let's put the safety valve where it's cheap to detect and where we\n> know it will distinguish between read-only and read-write use, (that\n> is, put it precisely at the point where there's an attempt to create a\n> new commit object while in the detached state).\n\nYes, I agree.\n\n>From my point of view, the question is where does it \"go\" committing\nchanges on top of a \"detached HEAD\".  Commits shold probably be only\nallowed on top of local branches, since creating the branch itself\nshows an intention, possibly intention to do work, to commit\nnew things.\n\n    Luben\n"},{"id":"31227","messageId":"7v64bgpjmy.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"7v3b6ksmo7.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH 0/6] Expose in_merge_bases() via merge-base.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-09T10:41:25Z","receivedAt":"2007-01-09T10:41:25Z","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> \"Shawn O. Pearce\" <spearce@spearce.org> writes:\n>\n>> The common case is probably going to be where the argument to\n>> `git checkout` is a fast-foward of the detached HEAD.  And that's\n>> pretty cheap to check.  So we perform that check, and if we fail\n>> that then we search through every ref to determine if the detached\n>> HEAD is fully contained in any of those.  Currently that would be\n>> pretty slow to do with the current tools, but a small modification\n>> of say git-merge-base (or git-describe) might make it cheap enough\n>> to run during this slightly less common case.\n>\n> The needed change to merge-base is quite minimum.  Let me come\n> up with a patch...\n\n[PATCH 1/6] Allow in_merge_bases() to take more than one reference commits.\n[PATCH 2/6] merge_base(): move traversal into a separate function.\n[PATCH 3/6] git-merge-base: --check-ancestry option\n[PATCH 4/6] in_merge_bases(): optimization\n[PATCH 5/6] Make merge-base a built-in.\n[PATCH 6/6] Teach \"git-merge-base --check-ancestry\" about refs.\n"},{"id":"31245","messageId":"20070109142130.GA10633@coredump.intra.peff.net","threadId":"6193","inReplyTo":"7vzm8tt5kf.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-01-09T14:21:31Z","receivedAt":"2007-01-09T14:21:31Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Jan 08, 2007 at 04:19:28PM -0800, Junio C Hamano wrote:\n\n> > Hrm. So does that mean this doesn't work (without -f):\n> >\n> >   git checkout v1.4.0\n> >   ... look around ...\n> >   git checkout v1.2.0\n> \n> That should work.\n> \n> The first checkout, because there is no branch v1.4.0, makes the\n> HEAD detached.  You are no longer on any branch at that point,\n> and \"git checkout v1.2.0\" that follows do not trigger the check\n> which is about \"coming back from the detached HEAD state\".\n\nOh, that's even worse, since the safety valve doesn't kick in when it\nshould. For example, with what's in next now, I can do this:\n\n  git checkout v1.4.0\n  hack hack hack\n  git commit -m -a 'some changes which will never be seen again'\n  git checkout v1.2.0\n\nI thought the _point_ of the safety valve was not to lose those changes.\n\n> But I would probably do the second v1.2.0 \"checkout\" with \"git\n> reset --hard\", if what I am doing is \"wandering, looking around\n> to see different commits\".\n\nAs Carl mentioned, I think recommending that workflow is a terrible idea\nfrom a user interface perspective.\n\n-Peff\n"},{"id":"31284","messageId":"7virffkick.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"20070109142130.GA10633@coredump.intra.peff.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-09T21:20:27Z","receivedAt":"2007-01-09T21:20:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> For example, with what's in next now, I can do this:\n>\n>   git checkout v1.4.0\n>   hack hack hack\n>   git commit -m -a 'some changes which will never be seen again'\n>   git checkout v1.2.0\n>\n> I thought the _point_ of the safety valve was not to lose those changes.\n\nFair enough.\n\nWe could always do the check upon \"git checkout\" from a detached\nHEAD state, whether it takes you back on some existing branch or\nleaves your HEAD still detached.\n"},{"id":"31286","messageId":"20070109213117.GB25012@fieldses.org","threadId":"6193","inReplyTo":"7virffkick.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2007-01-09T21:31:17Z","receivedAt":"2007-01-09T21:31:17Z","isPatch":true,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Tue, Jan 09, 2007 at 01:20:27PM -0800, Junio C Hamano wrote:\n> Jeff King <peff@peff.net> writes:\n> \n> > For example, with what's in next now, I can do this:\n> >\n> >   git checkout v1.4.0\n> >   hack hack hack\n> >   git commit -m -a 'some changes which will never be seen again'\n> >   git checkout v1.2.0\n> >\n> > I thought the _point_ of the safety valve was not to lose those changes.\n> \n> Fair enough.\n> \n> We could always do the check upon \"git checkout\" from a detached\n> HEAD state, whether it takes you back on some existing branch or\n> leaves your HEAD still detached.\n\nStupid question: why can't checkout do something like this?\n\n\tif we're currently not on a branch, fail if .git/PREV\n\t\tdoesn't point to the same commit as .git/HEAD.\n\n\tif we're checking out a non-branch, store its SHA1 into\n\t\t.git/PREV.\n\nSo the user gets a warning (overrideable with some kind of --force\noption) if they do a checkout when the HEAD isn't exactly what they last\nchecked out.  Then\n\n\tgit checkout master\n\tgit checkout v1.4.0\n\tgit checkout v1.2.0\n\tgit checkout master\n\nall works without complaints, but the example above gives a warning at\nthe \"git checkout v1.2.0\" point.\n\n--b.\n"},{"id":"31292","messageId":"87zm8ryiyz.wl%cworth@cworth.org","threadId":"6193","inReplyTo":"20070109213117.GB25012@fieldses.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2007-01-09T21:43:16Z","receivedAt":"2007-01-09T21:43:16Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Tue, 9 Jan 2007 16:31:17 -0500, \"J. Bruce Fields\" wrote:\n> > >   git checkout v1.4.0\n> > >   hack hack hack\n> > >   git commit -m -a 'some changes which will never be seen again'\n> > >   git checkout v1.2.0\n> > >\n> > > I thought the _point_ of the safety valve was not to lose those changes.\n...\n> Stupid question: why can't checkout do something like this?\n>\n> \tif we're currently not on a branch, fail if .git/PREV\n> \t\tdoesn't point to the same commit as .git/HEAD.\n>\n> \tif we're checking out a non-branch, store its SHA1 into\n> \t\t.git/PREV.\n\nI would guess the problem is that this would still cause warnings even\nif the user had since given a name (created a branch) for the commits\noriginally made to the dangling head.\n\nFrankly, I don't understand why so much effort is being put toward\nallowing these \"fragile commits\" to be made in the first place. Why\nnot require users to name the branch before creating any commits, just\nas has always been the case?\n\nTo me, the only real advantage to the new \"detached head\" stuff is\nsimply making it easier to checkout previous state without having to\nname a new branch precisely _because_ the user has not intent to\ncommit anything. If the user is going to commit something, then the\nuser should be able to come up with a name for the branch.\n\nBut, whatever, if allowing fragile commits is seen as important by\nthose doing the work, who am I to complain about that? I'd just ask\nthat the following not be made slow:\n\n\tgit checkout commit-from-beginning-of-time\n\tgit checkout master\n\nThanks to the index, and the simplicity of what \"git checkout\" means,\ncheckout has always been blisteringly fast. All the talk of doing\nreachability analysis scares me from a performance point of view,\n(particularly when the _interesting_ cases (to me) of checkouts to\nnon-branches never need this anyway---since no commits will be made).\n\nThanks,\n\n-Carl\n"},{"id":"31293","messageId":"20070109215343.GC25012@fieldses.org","threadId":"6193","inReplyTo":"87zm8ryiyz.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2007-01-09T21:53:43Z","receivedAt":"2007-01-09T21:53:43Z","isPatch":true,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Tue, Jan 09, 2007 at 01:43:16PM -0800, Carl Worth wrote:\n> On Tue, 9 Jan 2007 16:31:17 -0500, \"J. Bruce Fields\" wrote:\n> > > >   git checkout v1.4.0\n> > > >   hack hack hack\n> > > >   git commit -m -a 'some changes which will never be seen again'\n> > > >   git checkout v1.2.0\n> > > >\n> > > > I thought the _point_ of the safety valve was not to lose those changes.\n> ...\n> > Stupid question: why can't checkout do something like this?\n> >\n> > \tif we're currently not on a branch, fail if .git/PREV\n> > \t\tdoesn't point to the same commit as .git/HEAD.\n> >\n> > \tif we're checking out a non-branch, store its SHA1 into\n> > \t\t.git/PREV.\n> \n> I would guess the problem is that this would still cause warnings even\n> if the user had since given a name (created a branch) for the commits\n> originally made to the dangling head.\n\nI think as long as we provided a special exception for a case like \"git\ncheckout -b\":\n\n\tgit checkout v1.4.0\n\thack hack hack\n\tgit commit -m -a 'some changes'\n\tgit checkout -b new-changes\n\nand also provide a way out (--force-checkout-losing-current-head) for\npeople that really know what they're doing, that should be more than\nenough to handle that sort of case.\n\nBecause, I agree, the point is to make easy what 90% of users will\nprobably do, at least on the first encounter with git--download project\nX, checkout version Y, build--and making checkouts on detached commits\nconvenient seems a lower priority.\n\n--b.\n"},{"id":"31298","messageId":"7vy7obj07k.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"20070109213117.GB25012@fieldses.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-09T22:37:35Z","receivedAt":"2007-01-09T22:37:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"J. Bruce Fields\" <bfields@fieldses.org> writes:\n\n> On Tue, Jan 09, 2007 at 01:20:27PM -0800, Junio C Hamano wrote:\n>> Jeff King <peff@peff.net> writes:\n>> \n>> > For example, with what's in next now, I can do this:\n>> >\n>> >   git checkout v1.4.0\n>> >   hack hack hack\n>> >   git commit -m -a 'some changes which will never be seen again'\n>> >   git checkout v1.2.0\n>> >\n>> > I thought the _point_ of the safety valve was not to lose those changes.\n>> \n>> Fair enough.\n>> \n>> We could always do the check upon \"git checkout\" from a detached\n>> HEAD state, whether it takes you back on some existing branch or\n>> leaves your HEAD still detached.\n>\n> Stupid question: why can't checkout do something like this?\n>\n> \tif we're currently not on a branch, fail if .git/PREV\n> \t\tdoesn't point to the same commit as .git/HEAD.\n>\n> \tif we're checking out a non-branch, store its SHA1 into\n> \t\t.git/PREV.\n\nI do not want to think about the consequences of adding more\ncruft under .git/ directory.  For example, should PREV be\nnoticed by fsck and prune?  What should various forms of\n'git-reset' do with it?  How does it interact with 'git-bisect'?\n\nBeing able to test merge or even make commits without being on a\nbranch is vastly useful.  It might or might not lead to anywhere\neven after you make a handful commits -- and I would imagine\nthat it would be very handy to be able to be lazy and not having\nto decide if it is worth a new branch.\n\nBut that may be just my imagination; I generally prefer any\nfeature that allows me to defer decision over something that\nmakes me decide early.  If Carl wants to do a patch to teach\n'git-commit' (and all other things that can create commits) not\nto do things from working in a detached HEAD, I would probably\nnot opposed to it too much, but I am fairly certain that I won't\nbe coding it myself.\n\nIt's tempting to forget about this whole \"safety\" business.\nBecause we allow \"reset --hard\" and other forms of operations\nthat can lose history if they were done while on a branch, only\ngiving the safety to \"git checkout\" feels somewhat silly.  And\nthe primary motive for detached HEAD as I understand it is for\nsightseeing, and not allowing \"reset --hard\" to jump around is\njust plain silly.\n\nThat is, after:\n\n\tgit checkout v1.4.0\n\nyou are not on any branch, and we would still allow\n\n\tgit reset --hard v1.2.0\n\nwhich is exactly the same as:\n\n\tgit checkout v1.2.0\n\nYou can still say:\n\n\tgit checkout master\n\nand we do not even check.\n\nWhich makes the \"merge-base --check-ancestry\" stuff I did last\nnight pretty much unnecessary, but that's Ok.  It will find\nother uses.\n"},{"id":"31306","messageId":"20070109233948.GC30023@spearce.org","threadId":"6193","inReplyTo":"7vy7obj07k.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-09T23:39:48Z","receivedAt":"2007-01-09T23:39:48Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> I do not want to think about the consequences of adding more\n> cruft under .git/ directory.  For example, should PREV be\n> noticed by fsck and prune?  What should various forms of\n> 'git-reset' do with it?  How does it interact with 'git-bisect'?\n\nI agree.  The reachability list for those is already starting to\nget out of control, and the rules for making sure those files are\nalways in sync with every command is getting crazy.  Didn't we just\nfix `git reset --hard` to throw away .git/MERGE_MSG?  That's been\na longstanding bug right there, and that's something that has been\nin the tree for a loooooooong time.\n \n> Being able to test merge or even make commits without being on a\n> branch is vastly useful.  It might or might not lead to anywhere\n> even after you make a handful commits -- and I would imagine\n> that it would be very handy to be able to be lazy and not having\n> to decide if it is worth a new branch.\n\nI agree.  I'm always creating and deleting `foof` because I need\nsomeplace to work real quick.  Being able to work on a detached HEAD\nwould just slightly streamline the process, especially given that\n`git checkout -b a-real-name` is readily available to move that\ndetached HEAD state into a real branch and continue on with it.\n \n> If Carl wants to do a patch to teach\n> 'git-commit' (and all other things that can create commits) not\n> to do things from working in a detached HEAD\n\nMy concern here is to hit all of the corner cases.  reset.  bisect.\nam.  rebase.  merge.  cherry-pick/revert.  Did I get all of 'em?\nI'm not sure actually.  ;-)\n\n> It's tempting to forget about this whole \"safety\" business.\n> Because we allow \"reset --hard\" and other forms of operations\n> that can lose history if they were done while on a branch, only\n> giving the safety to \"git checkout\" feels somewhat silly.\n\nBut isn't the --hard switch the safety valve here?  And lets not\nforget that reflogs are enabled by default now so even a `reset\n--hard` on a real branch isn't a total loss (its only a loss for\nuncommitted files in the working directory).\n\nBut a detached HEAD has no reflog. Which means operations that\nupdate it in a non-fastforward way would orphan work.  A subsequent\ngc/prune/repack might destroy it, unless an existing ref contains\nthat previous commit.\n\n> Which makes the \"merge-base --check-ancestry\" stuff I did last\n> night pretty much unnecessary, but that's Ok.  It will find\n> other uses.\n\nPity.  It looked like it was a good change and would be useful here\nas a safety valve.  Though based on what you said above I would\nthink we'd actually want it in both checkout and reset (--soft and\n--hard versions).\n\n-- \nShawn.\n"},{"id":"31309","messageId":"20070109234421.GD30023@spearce.org","threadId":"6193","inReplyTo":"87zm8ryiyz.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-09T23:44:21Z","receivedAt":"2007-01-09T23:44:21Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Carl Worth <cworth@cworth.org> wrote:\n> But, whatever, if allowing fragile commits is seen as important by\n> those doing the work, who am I to complain about that? I'd just ask\n> that the following not be made slow:\n> \n> \tgit checkout commit-from-beginning-of-time\n> \tgit checkout master\n> \n> Thanks to the index, and the simplicity of what \"git checkout\" means,\n> checkout has always been blisteringly fast. All the talk of doing\n> reachability analysis scares me from a performance point of view,\n> (particularly when the _interesting_ cases (to me) of checkouts to\n> non-branches never need this anyway---since no commits will be made).\n\nThe safety valve I was proposing would be only the additional time of\nrunning `git merge-base commit-from-begging-of-time master` to verify\nthe former is completely contained in the latter.  That's going to\nbe true, and is a relatively fast operation (roughly linear in time\nwith the length of the history).\n\nHowever in this case:\n\n  git checkout v1.5.0\n  git checkout v1.2.0\n\nwould take slightly longer as we'd have to verify that the HEAD\nfrom the first checkout is contained in an existing tag/ref.\nWhich it is.  Since its probably exactly equal to one of those\ndereferenced tags this may just wind up being the cost of scanning\nthe .git/packed-refs file.  You do pack your refs, don't you?\n\nIn my mind that is a small price to pay for making sure the\ncommit currently in a detached HEAD doesn't get orphaned off\ninto never-never land.\n\n-- \nShawn.\n"},{"id":"31310","messageId":"Pine.LNX.4.64.0701091539050.3594@woody.osdl.org","threadId":"6193","inReplyTo":"7vy7obj07k.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2007-01-09T23:46:32Z","receivedAt":"2007-01-09T23:46:32Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 9 Jan 2007, Junio C Hamano wrote:\n> \n> Being able to test merge or even make commits without being on a\n> branch is vastly useful.\n\nYes. I think the detached head notion is really really important. I think \nit was a mistake to not allow it initially, but hey, there were various \nhistorical reasons, and the whole thing about how branches worked was a \nbit up in the air.\n\nI would suggest a solution:\n\n - git checkout will refuse to switch AWAY from a detached head unless the \n   SHA1 of the detached head exactly matches some other branch.\n\nNot any expensive \"reachability\" cheaks. Simple and straightforward: just \nsay \"no, I will not leave this branch-less HEAD behind, because it is not \ndescribed by any other branch or tag\".\n\nSo if you do\n\n\tgit checkout v1.4.4\n\nyou'll be fine, because even though you got a detached HEAD that isn't \nattached to any branch, it still exists as a tag, so checking out \nsomething else is fine - you've not lost any state.\n\nIn contrast, if you actually start committing to that detached HEAD, you \nneed to either\n\n - use some new flag (\"git checkout --forget-old\") to explicitly say that \n   you _want_ to leave this old naked branch behind\n\n - either tag the current point or make a real branch out of it (with \n   either \"git tag <tagname>\" or \"git branch <branchname>\" respectively) \n   and then you can check out some other tag/branch after that.\n\nDoing \"reachability analysis\" is not only expensive, it's actually really \nwrong, because even if the current HEAD is _reachable_ from some other tag \nor branch, you're still going to drop that point in the development series \nunless it _exactly_ matchs it.\n\nHmm?\n\nI'd love to see the detached HEAD series move into \"master\", but I do \nthink we should make sure that people can't drop their work easily by \nmistake, and I think the above suggestion is both simple and workable.\n\nComments?\n\n\t\tLinus\n"},{"id":"31316","messageId":"7vd55nivx7.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701091539050.3594@woody.osdl.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-10T00:10:12Z","receivedAt":"2007-01-10T00:10:12Z","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 Tue, 9 Jan 2007, Junio C Hamano wrote:\n>> \n>> Being able to test merge or even make commits without being on a\n>> branch is vastly useful.\n>\n> Yes. I think the detached head notion is really really important. I think \n> it was a mistake to not allow it initially, but hey, there were various \n> historical reasons, and the whole thing about how branches worked was a \n> bit up in the air.\n>\n> I would suggest a solution:\n>\n>  - git checkout will refuse to switch AWAY from a detached head unless the \n>    SHA1 of the detached head exactly matches some other branch.\n\n... or an existing \"ref^{commit}\".\n\n> I'd love to see the detached HEAD series move into \"master\", but I do \n> think we should make sure that people can't drop their work easily by \n> mistake, and I think the above suggestion is both simple and workable.\n>\n> Comments?\n\nI agree with the \"reachability is wrong -- you would lose the\npoint in the middle\" reasoning.\n"},{"id":"31318","messageId":"20070110001822.GG30023@spearce.org","threadId":"6193","inReplyTo":"7vd55nivx7.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-10T00:18:22Z","receivedAt":"2007-01-10T00:18:22Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> Linus Torvalds <torvalds@osdl.org> writes:\n> >  - git checkout will refuse to switch AWAY from a detached head unless the \n> >    SHA1 of the detached head exactly matches some other branch.\n> \n> ... or an existing \"ref^{commit}\".\n\nI think that was implied.  ;-)\n \n> > I'd love to see the detached HEAD series move into \"master\", but I do \n> > think we should make sure that people can't drop their work easily by \n> > mistake, and I think the above suggestion is both simple and workable.\n> >\n> > Comments?\n> \n> I agree with the \"reachability is wrong -- you would lose the\n> point in the middle\" reasoning.\n\nI have no problem with that.  Forget the reachability thing entirely.\n\nMy point about reset --hard/--soft probably also needing this check\nstill stands however.\n\n-- \nShawn.\n"},{"id":"31323","messageId":"eo1bqu$hji$1@sea.gmane.org","threadId":"6193","inReplyTo":"20070109234421.GD30023@spearce.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-01-10T00:26:19Z","receivedAt":"2007-01-10T00:26:19Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Shawn O. Pearce wrote:\n\n> In my mind that is a small price to pay for making sure the\n> commit currently in a detached HEAD doesn't get orphaned off\n> into never-never land.\n\nBy the way, would detached HEAD be reflogged, and if it would\n(and certainly it would be nice to have, because protection or\nnot sh*t happens) how it would be implemented?\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"31325","messageId":"20070110003433.GH30023@spearce.org","threadId":"6193","inReplyTo":"eo1bqu$hji$1@sea.gmane.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-10T00:34:33Z","receivedAt":"2007-01-10T00:34:33Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> wrote:\n> Shawn O. Pearce wrote:\n> \n> > In my mind that is a small price to pay for making sure the\n> > commit currently in a detached HEAD doesn't get orphaned off\n> > into never-never land.\n> \n> By the way, would detached HEAD be reflogged, and if it would\n> (and certainly it would be nice to have, because protection or\n> not sh*t happens) how it would be implemented?\n\nOhhhhh.  It should reflog if .git/logs/HEAD exists, so long as\nchanges to HEAD are done via update-ref and not just by echo (as\none of Junio's versions of the feature had done).\n\nUnfortunately .git/logs/HEAD wouldn't be created by default as its\nnot under refs/heads or refs/remotes.  Though it could be made to be\non by default, in which case it would only log changes while HEAD\nis detached.  If HEAD is attached to a branch then .git/logs/HEAD\nwouldn't be appended to (or even created), while the branch's own\nlog is still appended to.\n\n-- \nShawn.\n"},{"id":"31329","messageId":"87vejfya8o.wl%cworth@cworth.org","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701091539050.3594@woody.osdl.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2007-01-10T00:51:51Z","receivedAt":"2007-01-10T00:51:51Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Tue, 9 Jan 2007 15:46:32 -0800 (PST), Linus Torvalds wrote:\n>  - git checkout will refuse to switch AWAY from a detached head unless the\n>    SHA1 of the detached head exactly matches some other branch.\n\nThat's a nice cheap check.\n\nBut I've also been liking the idea of using this \"detached head\" stuff\nfor git-bisect, (instead of making it carry around its own temporary\nbranch). One long-standing user-interface bug with git-bisect is that\noften the user doesn't know a priori what the last-known-good state is\nto initially mark with \"git bisect good\". So I've long wanted a good\nclean way to explore fairly arbitrarily in order to get git-bisect\njump started.\n\nWhen I first started using git a year ago, what was suggested to me\nfor this, (and what I've used ever since), is:\n\n\tgit checkout -b tmp some-guess-at-a-good-commit\n\t# check it\n\tgit reset --hard next-guess-at-a-good-commit\n\nObviously, that works but fails the \"good clean\" test for me. Half\nthe time it fails for me and I have to \"git branch -D tmp\" first. Then\nthere's the fact that I want very new users to learn git-bisect---I\nwant random users that have hit bugs in my software to bisect those\nbugs for me---and many of these users will have never seen git\nbefore. I don't think it's kind to start their education with \"git\nreset --hard\". I'd like to instead teach them something as simple as:\n\n\tgit checkout some-guess-at-a-good-commit\n\t# check it\n\tgit checkout next-guess-at-a-good-commit\n\nI wouldn't want these uses to trigger warnings just because the user\nis checking out arbitrary revisions from the logs rather than using\ntags and branches.\n\nBut, yes, as soon as the user actually _commits_ in the detached\nstate, then a check for \"HEAD == some branch\" should be just fine for\nchecking a checkout to somewhere else.\n\n-Carl\n"},{"id":"31330","messageId":"Pine.LNX.4.64.0701091649510.3594@woody.osdl.org","threadId":"6193","inReplyTo":"20070110001822.GG30023@spearce.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2007-01-10T00:54:02Z","receivedAt":"2007-01-10T00:54:02Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 9 Jan 2007, Shawn O. Pearce wrote:\n> \n> My point about reset --hard/--soft probably also needing this check\n> still stands however.\n\nWell, I disagree, if only because the whole _point_ of \"git reset\" is to \nleave some point behind. I use it all the time (well, often enough) as a \n\"undo\" operation, and it's fundamentally different than \"git checkout\" at \nleast to my worldview.\n\nWhen you do \"git reset\" you _expect_ state to be reset/dropped. But when \njust switching between branches, you don't.\n\n(I realize that \"git checkout filename/goes/here\" has kind of mixed up \n\"git reset\" and \"git checkout\". The \"git checkout filename\" syntax \nbasically resets the filename, and that confuses things a bit. So in the \nabove, I really do talk about just \"checking out a _commit_\" and do a \nstate switch, not a \"check out a filename\" and overwrite the old contents \nof that file).\n\n\t\tLinus\n"},{"id":"31336","messageId":"20070110010312.GA25265@fieldses.org","threadId":"6193","inReplyTo":"20070110003433.GH30023@spearce.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2007-01-10T01:03:12Z","receivedAt":"2007-01-10T01:03:12Z","isPatch":true,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Tue, Jan 09, 2007 at 07:34:33PM -0500, Shawn O. Pearce wrote:\n> Unfortunately .git/logs/HEAD wouldn't be created by default as its\n> not under refs/heads or refs/remotes.  Though it could be made to be\n> on by default, in which case it would only log changes while HEAD\n> is detached.  If HEAD is attached to a branch then .git/logs/HEAD\n> wouldn't be appended to (or even created), while the branch's own\n> log is still appended to.\n\nThat would also provide all the needed \"safety valve\" on git checkout,\nwouldn't it?  Since you could always recover from\n\n\tgit checkout v1.4.0\n\tgit commit -m -a 'some changes'\n\tgit checkout 41.2.0\n\nby looking back through the reflog for HEAD.\n\n--b.\n"},{"id":"31340","messageId":"20070110010725.GI30023@spearce.org","threadId":"6193","inReplyTo":"20070110010312.GA25265@fieldses.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-10T01:07:25Z","receivedAt":"2007-01-10T01:07:25Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"\"J. Bruce Fields\" <bfields@fieldses.org> wrote:\n> On Tue, Jan 09, 2007 at 07:34:33PM -0500, Shawn O. Pearce wrote:\n> > Unfortunately .git/logs/HEAD wouldn't be created by default as its\n> > not under refs/heads or refs/remotes.  Though it could be made to be\n> > on by default, in which case it would only log changes while HEAD\n> > is detached.  If HEAD is attached to a branch then .git/logs/HEAD\n> > wouldn't be appended to (or even created), while the branch's own\n> > log is still appended to.\n> \n> That would also provide all the needed \"safety valve\" on git checkout,\n> wouldn't it?  Since you could always recover from\n> \n> \tgit checkout v1.4.0\n> \tgit commit -m -a 'some changes'\n> \tgit checkout 41.2.0\n> \n> by looking back through the reflog for HEAD.\n\nYes.  Then that removes my desire for a safety check in reset,\n(which Linus doesn't want) thereby making both of us happy.\n\n-- \nShawn.\n"},{"id":"31343","messageId":"Pine.LNX.4.64.0701092014390.4964@xanadu.home","threadId":"6193","inReplyTo":"20070110003433.GH30023@spearce.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-10T01:15:58Z","receivedAt":"2007-01-10T01:15:58Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Tue, 9 Jan 2007, Shawn O. Pearce wrote:\n\n> Jakub Narebski <jnareb@gmail.com> wrote:\n> > Shawn O. Pearce wrote:\n> > \n> > > In my mind that is a small price to pay for making sure the\n> > > commit currently in a detached HEAD doesn't get orphaned off\n> > > into never-never land.\n> > \n> > By the way, would detached HEAD be reflogged, and if it would\n> > (and certainly it would be nice to have, because protection or\n> > not sh*t happens) how it would be implemented?\n> \n> Ohhhhh.  It should reflog if .git/logs/HEAD exists, so long as\n> changes to HEAD are done via update-ref and not just by echo (as\n> one of Junio's versions of the feature had done).\n> \n> Unfortunately .git/logs/HEAD wouldn't be created by default as its\n> not under refs/heads or refs/remotes.  Though it could be made to be\n> on by default, in which case it would only log changes while HEAD\n> is detached.  If HEAD is attached to a branch then .git/logs/HEAD\n> wouldn't be appended to (or even created), while the branch's own\n> log is still appended to.\n\nIs this worth the trouble and complexity?  After all detached heads are \nnot meant to be used for serious development.\n\n\nNicolas\n"},{"id":"31345","messageId":"7vwt3vfzd1.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701092014390.4964@xanadu.home","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-10T01:24:10Z","receivedAt":"2007-01-10T01:24:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nicolas Pitre <nico@cam.org> writes:\n\n>> Unfortunately .git/logs/HEAD wouldn't be created by default as its\n>> not under refs/heads or refs/remotes.  Though it could be made to be\n>> on by default, in which case it would only log changes while HEAD\n>> is detached.  If HEAD is attached to a branch then .git/logs/HEAD\n>> wouldn't be appended to (or even created), while the branch's own\n>> log is still appended to.\n>\n> Is this worth the trouble and complexity?  After all detached heads are \n> not meant to be used for serious development.\n\nI agree.\n"},{"id":"31347","messageId":"200701100237.40059.jnareb@gmail.com","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701092014390.4964@xanadu.home","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-01-10T01:37:39Z","receivedAt":"2007-01-10T01:37:39Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Nicolas Pitre wrote:\n> On Tue, 9 Jan 2007, Shawn O. Pearce wrote:\n> \n>> Jakub Narebski <jnareb@gmail.com> wrote:\n>>> Shawn O. Pearce wrote:\n>>> \n>>>> In my mind that is a small price to pay for making sure the\n>>>> commit currently in a detached HEAD doesn't get orphaned off\n>>>> into never-never land.\n>>> \n>>> By the way, would detached HEAD be reflogged, and if it would\n>>> (and certainly it would be nice to have, because protection or\n>>> not sh*t happens) how it would be implemented?\n>> \n>> Ohhhhh.  It should reflog if .git/logs/HEAD exists, so long as\n>> changes to HEAD are done via update-ref and not just by echo (as\n>> one of Junio's versions of the feature had done).\n>> \n>> Unfortunately .git/logs/HEAD wouldn't be created by default as its\n>> not under refs/heads or refs/remotes.  Though it could be made to be\n>> on by default, in which case it would only log changes while HEAD\n>> is detached.  If HEAD is attached to a branch then .git/logs/HEAD\n>> wouldn't be appended to (or even created), while the branch's own\n>> log is still appended to.\n> \n> Is this worth the trouble and complexity?  After all detached heads\n> are not meant to be used for serious development.\n\nI think reflogging detached HEAD is easier than adding safety checks\neither on commit (no commits on top of detached HEAD), or on checkouts\nand stuff (try not to loose unless forced chain of commits built on top\nof detached HEAD).\n-- \nJakub Narebski\nPoland\n"},{"id":"31348","messageId":"20070110014000.GA30765@spearce.org","threadId":"6193","inReplyTo":"7vwt3vfzd1.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-10T01:40:00Z","receivedAt":"2007-01-10T01:40:00Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> Nicolas Pitre <nico@cam.org> writes:\n> \n> >> Unfortunately .git/logs/HEAD wouldn't be created by default as its\n> >> not under refs/heads or refs/remotes.  Though it could be made to be\n> >> on by default, in which case it would only log changes while HEAD\n> >> is detached.  If HEAD is attached to a branch then .git/logs/HEAD\n> >> wouldn't be appended to (or even created), while the branch's own\n> >> log is still appended to.\n> >\n> > Is this worth the trouble and complexity?  After all detached heads are \n> > not meant to be used for serious development.\n> \n> I agree.\n\n  git checkout v1.4.0\n  # dang, need some local fix\n  git commit -m tmpfix -a\n  git reset --hard v1.2.0\n  git reset --hard v1.3.0\n  # dang, need that local again fix - where is it?\n\nIt ain't in ORIG_HEAD.  Its now only findable by\nfsck-objects/lost-found.  But if you reflog a detached\nHEAD its there as HEAD@{2}.\n\nMaybe its not really worth it.  But it almost seems like it would\ncome free if we always use update-ref like we're supposed to...\n\n-- \nShawn.\n"},{"id":"31349","messageId":"Pine.LNX.4.64.0701092045090.4964@xanadu.home","threadId":"6193","inReplyTo":"20070110014000.GA30765@spearce.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-10T01:54:14Z","receivedAt":"2007-01-10T01:54:14Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Tue, 9 Jan 2007, Shawn O. Pearce wrote:\n\n> Junio C Hamano <junkio@cox.net> wrote:\n> > Nicolas Pitre <nico@cam.org> writes:\n> > \n> > >> Unfortunately .git/logs/HEAD wouldn't be created by default as its\n> > >> not under refs/heads or refs/remotes.  Though it could be made to be\n> > >> on by default, in which case it would only log changes while HEAD\n> > >> is detached.  If HEAD is attached to a branch then .git/logs/HEAD\n> > >> wouldn't be appended to (or even created), while the branch's own\n> > >> log is still appended to.\n> > >\n> > > Is this worth the trouble and complexity?  After all detached heads are \n> > > not meant to be used for serious development.\n> > \n> > I agree.\n> \n>   git checkout v1.4.0\n>   # dang, need some local fix\n>   git commit -m tmpfix -a\n>   git reset --hard v1.2.0\n>   git reset --hard v1.3.0\n>   # dang, need that local again fix - where is it?\n\n    cd /\n    ls\n    # wow lots of files\n    rm -rf .\n    # dang dunk down\n\nSo just don't use git-reset but create a branch to preserve that local \nchange instead.\n\n> It ain't in ORIG_HEAD.  Its now only findable by\n> fsck-objects/lost-found.\n\nWhich is good enough in that circumstance IMHO.  We cannot always try to \nprevent people from shooting in their foot if they really want to.\n\n> But if you reflog a detached\n> HEAD its there as HEAD@{2}.\n\nBut when your head is not detached anymore then HEAD@{2} changes \nmeaning and that is rather not good.\n\n\nNicolas\n"},{"id":"31354","messageId":"20070110022829.GB30765@spearce.org","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701092045090.4964@xanadu.home","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-10T02:28:30Z","receivedAt":"2007-01-10T02:28:30Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Nicolas Pitre <nico@cam.org> wrote:\n> On Tue, 9 Jan 2007, Shawn O. Pearce wrote:\n> > But if you reflog a detached\n> > HEAD its there as HEAD@{2}.\n> \n> But when your head is not detached anymore then HEAD@{2} changes \n> meaning and that is rather not good.\n\nAh, yes, apparently my own head is detached and not clearly thinking.\nThanks.  That UI is not so good.\n\n-- \nShawn.\n"},{"id":"31368","messageId":"7vodp7e2c4.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701091539050.3594@woody.osdl.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-10T08:02:51Z","receivedAt":"2007-01-10T08:02:51Z","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> I'd love to see the detached HEAD series move into \"master\", but I do \n> think we should make sure that people can't drop their work easily by \n> mistake, and I think the above suggestion is both simple and workable.\n\nI've done this, also added one fix and merged the topic to\n\"next\".  I am hoping I can move this to \"master\" by the weekend.\n"},{"id":"31372","messageId":"200701100904.32077.andyparkins@gmail.com","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701091539050.3594@woody.osdl.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-01-10T09:04:29Z","receivedAt":"2007-01-10T09:04:29Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Tuesday 2007 January 09 23:46, Linus Torvalds wrote:\n\n> I would suggest a solution:\n>\n>  - git checkout will refuse to switch AWAY from a detached head unless the\n>    SHA1 of the detached head exactly matches some other branch.\n\nIf the detached HEAD matches another branch what did we need a detached HEAD \nfor in the first place?\n\nSeems that this check will in practice always be true.  A detached HEAD by \ndefinition doesn't match some other branch.\n\nHave I misunderstood?  Perhaps you meant the detached HEAD is /on/ some other \nbranch?\n\n\n\nAndy\n\n-- \nDr Andy Parkins, M Eng (hons), MIEE\nandyparkins@gmail.com\n"},{"id":"31373","messageId":"20070110090548.GE30765@spearce.org","threadId":"6193","inReplyTo":"200701100904.32077.andyparkins@gmail.com","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-10T09:05:48Z","receivedAt":"2007-01-10T09:05:48Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Andy Parkins <andyparkins@gmail.com> wrote:\n> On Tuesday 2007 January 09 23:46, Linus Torvalds wrote:\n> \n> > I would suggest a solution:\n> >\n> >  - git checkout will refuse to switch AWAY from a detached head unless the\n> >    SHA1 of the detached head exactly matches some other branch.\n> \n> If the detached HEAD matches another branch what did we need a detached HEAD \n> for in the first place?\n\nTags.  Previously you could not checkout a tag without first making\na branch from it.  Now you can.\n\n-- \nShawn.\n"},{"id":"31374","messageId":"45A4AD08.1020002@op5.se","threadId":"6193","inReplyTo":"87zm8ryiyz.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2007-01-10T09:08:24Z","receivedAt":"2007-01-10T09:08:24Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Carl Worth wrote:\n> \n> Frankly, I don't understand why so much effort is being put toward\n> allowing these \"fragile commits\" to be made in the first place. Why\n> not require users to name the branch before creating any commits, just\n> as has always been the case?\n> \n\nAgreed. Possibly, we could have commit (or commit-tree) issue a big fat \nwarning along the lines of:\n\n*** WARNING ***\nYou are about to create a commit on a detached HEAD.\nIt is recommended that you run \"git branch <name>\" to create a branch to \ncommit to first. If you don't, you might lose this commit further on.\n*** WARNING ***\n\nwhich could be suppressed by a \"--silently-ignore-detached-head\" in case \nscripts (securely) use this behaviour. Since committing on detached \nheads really should be a very rare case I don't think many people will \nfind this terribly annoying.\n\n> To me, the only real advantage to the new \"detached head\" stuff is\n> simply making it easier to checkout previous state without having to\n> name a new branch precisely _because_ the user has not intent to\n> commit anything. If the user is going to commit something, then the\n> user should be able to come up with a name for the branch.\n> \n\nIndeed and as I've said before, *all* developers have \"silly-names\" they \nuse for temporary stuff (foo, bar, frotz, nitfol, blaj, fnurg, sdf, ...) \nso it's not like we'll put a heavy burden on peoples imagination.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"31375","messageId":"7vbql7cjk8.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"200701100904.32077.andyparkins@gmail.com","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-10T09:33:43Z","receivedAt":"2007-01-10T09:33:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andy Parkins <andyparkins@gmail.com> writes:\n\n> On Tuesday 2007 January 09 23:46, Linus Torvalds wrote:\n>\n>> I would suggest a solution:\n>>\n>>  - git checkout will refuse to switch AWAY from a detached head unless the\n>>    SHA1 of the detached head exactly matches some other branch.\n>\n> If the detached HEAD matches another branch what did we need a detached HEAD \n> for in the first place?\n>\n> Seems that this check will in practice always be true.  A detached HEAD by \n> definition doesn't match some other branch.\n\nYou are forgetting this:\n\n\tgit checkout v1.0.0\n"},{"id":"31376","messageId":"7v3b6jcj8g.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"87zm8ryiyz.wl%cworth@cworth.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-10T09:40:47Z","receivedAt":"2007-01-10T09:40:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n> Frankly, I don't understand why so much effort is being put toward\n> allowing these \"fragile commits\" to be made in the first place. Why\n> not require users to name the branch before creating any commits, just\n> as has always been the case?\n\nThen we would not be talking about detached HEAD at all.  Why\nnot require users to name the branch if they want to check out\nwhat they should not be able to in the first place?\n\nConvenience.\n\nSome features of git are about being convenient by allowing you\nto defer the decision.  You can start mucking with the working\ntree files without knowing where it leads to and then from that\npoint with the dirty working tree state decide to fork what you\nhave started using \"checkout -b newbranch\".  Even though you may\nhave many dirty files in the working tree, you can selectively\nupdate index (especially with the patch subcommand of the\ninteractive git-add) to prepare for commit -- you do not choose\nwhat to edit, but you defer the decision of what to include in\nthe commit.\n"},{"id":"31377","messageId":"7vwt3vb4ev.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"45A4AD08.1020002@op5.se","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-10T09:46:16Z","receivedAt":"2007-01-10T09:46:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andreas Ericsson <ae@op5.se> writes:\n\n> ... Since committing on\n> detached heads really should be a very rare case I don't think many\n> people will find this terribly annoying.\n\nQuite the contrary, I would imagine it would be quite natural to\ndo throw-away commits and merges on detached head while\nbisecting the history (e.g. commit small fixup to make it\ncompile and then mark the result for bisection to hunt for real\nbugs that are hidden by silly compilation problems).  \n\nThe check suggested by Linus would be safe enough for people to\nwhom it is \"very rare\" for their workflow to commitg on detached\nHEAD anyway, so you should not burden \"git commit\" with such an\nannoying warning messages.\n"},{"id":"31378","messageId":"200701101010.46269.andyparkins@gmail.com","threadId":"6193","inReplyTo":"7vbql7cjk8.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-01-10T10:10:44Z","receivedAt":"2007-01-10T10:10:44Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Wednesday 2007 January 10 09:33, Junio C Hamano wrote:\n\n> > If the detached HEAD matches another branch what did we need a detached\n> > HEAD for in the first place?\n> >\n> > Seems that this check will in practice always be true.  A detached HEAD\n> > by definition doesn't match some other branch.\n>\n> You are forgetting this:\n>\n> \tgit checkout v1.0.0\n\nNo I'm not.  Linus's suggested check is \"git checkout will refuse to switch \nAWAY from a detached head unless the SHA1 of the detached head exactly \nmatches some other branch.\"\n\nMy question is what use is that?  In exactly the situation you describe HEAD \ndoesn't match a branch.\n\n  git checkout v1.0.0\n\nHEAD after that doesn't match any branch so the next \"git checkout\" will find \nthat HEAD doesn't match any branch and will refuse to switch away.  Why?  A \ncheckout in this case isn't dangerous at all.\n\nOf course I could still be misunderstanding.  If Linus meant \"refuse to switch \nAWAY from a detached HEAD unless the hash of the detached head exactly \nmatches some other ref\", I would be less confused.\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIEE\nandyparkins@gmail.com\n"},{"id":"31379","messageId":"20070110102516.GF30765@spearce.org","threadId":"6193","inReplyTo":"200701101010.46269.andyparkins@gmail.com","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-10T10:25:16Z","receivedAt":"2007-01-10T10:25:16Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Andy Parkins <andyparkins@gmail.com> wrote:\n> Of course I could still be misunderstanding.  If Linus meant \"refuse to switch \n> AWAY from a detached HEAD unless the hash of the detached head exactly \n> matches some other ref\", I would be less confused.\n\nI believe that's what Linus meant.  As otherwise you are right,\nit doesn't make much sense.  :-)\n\n-- \nShawn.\n"},{"id":"31394","messageId":"20070110140432.GA20868@coredump.intra.peff.net","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701091539050.3594@woody.osdl.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-01-10T14:04:32Z","receivedAt":"2007-01-10T14:04:32Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Jan 09, 2007 at 03:46:32PM -0800, Linus Torvalds wrote:\n\n> I would suggest a solution:\n> \n>  - git checkout will refuse to switch AWAY from a detached head unless the \n>    SHA1 of the detached head exactly matches some other branch.\n\nWhat about\n\n  git checkout HEAD~20\n\nI agree that checking out tags will be more common, but it feels like we\nare discouraging this usage by presenting spurious warning messages.\n\n-Peff\n"},{"id":"31398","messageId":"7vsleic0t7.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"200701101010.46269.andyparkins@gmail.com","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-10T16:18:44Z","receivedAt":"2007-01-10T16:18:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andy Parkins <andyparkins@gmail.com> writes:\n\n> No I'm not.  Linus's suggested check is \"git checkout will refuse to switch \n> AWAY from a detached head unless the SHA1 of the detached head exactly \n> matches some other branch.\"\n>\n> My question is what use is that?  In exactly the situation you describe HEAD \n> doesn't match a branch.\n>\n>   git checkout v1.0.0\n\nYou are taking it too literally.  Read what Linus wrote again.\n\n    So if you do\n\n            git checkout v1.4.4\n\n    you'll be fine, because even though you got a detached HEAD that isn't \n    attached to any branch, it still exists as a tag, so checking out \n    something else is fine - you've not lost any state.\n\nThe version in \"next\" does that, in a quite straightforward way:\n\n\tgit show-ref -d -s | grep \"$old\" || { barf }\n\nwhich should be fairly fast in a repository with packed-pruned\nrefs.\n"},{"id":"31399","messageId":"Pine.LNX.4.64.0701101041210.20138@iabervon.org","threadId":"6193","inReplyTo":"7vwt3vb4ev.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2007-01-10T16:30:23Z","receivedAt":"2007-01-10T16:30:23Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Wed, 10 Jan 2007, Junio C Hamano wrote:\n\n> Andreas Ericsson <ae@op5.se> writes:\n> \n> > ... Since committing on\n> > detached heads really should be a very rare case I don't think many\n> > people will find this terribly annoying.\n> \n> Quite the contrary, I would imagine it would be quite natural to\n> do throw-away commits and merges on detached head while\n> bisecting the history (e.g. commit small fixup to make it\n> compile and then mark the result for bisection to hunt for real\n> bugs that are hidden by silly compilation problems).  \n\nI don't think this would actually work. If you commit your build fix, and \nthen mark the result as bad, won't bisect skew its choices due to \nsuspecting that your build fix is the real bug?\n\nI'd think that, if you make changes while bisecting, you probably want to \nleave those changes uncommitted, and merge or discard them when testing \nother commits.\n\nIf anything, I'd think you'd want a rather different sort of commit \nmechanism than the usual commit, which says, \"whenever you consider commit \n{sha1-from-real-history}, use {tree-with-local-changes} instead of \n{tree-in-real-commit}.\" Or, more generally, \"in order to get the trees \nI want to actually use, this patch (git diff HEAD) needs to be applied to \nevery commit in some portion of the history including, at least, \nget_sha1(HEAD)\".\n\nI'm not seeing any actual benefit to causing the history to contain a \ndead-end fork off of an antique commit, and then throwing this away. And \ncommitting your change so that it won't get lost, with the intention of \nlosing it in a little while, doesn't seem to make any sense, either.\n\n(Of course, it also makes sense to do merges, but again, you probably want \nto create and temporarily use the working tree resulting from the merge, \nnot create the commit.)\n\nI think that the workflow that uses regular commits with a detached HEAD \nis this: do a series of commits representing real work on top of a remote \nbranch or a tag, and decide later (once you've tested the results for \nworthiness) whether to turn this into a topic branch or throw it away.\n\nBut I don't think this is a good match for detached HEAD, because you may \nwant to do exactly the same thing, but start with a regular local head. I \nthink the right thing to do is something like \"git checkout --anon\", which \nputs you on a new branch with no name, which will evaporate if you leave \nit (as per \"git branch -d\"; you need to force it if it isn't fully \nmerged).\n\nSo I think the feature which lets you make commits without being on a \nbranch from refs/heads is actually a different feature from \"detached \nHEAD\", which only shares the aspect that \"git branch\" has no line with a \n\"*\", because there is no name for what HEAD points to.\n\n(I'd implement \"anonymous branch\" by putting you on refs/heads/.anon, and \nadding rules for this situation to for_each_ref and update_ref; but that's \nan implementation detail, and shouldn't affect the intended semantics of \nthe feature.)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"31426","messageId":"7vslei764u.fsf@assigned-by-dhcp.cox.net","threadId":"6193","inReplyTo":"20070110140432.GA20868@coredump.intra.peff.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-11T00:34:57Z","receivedAt":"2007-01-11T00:34:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Tue, Jan 09, 2007 at 03:46:32PM -0800, Linus Torvalds wrote:\n>\n>> I would suggest a solution:\n>> \n>>  - git checkout will refuse to switch AWAY from a detached head unless the \n>>    SHA1 of the detached head exactly matches some other branch.\n>\n> What about\n>\n>   git checkout HEAD~20\n>\n> I agree that checking out tags will be more common, but it feels like we\n> are discouraging this usage by presenting spurious warning messages.\n\nOnce the user knows what HEAD~20 means, I think it is safe to\nassume that the user knows what the branches are.\n\n\"git checkout master\" will barf and suggests the user possible\ncommon exits; \"checkout -f\" if there is nothing of value,\n\"checkout -b <branch>\" or if they want to build on the current\nstate.\n\nAnd once the user who knows what the branches are sees such, and\nespecially with the help from $PS1 hack of bash-completion in\ncontrib/ section, the user will learn to do \"checkout -f\" after\nwandering around for sightseeing on a detached HEAD, and at that\npoint the annoying error message will not be even seen.\n"},{"id":"31429","messageId":"20070111043101.GB29214@fieldses.org","threadId":"6193","inReplyTo":"7vslei764u.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2007-01-11T04:31:01Z","receivedAt":"2007-01-11T04:31:01Z","isPatch":true,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Wed, Jan 10, 2007 at 04:34:57PM -0800, Junio C Hamano wrote:\n> Jeff King <peff@peff.net> writes:\n> \n> > On Tue, Jan 09, 2007 at 03:46:32PM -0800, Linus Torvalds wrote:\n> >\n> >> I would suggest a solution:\n> >> \n> >>  - git checkout will refuse to switch AWAY from a detached head unless the \n> >>    SHA1 of the detached head exactly matches some other branch.\n> >\n> > What about\n> >\n> >   git checkout HEAD~20\n> >\n> > I agree that checking out tags will be more common, but it feels like we\n> > are discouraging this usage by presenting spurious warning messages.\n> \n> Once the user knows what HEAD~20 means, I think it is safe to\n> assume that the user knows what the branches are.\n\nI'm interested of course in making life easy for project admins when\nthey need to tell testers how to get code to test out of git.  It'll be\nnice to able to say:\n\n\t\"Install git, then run\n\tgit clone git://ourproject.com/ourproject.git\n\tcd ourproject\n\tgit checkout <version you want>\n\t\"\n\nInstead of having to say\n\n\t\"Install git, then run\n\tgit clone git://ourproject.com/ourproject.git\n\tcd ourproject\n\tgit checkout -b FOO <version you want>\n\n\tThen if you later need to check out another version, run\n\tgit reset --hard <other version>\n\t\"\n\nI suppose <version you want> will typically be either some tagged\nrelease or the latest head.  But it's not that farfetched to imagine\nasking someone to test version 01997b4....\n\n> \"git checkout master\" will barf and suggests the user possible\n> common exits; \"checkout -f\" if there is nothing of value,\n> \"checkout -b <branch>\" or if they want to build on the current\n> state.\n\nThat should make it easy enough, though, I guess.\n\n--b.\n"},{"id":"31449","messageId":"45A60736.4050503@op5.se","threadId":"6193","inReplyTo":"Pine.LNX.4.64.0701101041210.20138@iabervon.org","subject":"Re: [PATCH] Detached HEAD (experimental)","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2007-01-11T09:45:26Z","receivedAt":"2007-01-11T09:45:26Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Daniel Barkalow wrote:\n> On Wed, 10 Jan 2007, Junio C Hamano wrote:\n> \n>> Andreas Ericsson <ae@op5.se> writes:\n>>\n>>> ... Since committing on\n>>> detached heads really should be a very rare case I don't think many\n>>> people will find this terribly annoying.\n>> Quite the contrary, I would imagine it would be quite natural to\n>> do throw-away commits and merges on detached head while\n>> bisecting the history (e.g. commit small fixup to make it\n>> compile and then mark the result for bisection to hunt for real\n>> bugs that are hidden by silly compilation problems).  \n> \n> I don't think this would actually work. If you commit your build fix, and \n> then mark the result as bad, won't bisect skew its choices due to \n> suspecting that your build fix is the real bug?\n> \n> I'd think that, if you make changes while bisecting, you probably want to \n> leave those changes uncommitted, and merge or discard them when testing \n> other commits.\n> \n> If anything, I'd think you'd want a rather different sort of commit \n> mechanism than the usual commit, which says, \"whenever you consider commit \n> {sha1-from-real-history}, use {tree-with-local-changes} instead of \n> {tree-in-real-commit}.\" Or, more generally, \"in order to get the trees \n> I want to actually use, this patch (git diff HEAD) needs to be applied to \n> every commit in some portion of the history including, at least, \n> get_sha1(HEAD)\".\n> \n> I'm not seeing any actual benefit to causing the history to contain a \n> dead-end fork off of an antique commit, and then throwing this away. And \n> committing your change so that it won't get lost, with the intention of \n> losing it in a little while, doesn't seem to make any sense, either.\n> \n\nSame here. I'd imagine temporary build-fixes to live as a patch-file \ngenerated by\n\n\tgit diff > build-fixes.diff\n\nafter having hacked on the tree. There's no sane way of inserting \ncommits into the middle of the DAG, so committing on something that \nisn't a branch with the intention of losing it is just plain weird.\n\n\n> (Of course, it also makes sense to do merges, but again, you probably want \n> to create and temporarily use the working tree resulting from the merge, \n> not create the commit.)\n> \n\nYes. I'd imagine \"git merge --no-commit\" could be used for this, to \nmerge things only in the working directory.\n\n\n> I think that the workflow that uses regular commits with a detached HEAD \n> is this: do a series of commits representing real work on top of a remote \n> branch or a tag, and decide later (once you've tested the results for \n> worthiness) whether to turn this into a topic branch or throw it away.\n> \n\nPerhaps, but this is also a bit weird, as you would normally hack things \nup to fit on top of some already existing branch, so then you'd detach \nthe head but point it to something that already has a branch-name \nassociated with it.\n\nOtoh, I could imagine this would be sort of nifty for applying bugfixes \non top of old tags, so perhaps it's not so weird after all. Then you'd \nprobably want to create a new tag before releasing the bugfixed version, \nso Linus suggestion makes sense in this case (assuming it doesn't fsck \nup the bisect case, ofc).\n\n\n> But I don't think this is a good match for detached HEAD, because you may \n> want to do exactly the same thing, but start with a regular local head. I \n> think the right thing to do is something like \"git checkout --anon\", which \n> puts you on a new branch with no name, which will evaporate if you leave \n> it (as per \"git branch -d\"; you need to force it if it isn't fully \n> merged).\n> \n\n\nYes. I'd imagine \"git merge --no-commit\" could be used for this, to \nmerge things only in the working directory. We could easily create a \nhack for this by doing a \"git reset --mixed HEAD^1\" after the merge is \ncomplete.\n\n> So I think the feature which lets you make commits without being on a \n> branch from refs/heads is actually a different feature from \"detached \n> HEAD\", which only shares the aspect that \"git branch\" has no line with a \n> \"*\", because there is no name for what HEAD points to.\n> \n\n\nAgreed. They really are two completely different things. I see no harm \nin splitting them up codewise. Bisect could start working without its \nprotected branch straight away, but commits (and merges) to detached \nheads wouldn't work at all. Then we can see what use people put this to \nand what walls they run into and make the feature accordingly.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"}]}