* [PATCH] Proof-of-concept patch to remember what the detached HEAD was @ 2009-10-14 4:44 Daniel Barkalow 2009-10-14 5:07 ` Junio C Hamano ` (3 more replies) 0 siblings, 4 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-14 4:44 UTC (permalink / raw) To: Junio C Hamano; +Cc: git When detaching HEAD (or "browsing history"), the user has specified the commit with some "extended SHA1" which is not a local branch. Exactly what that string was is likely to be useful to the user later. Also, we can detect the user putting work into the history for the first time (such that it is no longer going to be protected as uncommitted changes in the working tree) without a branch to hold it by seeing that there is such a description for the current state before the commit. (Afterwards, the description should be dropped; it doesn't make sense to tell the user they checked out "origin/master" or "d199fb7" when they've now diverged from that remote branch with local changes or made a different commit.) The upshot of the messages should be: $ git checkout origin/master Since you can't actually change "origin/master" yourself, you'll just be sightseeing unless you create a local branch to hold new local work. $ git branch * (not a local branch, but "origin/master") $ git commit You've been sightseeing "origin/master". The commit can't change that value, so your commit isn't held in any branch. If you want to create a branch to hold it, here's how. "git checkout origin/master" should be similar in complexity to "svn checkout -r 8655"; the difference is that svn won't let you commit then and git will but you'll need to understand the implications if you do so. If you don't commit (because you don't want to make any changes, because you don't think it would be possible, or because you don't want to worry about what would happen), there's no meaningful difference, and you don't need to be told. The messages have to be improved and made more useful. The effects of "git checkout HEAD", "git checkout origin/master; git checkout HEAD^", and "git checkout origin/master; git reset --hard origin/next" aren't handled quite right; none of them keep a description, but there should always be some description of a detached HEAD unless the user has made a commit (and therefore gotten the message about making a local branch to put it on). --- branch.c | 13 +++++++++++++ branch.h | 6 ++++++ builtin-branch.c | 13 ++++++++++++- builtin-checkout.c | 8 +++++++- builtin-commit.c | 10 +++++++++- t/t3203-branch-output.sh | 2 +- t/t7201-co.sh | 6 ++---- 7 files changed, 50 insertions(+), 8 deletions(-) diff --git a/branch.c b/branch.c index 05ef3f5..2c5b6d3 100644 --- a/branch.c +++ b/branch.c @@ -194,6 +194,18 @@ void create_branch(const char *head, free(real_ref); } +char *get_detached_head_string(void) +{ + char *filename = git_path("DETACH_NAME"); + struct stat st; + if (stat(filename, &st) || !S_ISREG(st.st_mode)) + return NULL; + struct strbuf buf = STRBUF_INIT; + strbuf_read_file(&buf, filename, st.st_size); + strbuf_trim(&buf); + return strbuf_detach(&buf, 0); +} + void remove_branch_state(void) { unlink(git_path("MERGE_HEAD")); @@ -201,4 +213,5 @@ void remove_branch_state(void) unlink(git_path("MERGE_MSG")); unlink(git_path("MERGE_MODE")); unlink(git_path("SQUASH_MSG")); + unlink(git_path("DETACH_NAME")); } diff --git a/branch.h b/branch.h index eed817a..0a30c3a 100644 --- a/branch.h +++ b/branch.h @@ -22,6 +22,12 @@ void create_branch(const char *head, const char *name, const char *start_name, void remove_branch_state(void); /* + * Returns the string used when detaching HEAD, or NULL if HEAD is not + * detached. + */ +char *get_detached_head_string(void); + +/* * Configure local branch "local" to merge remote branch "remote" * taken from origin "origin". */ diff --git a/builtin-branch.c b/builtin-branch.c index 9f57992..9ce4127 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -425,7 +425,18 @@ static void show_detached(struct ref_list *ref_list) if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) { struct ref_item item; - item.name = xstrdup("(no branch)"); + char *literal = get_detached_head_string(); + struct stat st; + if (literal) { + struct strbuf buf = STRBUF_INIT; + strbuf_addstr(&buf, "(no branch, as \""); + strbuf_addstr(&buf, literal); + strbuf_addstr(&buf, "\")"); + free(literal); + item.name = strbuf_detach(&buf, 0); + } else { + item.name = xstrdup("(no branch)"); + } item.len = strlen(item.name); item.kind = REF_LOCAL_BRANCH; item.dest = NULL; diff --git a/builtin-checkout.c b/builtin-checkout.c index d050c37..448397d 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -510,11 +510,17 @@ static void update_refs_for_switch(struct checkout_opts *opts, REF_NODEREF, DIE_ON_ERR); if (!opts->quiet) { if (old->path) - fprintf(stderr, "Note: moving to '%s' which isn't a local branch\nIf you want to create a new branch from this checkout, you may do so\n(now or later) by using -b with the checkout command again. Example:\n git checkout -b <new_branch_name>\n", new->name); + fprintf(stderr, "Note: moving to '%s' which isn't a local branch.\nAny commits you may make will not affect the commit with this name.\n", new->name); describe_detached_head("HEAD is now at", new->commit); } } remove_branch_state(); + if (!new->path && strcmp(new->name, "HEAD")) { + FILE *detach_name; + detach_name = fopen(git_path("DETACH_NAME"), "w"); + fprintf(detach_name, "%s\n", new->name); + fclose(detach_name); + } strbuf_release(&msg); if (!opts->quiet && (new->path || !strcmp(new->name, "HEAD"))) report_tracking(new); diff --git a/builtin-commit.c b/builtin-commit.c index 200ffda..2ceb951 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -24,6 +24,7 @@ #include "string-list.h" #include "rerere.h" #include "unpack-trees.h" +#include "branch.h" static const char * const builtin_commit_usage[] = { "git commit [options] [--] <filepattern>...", @@ -968,6 +969,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) struct ref_lock *ref_lock; struct commit_list *parents = NULL, **pptr = &parents; struct stat statbuf; + char *detached_string; int allow_fast_forward = 1; struct wt_status s; @@ -1089,10 +1091,13 @@ int cmd_commit(int argc, const char **argv, const char *prefix) die("cannot update HEAD ref"); } + detached_string = get_detached_head_string(); + unlink(git_path("MERGE_HEAD")); unlink(git_path("MERGE_MSG")); unlink(git_path("MERGE_MODE")); unlink(git_path("SQUASH_MSG")); + unlink(git_path("DETACH_NAME")); if (commit_index_files()) die ("Repository has been updated, but unable to write\n" @@ -1101,8 +1106,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix) rerere(); run_hook(get_index_file(), "post-commit", NULL); - if (!quiet) + if (!quiet) { + if (detached_string) + fprintf(stderr, "\nNote: you had checked out '%s' which isn't a local branch.\nIf you want to create a new branch with this commit, you may do so\n(now or later) by using -b with the checkout command. Example:\n git checkout -b <new_branch_name>\n\n", detached_string); print_summary(prefix, commit_sha1); + } return 0; } diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 809d1c4..08409cd 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -67,7 +67,7 @@ test_expect_success 'git branch -v shows branch summaries' ' ' cat >expect <<'EOF' -* (no branch) +* (no branch, as "HEAD^0") branch-one branch-two master diff --git a/t/t7201-co.sh b/t/t7201-co.sh index ebfd34d..0f40589 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -171,10 +171,8 @@ test_expect_success 'checkout to detach HEAD' ' git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && (cat >messages.expect <<EOF -Note: moving to '\''renamer^'\'' which isn'\''t a local branch -If you want to create a new branch from this checkout, you may do so -(now or later) by using -b with the checkout command again. Example: - git checkout -b <new_branch_name> +Note: moving to '\''renamer^'\'' which isn'\''t a local branch. +Any commits you may make will not affect the commit with this name. HEAD is now at 7329388... Initial A one, A two EOF ) && -- 1.6.5.9.ge994f.dirty ^ permalink raw reply related [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 4:44 [PATCH] Proof-of-concept patch to remember what the detached HEAD was Daniel Barkalow @ 2009-10-14 5:07 ` Junio C Hamano 2009-10-14 5:08 ` Jeff King ` (2 subsequent siblings) 3 siblings, 0 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-14 5:07 UTC (permalink / raw) To: Daniel Barkalow; +Cc: git Daniel Barkalow <barkalow@iabervon.org> writes: > When detaching HEAD (or "browsing history"), the user has specified > the commit with some "extended SHA1" which is not a local > branch.... I do not have enough mental bandwidth to think about (1) if this information is a good thing to have, shown in your transcript, or (2) if the name of the branch _before_ getting into the detached state may be more interesting information tonight. But I have one question regarding the implementation. Why do you need a new file in $GIT_DIR for this? Wouldn't what is in the logs/HEAD be enough, and if not why not? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 4:44 [PATCH] Proof-of-concept patch to remember what the detached HEAD was Daniel Barkalow 2009-10-14 5:07 ` Junio C Hamano @ 2009-10-14 5:08 ` Jeff King 2009-10-14 10:33 ` Johannes Schindelin 2009-10-14 15:56 ` Daniel Barkalow 2009-10-14 18:56 ` Jay Soffian 2009-10-16 22:36 ` Christoph Bartoschek 3 siblings, 2 replies; 93+ messages in thread From: Jeff King @ 2009-10-14 5:08 UTC (permalink / raw) To: Daniel Barkalow; +Cc: Junio C Hamano, git On Wed, Oct 14, 2009 at 12:44:34AM -0400, Daniel Barkalow wrote: > +char *get_detached_head_string(void) > +{ > + char *filename = git_path("DETACH_NAME"); > + struct stat st; > + if (stat(filename, &st) || !S_ISREG(st.st_mode)) > + return NULL; > + struct strbuf buf = STRBUF_INIT; > + strbuf_read_file(&buf, filename, st.st_size); > + strbuf_trim(&buf); > + return strbuf_detach(&buf, 0); > +} Would it hurt to tuck this information into HEAD itself, as we already put arbitrary text into FETCH_HEAD? -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 5:08 ` Jeff King @ 2009-10-14 10:33 ` Johannes Schindelin 2009-10-14 15:39 ` Jeff King 2009-10-14 15:56 ` Daniel Barkalow 1 sibling, 1 reply; 93+ messages in thread From: Johannes Schindelin @ 2009-10-14 10:33 UTC (permalink / raw) To: Jeff King; +Cc: Daniel Barkalow, Junio C Hamano, git Hi, On Wed, 14 Oct 2009, Jeff King wrote: > On Wed, Oct 14, 2009 at 12:44:34AM -0400, Daniel Barkalow wrote: > > > +char *get_detached_head_string(void) > > +{ > > + char *filename = git_path("DETACH_NAME"); > > + struct stat st; > > + if (stat(filename, &st) || !S_ISREG(st.st_mode)) > > + return NULL; > > + struct strbuf buf = STRBUF_INIT; > > + strbuf_read_file(&buf, filename, st.st_size); > > + strbuf_trim(&buf); > > + return strbuf_detach(&buf, 0); > > +} > > Would it hurt to tuck this information into HEAD itself, as we already > put arbitrary text into FETCH_HEAD? AFAIR we still remember HEAD to be a symlink. Ciao, Dscho ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 10:33 ` Johannes Schindelin @ 2009-10-14 15:39 ` Jeff King 2009-10-14 18:34 ` Junio C Hamano 0 siblings, 1 reply; 93+ messages in thread From: Jeff King @ 2009-10-14 15:39 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Daniel Barkalow, Junio C Hamano, git On Wed, Oct 14, 2009 at 12:33:22PM +0200, Johannes Schindelin wrote: > > > +char *get_detached_head_string(void) > > > +{ > > > + char *filename = git_path("DETACH_NAME"); > > > + struct stat st; > > > + if (stat(filename, &st) || !S_ISREG(st.st_mode)) > > > + return NULL; > > > + struct strbuf buf = STRBUF_INIT; > > > + strbuf_read_file(&buf, filename, st.st_size); > > > + strbuf_trim(&buf); > > > + return strbuf_detach(&buf, 0); > > > +} > > > > Would it hurt to tuck this information into HEAD itself, as we already > > put arbitrary text into FETCH_HEAD? > > AFAIR we still remember HEAD to be a symlink. I think that has been abandoned for detached HEAD (that is, if you support only symlinked HEAD, then you cannot detach at all). But I might be wrong. It has been a while since I looked at that code. -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 15:39 ` Jeff King @ 2009-10-14 18:34 ` Junio C Hamano 2009-10-14 18:40 ` Jeff King 0 siblings, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-14 18:34 UTC (permalink / raw) To: Jeff King; +Cc: Johannes Schindelin, Daniel Barkalow, Junio C Hamano, git Jeff King <peff@peff.net> writes: > On Wed, Oct 14, 2009 at 12:33:22PM +0200, Johannes Schindelin wrote: > >> > > +char *get_detached_head_string(void) >> > > +{ >> > > + char *filename = git_path("DETACH_NAME"); >> > > + struct stat st; >> > > + if (stat(filename, &st) || !S_ISREG(st.st_mode)) >> > > + return NULL; >> > > + struct strbuf buf = STRBUF_INIT; >> > > + strbuf_read_file(&buf, filename, st.st_size); >> > > + strbuf_trim(&buf); >> > > + return strbuf_detach(&buf, 0); >> > > +} >> > >> > Would it hurt to tuck this information into HEAD itself, as we already >> > put arbitrary text into FETCH_HEAD? >> >> AFAIR we still remember HEAD to be a symlink. > > I think that has been abandoned for detached HEAD (that is, if you > support only symlinked HEAD, then you cannot detach at all). But I might > be wrong. It has been a while since I looked at that code. If I understand what Daniel is doing correctly, the idea is to keep this extra information only while the HEAD is detached, no? "HEAD itself could be a symlink" is an irrelevant issue, isn't it? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 18:34 ` Junio C Hamano @ 2009-10-14 18:40 ` Jeff King 0 siblings, 0 replies; 93+ messages in thread From: Jeff King @ 2009-10-14 18:40 UTC (permalink / raw) To: Junio C Hamano; +Cc: Johannes Schindelin, Daniel Barkalow, git On Wed, Oct 14, 2009 at 11:34:44AM -0700, Junio C Hamano wrote: > >> AFAIR we still remember HEAD to be a symlink. > > > > I think that has been abandoned for detached HEAD (that is, if you > > support only symlinked HEAD, then you cannot detach at all). But I might > > be wrong. It has been a while since I looked at that code. > > If I understand what Daniel is doing correctly, the idea is to keep this > extra information only while the HEAD is detached, no? "HEAD itself > could be a symlink" is an irrelevant issue, isn't it? Right. That is what I was trying to say, but somehow it didn't come out very clearly. -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 5:08 ` Jeff King 2009-10-14 10:33 ` Johannes Schindelin @ 2009-10-14 15:56 ` Daniel Barkalow 1 sibling, 0 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-14 15:56 UTC (permalink / raw) To: Jeff King; +Cc: Junio C Hamano, git On Wed, 14 Oct 2009, Jeff King wrote: > On Wed, Oct 14, 2009 at 12:44:34AM -0400, Daniel Barkalow wrote: > > > +char *get_detached_head_string(void) > > +{ > > + char *filename = git_path("DETACH_NAME"); > > + struct stat st; > > + if (stat(filename, &st) || !S_ISREG(st.st_mode)) > > + return NULL; > > + struct strbuf buf = STRBUF_INIT; > > + strbuf_read_file(&buf, filename, st.st_size); > > + strbuf_trim(&buf); > > + return strbuf_detach(&buf, 0); > > +} > > Would it hurt to tuck this information into HEAD itself, as we already > put arbitrary text into FETCH_HEAD? I don't know; I'll have to try that and see if the tools that handle HEAD are happy with extra text there. If it works, it's a good solution. I think I tried it at some point and things failed all over the place, but that may have been before symrefs, when you could get the actual sha1 hash out of HEAD with "$(cat .git/HEAD)". -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 4:44 [PATCH] Proof-of-concept patch to remember what the detached HEAD was Daniel Barkalow 2009-10-14 5:07 ` Junio C Hamano 2009-10-14 5:08 ` Jeff King @ 2009-10-14 18:56 ` Jay Soffian 2009-10-14 19:15 ` Daniel Barkalow 2009-10-16 22:36 ` Christoph Bartoschek 3 siblings, 1 reply; 93+ messages in thread From: Jay Soffian @ 2009-10-14 18:56 UTC (permalink / raw) To: Daniel Barkalow; +Cc: Junio C Hamano, git On Wed, Oct 14, 2009 at 12:44 AM, Daniel Barkalow <barkalow@iabervon.org> wrote: > $ git commit > You've been sightseeing "origin/master". The commit can't change that > value, so your commit isn't held in any branch. If you want to create > a branch to hold it, here's how. > > "git checkout origin/master" should be similar in complexity to > "svn checkout -r 8655"; the difference is that svn won't let you > commit then and git will but you'll need to understand the > implications if you do so. If you don't commit (because you don't want > to make any changes, because you don't think it would be possible, or > because you don't want to worry about what would happen), there's no > meaningful difference, and you don't need to be told. Huh, I hadn't seen this message before I wrote in a reply to "builtin-checkout: suggest creating local branch" that we do the following at commit, which I think is what you're suggesting: $ git commit -m "blah" Cannot commit while not on any branch. Please use git commit -b <branch> to specify the name of a new branch to commit to, or use git commit -f to force a detached commit. I'm not sure that requires the complexity of remembering how the user got detached though? j. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 18:56 ` Jay Soffian @ 2009-10-14 19:15 ` Daniel Barkalow 2009-10-14 20:18 ` Nicolas Pitre 0 siblings, 1 reply; 93+ messages in thread From: Daniel Barkalow @ 2009-10-14 19:15 UTC (permalink / raw) To: Jay Soffian; +Cc: Junio C Hamano, git [-- Attachment #1: Type: TEXT/PLAIN, Size: 1717 bytes --] On Wed, 14 Oct 2009, Jay Soffian wrote: > On Wed, Oct 14, 2009 at 12:44 AM, Daniel Barkalow <barkalow@iabervon.org> wrote: > > $ git commit > > You've been sightseeing "origin/master". The commit can't change that > > value, so your commit isn't held in any branch. If you want to create > > a branch to hold it, here's how. > > > > "git checkout origin/master" should be similar in complexity to > > "svn checkout -r 8655"; the difference is that svn won't let you > > commit then and git will but you'll need to understand the > > implications if you do so. If you don't commit (because you don't want > > to make any changes, because you don't think it would be possible, or > > because you don't want to worry about what would happen), there's no > > meaningful difference, and you don't need to be told. > > Huh, I hadn't seen this message before I wrote in a reply to > "builtin-checkout: suggest creating local branch" that we do the > following at commit, which I think is what you're suggesting: > > $ git commit -m "blah" > Cannot commit while not on any branch. Please use git commit -b <branch> to > specify the name of a new branch to commit to, or use git commit -f to > force a detached commit. The difference is that some experienced users depend on being able to commit while not on a branch, and want to not get a warning for every commit while not on a branch. > I'm not sure that requires the complexity of remembering how the user > got detached though? What matters there is actually whether we got to the present state by committing or not. It's also relevant to telling the user what they've got checked out that isn't a branch. -Daniel *This .sif left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 19:15 ` Daniel Barkalow @ 2009-10-14 20:18 ` Nicolas Pitre 2009-10-14 20:37 ` Daniel Barkalow 2009-10-14 20:42 ` Junio C Hamano 0 siblings, 2 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-14 20:18 UTC (permalink / raw) To: Daniel Barkalow; +Cc: Jay Soffian, Junio C Hamano, git On Wed, 14 Oct 2009, Daniel Barkalow wrote: > On Wed, 14 Oct 2009, Jay Soffian wrote: > > > $ git commit -m "blah" > > Cannot commit while not on any branch. Please use git commit -b <branch> to > > specify the name of a new branch to commit to, or use git commit -f to > > force a detached commit. > > The difference is that some experienced users depend on being able to > commit while not on a branch, and want to not get a warning for every > commit while not on a branch. I assume that the -f would silence any warning? Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 20:18 ` Nicolas Pitre @ 2009-10-14 20:37 ` Daniel Barkalow 2009-10-14 20:42 ` Junio C Hamano 1 sibling, 0 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-14 20:37 UTC (permalink / raw) To: Nicolas Pitre; +Cc: Jay Soffian, Junio C Hamano, git On Wed, 14 Oct 2009, Nicolas Pitre wrote: > On Wed, 14 Oct 2009, Daniel Barkalow wrote: > > > On Wed, 14 Oct 2009, Jay Soffian wrote: > > > > > $ git commit -m "blah" > > > Cannot commit while not on any branch. Please use git commit -b <branch> to > > > specify the name of a new branch to commit to, or use git commit -f to > > > force a detached commit. > > > > The difference is that some experienced users depend on being able to > > commit while not on a branch, and want to not get a warning for every > > commit while not on a branch. > > I assume that the -f would silence any warning? I suppose; I don't know if that would be acceptable to the relevant users. It would certainly require script changes, but that's not an issue for 1.7.0, presumably. I personally normally use the order: $ git checkout origin/master (change stuff, test) $ git checkout -b my-topic $ git commit So I only care about detaching, not committing while detached, and I'm not the right person to ask. -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 20:18 ` Nicolas Pitre 2009-10-14 20:37 ` Daniel Barkalow @ 2009-10-14 20:42 ` Junio C Hamano 2009-10-14 20:48 ` Nicolas Pitre 2009-10-14 23:52 ` Eric Raible 1 sibling, 2 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-14 20:42 UTC (permalink / raw) To: Nicolas Pitre; +Cc: Daniel Barkalow, Jay Soffian, Junio C Hamano, git Nicolas Pitre <nico@fluxnic.net> writes: > On Wed, 14 Oct 2009, Daniel Barkalow wrote: > >> On Wed, 14 Oct 2009, Jay Soffian wrote: >> >> > $ git commit -m "blah" >> > Cannot commit while not on any branch. Please use git commit -b <branch> to >> > specify the name of a new branch to commit to, or use git commit -f to >> > force a detached commit. >> >> The difference is that some experienced users depend on being able to >> commit while not on a branch, and want to not get a warning for every >> commit while not on a branch. > > I assume that the -f would silence any warning? It won't help to alleviate my irritation if I need to give -f to each and every invocation of "git commit" while detached, though. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 20:42 ` Junio C Hamano @ 2009-10-14 20:48 ` Nicolas Pitre 2009-10-14 22:34 ` Junio C Hamano 2009-10-14 23:52 ` Eric Raible 1 sibling, 1 reply; 93+ messages in thread From: Nicolas Pitre @ 2009-10-14 20:48 UTC (permalink / raw) To: Junio C Hamano; +Cc: Daniel Barkalow, Jay Soffian, git On Wed, 14 Oct 2009, Junio C Hamano wrote: > Nicolas Pitre <nico@fluxnic.net> writes: > > > On Wed, 14 Oct 2009, Daniel Barkalow wrote: > > > >> On Wed, 14 Oct 2009, Jay Soffian wrote: > >> > >> > $ git commit -m "blah" > >> > Cannot commit while not on any branch. Please use git commit -b <branch> to > >> > specify the name of a new branch to commit to, or use git commit -f to > >> > force a detached commit. > >> > >> The difference is that some experienced users depend on being able to > >> commit while not on a branch, and want to not get a warning for every > >> commit while not on a branch. > > > > I assume that the -f would silence any warning? > > It won't help to alleviate my irritation if I need to give -f to each and > every invocation of "git commit" while detached, though. Agreed. Presumably some expert mode config would imply -f automatically. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 20:48 ` Nicolas Pitre @ 2009-10-14 22:34 ` Junio C Hamano 2009-10-14 23:09 ` Jeff King 0 siblings, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-14 22:34 UTC (permalink / raw) To: Nicolas Pitre; +Cc: Daniel Barkalow, Jay Soffian, git Nicolas Pitre <nico@fluxnic.net> writes: > On Wed, 14 Oct 2009, Junio C Hamano wrote: > >> Nicolas Pitre <nico@fluxnic.net> writes: >> >> > On Wed, 14 Oct 2009, Daniel Barkalow wrote: >> > >> >> On Wed, 14 Oct 2009, Jay Soffian wrote: >> >> >> >> > $ git commit -m "blah" >> >> > Cannot commit while not on any branch. Please use git commit -b <branch> to >> >> > specify the name of a new branch to commit to, or use git commit -f to >> >> > force a detached commit. >> >> >> >> The difference is that some experienced users depend on being able to >> >> commit while not on a branch, and want to not get a warning for every >> >> commit while not on a branch. >> > >> > I assume that the -f would silence any warning? >> >> It won't help to alleviate my irritation if I need to give -f to each and >> every invocation of "git commit" while detached, though. > > Agreed. Presumably some expert mode config would imply -f > automatically. No, I do not want an expert mode. I can probably live with "per session" setting, that makes me decide to set or not set it when I detach, though. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 22:34 ` Junio C Hamano @ 2009-10-14 23:09 ` Jeff King 2009-10-14 23:34 ` Nicolas Pitre 2009-10-15 7:36 ` James Pickens 0 siblings, 2 replies; 93+ messages in thread From: Jeff King @ 2009-10-14 23:09 UTC (permalink / raw) To: Junio C Hamano; +Cc: Nicolas Pitre, Daniel Barkalow, Jay Soffian, git On Wed, Oct 14, 2009 at 03:34:05PM -0700, Junio C Hamano wrote: > > Agreed. Presumably some expert mode config would imply -f > > automatically. > > No, I do not want an expert mode. I can probably live with "per session" > setting, that makes me decide to set or not set it when I detach, though. That makes the most sense to me. If "git checkout" could write metadata into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout could record an "ok to commit" bit. And could also be used to change it after the fact. E.g.: $ git checkout --detach=commit origin/master $ git commit ;# should be ok $ git checkout --detach=examine origin/master $ git commit ;# complain $ git checkout --detach=commit HEAD $ git commit ;# ok I guess something like "rebase" should detach with "ok to commit", since it is planning on attaching the commits later. I'm not sure about "git bisect". I guess probably it should be "not ok to commit" to be on the safe side, and then somebody can "git checkout --detach=commit" if they want to. -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 23:09 ` Jeff King @ 2009-10-14 23:34 ` Nicolas Pitre 2009-10-15 0:56 ` Junio C Hamano 2009-10-15 7:36 ` James Pickens 1 sibling, 1 reply; 93+ messages in thread From: Nicolas Pitre @ 2009-10-14 23:34 UTC (permalink / raw) To: Jeff King; +Cc: Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Wed, 14 Oct 2009, Jeff King wrote: > On Wed, Oct 14, 2009 at 03:34:05PM -0700, Junio C Hamano wrote: > > > > Agreed. Presumably some expert mode config would imply -f > > > automatically. > > > > No, I do not want an expert mode. I can probably live with "per session" > > setting, that makes me decide to set or not set it when I detach, though. > > That makes the most sense to me. If "git checkout" could write metadata > into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout > could record an "ok to commit" bit. And could also be used to change it > after the fact. E.g.: > > $ git checkout --detach=commit origin/master > $ git commit ;# should be ok > > $ git checkout --detach=examine origin/master > $ git commit ;# complain > $ git checkout --detach=commit HEAD > $ git commit ;# ok > > I guess something like "rebase" should detach with "ok to commit", since > it is planning on attaching the commits later. I'm not sure about "git > bisect". I guess probably it should be "not ok to commit" to be on the > safe side, and then somebody can "git checkout --detach=commit" if they > want to. Whatever is done about this... I'm afraid Git will end up less useful as operations that were possible before won't be anymore for "security's sake" unless some obnoxious override mode is involved. Isn't the reflog already dealing with the security issue by making sure that nothing is "lost"? Can't the user confusion be dealt with through some means other than making the tool less flexible? I don't mind extra help message to be displayed after a headless commit is made for example. But trying to make the tool more friendly should perhaps come from better education rather than added restrictions. My thoughts only. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 23:34 ` Nicolas Pitre @ 2009-10-15 0:56 ` Junio C Hamano 2009-10-15 1:47 ` Jeff King 2009-10-16 0:53 ` Johannes Schindelin 0 siblings, 2 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-15 0:56 UTC (permalink / raw) To: Nicolas Pitre Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git Nicolas Pitre <nico@fluxnic.net> writes: > Can't the user confusion be dealt with through some means other than > making the tool less flexible? I don't mind extra help message to be > displayed after a headless commit is made for example. But trying to > make the tool more friendly should perhaps come from better education > rather than added restrictions. > > My thoughts only. I actually share that but there apparently are people who have given up on the education route. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 0:56 ` Junio C Hamano @ 2009-10-15 1:47 ` Jeff King 2009-10-15 3:08 ` Nicolas Pitre 2009-10-16 0:53 ` Johannes Schindelin 1 sibling, 1 reply; 93+ messages in thread From: Jeff King @ 2009-10-15 1:47 UTC (permalink / raw) To: Junio C Hamano; +Cc: Nicolas Pitre, Daniel Barkalow, Jay Soffian, git On Wed, Oct 14, 2009 at 05:56:52PM -0700, Junio C Hamano wrote: > Nicolas Pitre <nico@fluxnic.net> writes: > > > Can't the user confusion be dealt with through some means other than > > making the tool less flexible? I don't mind extra help message to be > > displayed after a headless commit is made for example. But trying to > > make the tool more friendly should perhaps come from better education > > rather than added restrictions. > > > > My thoughts only. > > I actually share that but there apparently are people who have given up on > the education route. I am personally undecided on this issue (my "this is the best option" was the best of "a -f switch to commit, an 'expert' config option', or a session-based option to commit"). But we really seem to have reached an impasse with how to proceed with git ui. People like Dscho are fed up with user complaints about parts of git that can be unfriendly to new users. And I can understand that. There _is_ a perception that git is hard for beginners to use, and I don't think that perception is entirely without merit. We expect the user to understand the basic concepts of git, like history graphs, named refs versus detached heads, tracking refs, the index, etc. At the same time, I think that is what many of us _like_ about git. It is based around simple and powerful concepts, and it doesn't get in your way when you want to use those concepts in a powerful and flexible manner. And I can understand resistance to making those features hard or inconvenient to access; detached HEADs were invented for a reason, and we want to use them. So what is the right way to mediate between those desires? We have tried or suggested several options, including: 1. Educate users. Keep exposing them to the concepts, but make messages more clear. Improve documentation. This is largely the route taken with the index. Has it worked? I think there is still a perception among new users that the index is confusing. 2. Use configuration options to differentiate behavior. This comes in the form of the sometimes-requested "expert/beginner mode" option. But it can also mean a config option for a specific behavior. The argument against it I have seen is that it can make git unpredictable for new versus old users. An old-timer helping a new person is more out-of-touch with what the new person's setup will do (which hurts when sitting at their terminal or when giving them advice online). 3. Make a new porcelain interface that wraps the git plumbing. We have seen some examples of this. Obviously cogito was the first, and it has fallen by the wayside as people moved towards core git. That may be an artifact of its timing, though, as core git was a rapidly moving target, and power users wanted to use the new features. More recently we've had 'eg'. I don't know how many people are using it, but it is certainly not discussed on this list much. There are also GUIs wrapping git. I think these are subject to the same argument as (2), but even more so. An entirely new interface like 'eg' is really splitting the user base. As a git old-timer, I can keep up with what newbie options might impact git's behavior. But I haven't a clue how to do anything in 'eg'. 4. Hide potentially dangerous behavior behind "-f" or similar options, or make it even more inaccessible. We have done this with some obviously dangerous cases, like "push -f" or "checkout -f", which can throw away data. But I think in cases where the behavior is simply confusing and not dangerous, we tend not to do this (at least I couldn't think of any examples off the top of my head). The obvious argument against it is that it inconveniences more experienced users. Dscho advocated "the good of the many" versus "the good of the few". And I can see some logic in that. At the same time, open source is about scratching itches. Is anyone really interested in doing something that makes our own itch worse? Everytime you use it, won't you be thinking about scratching? So I don't know what the solution is. And maybe this is just useless pontificating. But I feel like we have this discussion over and over, every few months, about a different feature. I wish there were some way to fix that. Out of ideas, -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 1:47 ` Jeff King @ 2009-10-15 3:08 ` Nicolas Pitre 2009-10-15 4:21 ` Jeff King 2009-10-16 1:04 ` Johannes Schindelin 0 siblings, 2 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-15 3:08 UTC (permalink / raw) To: Jeff King; +Cc: Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Wed, 14 Oct 2009, Jeff King wrote: > On Wed, Oct 14, 2009 at 05:56:52PM -0700, Junio C Hamano wrote: > > > Nicolas Pitre <nico@fluxnic.net> writes: > > > > > Can't the user confusion be dealt with through some means other than > > > making the tool less flexible? I don't mind extra help message to be > > > displayed after a headless commit is made for example. But trying to > > > make the tool more friendly should perhaps come from better education > > > rather than added restrictions. > > > > > > My thoughts only. > > > > I actually share that but there apparently are people who have given up on > > the education route. > > I am personally undecided on this issue (my "this is the best option" > was the best of "a -f switch to commit, an 'expert' config option', or a > session-based option to commit"). > > But we really seem to have reached an impasse with how to proceed with > git ui. > > People like Dscho are fed up with user complaints about parts of git > that can be unfriendly to new users. And I can understand that. People like Dscho have to grow a thicker skin then. There will _always_ be user complaints regardless of how balanced you try to make a UI. > There _is_ a perception that git is hard for beginners to use, and I > don't think that perception is entirely without merit. We expect the > user to understand the basic concepts of git, like history graphs, > named refs versus detached heads, tracking refs, the index, etc. Sure. That's part of it, and beginners must get over with that perception. Git is a professional tool and not a toy project anymore. Like any professional grade tool, there is a greater effort needed from beginners before being comfortable with the tool. > At the same time, I think that is what many of us _like_ about git. It > is based around simple and powerful concepts, and it doesn't get in your > way when you want to use those concepts in a powerful and flexible > manner. And I can understand resistance to making those features hard or > inconvenient to access; detached HEADs were invented for a reason, and > we want to use them. Right. Removing features That _are_ being used sounds a bit backward. Just because they happen to be confusing to beginners is not a good justification to remove/cripple them IMHO. > So what is the right way to mediate between those desires? We have tried > or suggested several options, including: > > 1. Educate users. Keep exposing them to the concepts, but make > messages more clear. Improve documentation. This is largely the > route taken with the index. Has it worked? I think there is still a > perception among new users that the index is confusing. Well, New users won't be new forever. And Git is different from most other SCMs. Eventually that difference is well understood by most not-so-new-anymore Git users. Right now I have to deal with Perforce at $work and I find it _terribly_ confusing and obnoxious to use. So it's only a question of getting used to something different. IMHO this patch proposed by Daniel about the detached head is probably a good compromise. It makes "confusing" operations more verbose to give new users a better feeling while keeping the flexibility intact. And increased verbosity is less annoying than decreased flexibility. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 3:08 ` Nicolas Pitre @ 2009-10-15 4:21 ` Jeff King 2009-10-16 1:04 ` Johannes Schindelin 1 sibling, 0 replies; 93+ messages in thread From: Jeff King @ 2009-10-15 4:21 UTC (permalink / raw) To: Nicolas Pitre; +Cc: Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Wed, Oct 14, 2009 at 11:08:59PM -0400, Nicolas Pitre wrote: > IMHO this patch proposed by Daniel about the detached head is probably a > good compromise. It makes "confusing" operations more verbose to give > new users a better feeling while keeping the flexibility intact. And > increased verbosity is less annoying than decreased flexibility. And I don't think there is as much opposition to a config option to silence verbosity, because it isn't really a change in behavior. We already have advice.*, and if the new message is too annoying, we can get advice.commitDetachedHead. -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 3:08 ` Nicolas Pitre 2009-10-15 4:21 ` Jeff King @ 2009-10-16 1:04 ` Johannes Schindelin 2009-10-16 1:36 ` Nicolas Pitre 1 sibling, 1 reply; 93+ messages in thread From: Johannes Schindelin @ 2009-10-16 1:04 UTC (permalink / raw) To: Nicolas Pitre Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git Hi, On Wed, 14 Oct 2009, Nicolas Pitre wrote: > On Wed, 14 Oct 2009, Jeff King wrote: > > > On Wed, Oct 14, 2009 at 05:56:52PM -0700, Junio C Hamano wrote: > > > > > Nicolas Pitre <nico@fluxnic.net> writes: > > > > > > > Can't the user confusion be dealt with through some means other than > > > > making the tool less flexible? I don't mind extra help message to be > > > > displayed after a headless commit is made for example. But trying to > > > > make the tool more friendly should perhaps come from better education > > > > rather than added restrictions. > > > > > > > > My thoughts only. > > > > > > I actually share that but there apparently are people who have given up on > > > the education route. > > > > I am personally undecided on this issue (my "this is the best option" > > was the best of "a -f switch to commit, an 'expert' config option', or a > > session-based option to commit"). > > > > But we really seem to have reached an impasse with how to proceed with > > git ui. > > > > People like Dscho are fed up with user complaints about parts of git > > that can be unfriendly to new users. And I can understand that. > > People like Dscho have to grow a thicker skin then. There will _always_ > be user complaints regardless of how balanced you try to make a UI. You are seriously misreading my intentions, then. Or my intelligence. It is not about growing a thicker skin towards unmerited complaints. It is about shedding the thick skin when there are merited complaints, and some people are just too used to the old ways to understand that some of the complaints have _a lot_ of merit. It is just like with the olden days when only a precious few could drive cars, and maintained that it _is_ hard to drive a car, and _not_ everybody can do it _because_ you will have a breakdown with the car and you _have_ to be able to fix it yourself. Fast-forward a hundred years. None of this is true any longer. None. Guess what? In these days, we do not need a hundred years. Four is plenty enough. We have a lot of Git users who do not understand the inner workings of Git. And why should they need to? Who are you to say they should? We, the old Gits need to change. Not the many other people. Remember: you do not know how exactly the clutch interacts with the 2nd cylinder of the engine. And you do not _need_ to. Neither should Git users need to. Ciao, Dscho ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 1:04 ` Johannes Schindelin @ 2009-10-16 1:36 ` Nicolas Pitre 2009-10-16 2:07 ` Johannes Schindelin 0 siblings, 1 reply; 93+ messages in thread From: Nicolas Pitre @ 2009-10-16 1:36 UTC (permalink / raw) To: Johannes Schindelin Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Fri, 16 Oct 2009, Johannes Schindelin wrote: > We, the old Gits need to change. Not the many other people. > > Remember: you do not know how exactly the clutch interacts with the 2nd > cylinder of the engine. And you do not _need_ to. Really, the detached HEAD concept can't be _that_ hard. It is not like if we were asking our users to fully grok the blob/tree/commit hierarchy and delta compression heuristics to be able to work with Git. > Neither should Git users need to. What you're asking for, though, is more comparable to asking old Gits to give up on their clutch and manual gearbox because most American Git users are expecting automatic transmissions. Maybe that's not the case in Germany, but over here automatic transmissions are by far the norm and a manual gearbox can be obtained only in limited cases if at all. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 1:36 ` Nicolas Pitre @ 2009-10-16 2:07 ` Johannes Schindelin 2009-10-16 2:45 ` Nicolas Pitre ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: Johannes Schindelin @ 2009-10-16 2:07 UTC (permalink / raw) To: Nicolas Pitre Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git Hi, On Thu, 15 Oct 2009, Nicolas Pitre wrote: > On Fri, 16 Oct 2009, Johannes Schindelin wrote: > > > We, the old Gits need to change. Not the many other people. > > > > Remember: you do not know how exactly the clutch interacts with the 2nd > > cylinder of the engine. And you do not _need_ to. > > Really, the detached HEAD concept can't be _that_ hard. You are trying to educate the users to use the double-clutch. Rather than making the double-clutch obsolete. That's what I call "BlameTheWrongThing". > > Neither should Git users need to. > > What you're asking for, though, is more comparable to asking old Gits to > give up on their clutch and manual gearbox because most American Git > users are expecting automatic transmissions. Maybe that's not the case > in Germany, but over here automatic transmissions are by far the norm > and a manual gearbox can be obtained only in limited cases if at all. Your point being? You really think Git is already at the stage where it has automatic transmission and all you have to do is hit the gas or the brake? No, Nico, you are too intelligent to believe that. Besides, Git is not even at the stage of a manual gearbox. Just recently, I had a user request (a very valid one, mind you) where the user does not want to provide a commit message, and wants to just commit all the current changes. In that particular case, it is very sensible to ask for these things. It is something utterly simple to ask for. Yet, it is utterly hard with Git, especially if I have to explain it. Maybe the core Git developers should spend a month explaining the core principles of Git to some random software developers, just so all of us get an idea just how wrong we are on the account of how intuitive Git is. Ciao, Dscho ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 2:07 ` Johannes Schindelin @ 2009-10-16 2:45 ` Nicolas Pitre 2009-10-16 2:56 ` Junio C Hamano 2009-10-17 7:24 ` Sean Estabrooks 2 siblings, 0 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-16 2:45 UTC (permalink / raw) To: Johannes Schindelin Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Fri, 16 Oct 2009, Johannes Schindelin wrote: > Hi, > > On Thu, 15 Oct 2009, Nicolas Pitre wrote: > > > On Fri, 16 Oct 2009, Johannes Schindelin wrote: > > > > > We, the old Gits need to change. Not the many other people. > > > > > > Remember: you do not know how exactly the clutch interacts with the 2nd > > > cylinder of the engine. And you do not _need_ to. > > > > Really, the detached HEAD concept can't be _that_ hard. > > You are trying to educate the users to use the double-clutch. Rather than > making the double-clutch obsolete. > That's what I call "BlameTheWrongThing". I just can't convince myself to share that point of view. Doesn't mean that I'm right though, but that's how I see it given the alternative. > > > Neither should Git users need to. > > > > What you're asking for, though, is more comparable to asking old Gits to > > give up on their clutch and manual gearbox because most American Git > > users are expecting automatic transmissions. Maybe that's not the case > > in Germany, but over here automatic transmissions are by far the norm > > and a manual gearbox can be obtained only in limited cases if at all. > > Your point being? You really think Git is already at the stage where it > has automatic transmission and all you have to do is hit the gas or the > brake? No, Nico, you are too intelligent to believe that. No, Git is not at the automatic transmission level, and I _don't_ want it to, ever. That would not be _my_ choice. > Besides, Git is not even at the stage of a manual gearbox. Here I disagree. > Just recently, I had a user request (a very valid one, mind you) where the > user does not want to provide a commit message, and wants to just commit > all the current changes. In that particular case, it is very sensible to > ask for these things. It is something utterly simple to ask for. Yet, it > is utterly hard with Git, especially if I have to explain it. I hope this is a bad example. I just can't imagine how "very sensible" you may consider messageless commits. I've dealt with them too many times in my life. But still, if someone just can't be bothered at all then the "workaround" is easy: just use '-m.' or any other meaningless character of your choice. At least _I_ will be able to identify those commits as being purposely messageless and make a better informed opinion on that committer instead of blaming it on ignorance. > Maybe the core Git developers should spend a month explaining the core > principles of Git to some random software developers, just so all of us > get an idea just how wrong we are on the account of how intuitive Git is. Sorry but I don't share that feeling of hopelessness that seems to affect those random software developers you might have tried to teach Git to. Well, actually I do have to deal with hopeless software developers once in a while which are simply total idiots, and they certainly shine at depicting Git, or any other tool at their disposal for that matter, as utter crap. But fortunately for me, the few people to whom I've explained Git so far simply got it in very little time. In my opinion, the most important concept to explain first is Git branching. Everything else is kinda secondary. Worked for me pretty well so far. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 2:07 ` Johannes Schindelin 2009-10-16 2:45 ` Nicolas Pitre @ 2009-10-16 2:56 ` Junio C Hamano 2009-10-17 7:24 ` Sean Estabrooks 2 siblings, 0 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-16 2:56 UTC (permalink / raw) To: Johannes Schindelin Cc: Nicolas Pitre, Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > You are trying to educate the users to use the double-clutch. Rather than > making the double-clutch obsolete. I do not quite get your double-clutch rhetoric, in the sense that I do not think it has anything analogous in the topic of detached HEAD we have been discussing. Didn't we discuss possible solutions to make sure that you do not have to detach HEAD and lose commits by coming back without saving them? I would consider that corresponds to inventing automatic (iow, making sure that sightseeing can be done without having to worry about accidentally committing on that state and later losing them). Obviously, you would need to cover cases other than we have discussed (e.g. if "rebase -i" detaches, it needs to allow "commit", "commit --amend", and "reset --soft HEAD^", but you probably would not want to allow "checkout" to switch to another branch). Thinking things through so that we can fill in all these details is a tedious and hard work, but I would say it would be worth it. In the ideal world, if you do not have to (nor want to) use the detached HEAD feature, you do not have to. But that is entirely different from saying "I do not need to use detached HEAD, I cannot explain it to my users. Let's make it unusable, iow, I give up". Unfortunately that is the impression I am getting from your whining. If you have been advocating for something else, and you share the goal of helping users by e.g. making it unnecessary to worry about accidentally committing on that state and later losing them, you would need to do a better job explaining yourself. > Just recently, I had a user request (a very valid one, mind you) where the > user does not want to provide a commit message, and wants to just commit > all the current changes. In that particular case, it is very sensible to > ask for these things. It is something utterly simple to ask for. Yet, it > is utterly hard with Git, especially if I have to explain it. I suspect the above is another example of your needing to do a better job explaining yourself here, but from "just commit all the changes without saying message", my knee-jerk reaction is "git commit -a -m 'no message'". You would need to justify why -m 'no message' does not fit the bill better than just saying "is very sensible to ask for these things", as I highly suspect that I misunderstood what "these things" are in your five lines to come up with that "solution" that you are now going to explain why that is not what the end user wanted. And in this case, I do not think it is that me being disconnected from the real world, but that your explanation is insufficient. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 2:07 ` Johannes Schindelin 2009-10-16 2:45 ` Nicolas Pitre 2009-10-16 2:56 ` Junio C Hamano @ 2009-10-17 7:24 ` Sean Estabrooks 2009-10-26 22:22 ` Johannes Schindelin 2 siblings, 1 reply; 93+ messages in thread From: Sean Estabrooks @ 2009-10-17 7:24 UTC (permalink / raw) To: Johannes Schindelin Cc: Nicolas Pitre, Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Fri, 16 Oct 2009 04:07:23 +0200 (CEST) Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote: > Just recently, I had a user request (a very valid one, mind you) where the > user does not want to provide a commit message, and wants to just commit > all the current changes. In that particular case, it is very sensible to > ask for these things. It is something utterly simple to ask for. Yet, it > is utterly hard with Git, especially if I have to explain it. Hey Johannes, It's actually easy, but maybe hard to find: $ git commit --cleanup=verbatim -m "" Cheers, Sean ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 7:24 ` Sean Estabrooks @ 2009-10-26 22:22 ` Johannes Schindelin 2009-10-27 3:41 ` Nanako Shiraishi 0 siblings, 1 reply; 93+ messages in thread From: Johannes Schindelin @ 2009-10-26 22:22 UTC (permalink / raw) To: Sean Estabrooks Cc: Nicolas Pitre, Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git Hi, On Sat, 17 Oct 2009, Sean Estabrooks wrote: > On Fri, 16 Oct 2009 04:07:23 +0200 (CEST) > Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote: > > > Just recently, I had a user request (a very valid one, mind you) where > > the user does not want to provide a commit message, and wants to just > > commit all the current changes. In that particular case, it is very > > sensible to ask for these things. It is something utterly simple to > > ask for. Yet, it is utterly hard with Git, especially if I have to > > explain it. > > Hey Johannes, > > It's actually easy, but maybe hard to find: > > $ git commit --cleanup=verbatim -m "" Of course that leaves out the main part. But it is simple once you know it (I did not): git add -A (we even went out of our way _not_ to name the long option --addremove, but --all -- it does not seem to be an expressive-enough option name to me, but what does my impression matter...) So I retract my claim that it is utterly hard to do with Git (but not the rest). Ciao, Dscho ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-26 22:22 ` Johannes Schindelin @ 2009-10-27 3:41 ` Nanako Shiraishi 2009-10-27 10:33 ` Making Git easy to use -- without RTFM, was " Johannes Schindelin 0 siblings, 1 reply; 93+ messages in thread From: Nanako Shiraishi @ 2009-10-27 3:41 UTC (permalink / raw) To: Johannes Schindelin Cc: Sean Estabrooks, Nicolas Pitre, Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git Quoting Johannes Schindelin <Johannes.Schindelin@gmx.de> > On Sat, 17 Oct 2009, Sean Estabrooks wrote: > >> On Fri, 16 Oct 2009 04:07:23 +0200 (CEST) >> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote: >> >> > Just recently, I had a user request (a very valid one, mind you) where >> > the user does not want to provide a commit message, and wants to just >> > commit all the current changes. In that particular case, it is very >> > sensible to ask for these things. It is something utterly simple to >> > ask for. Yet, it is utterly hard with Git, especially if I have to >> > explain it. >> >> Hey Johannes, >> >> It's actually easy, but maybe hard to find: >> >> $ git commit --cleanup=verbatim -m "" > > Of course that leaves out the main part. But it is simple once you > know it (I did not): git add -A (we even went out of our way _not_ to name > the long option --addremove, but --all -- it does not seem to be an > expressive-enough option name to me, but what does my impression > matter...) > > So I retract my claim that it is utterly hard to do with Git (but not the > rest). Last week, Junio gave this comment to your message. > I suspect the above is another example of your needing to do > a better job explaining yourself here, but from "just commit > all the changes without saying message", my knee-jerk > reaction is "git commit -a -m 'no message'". > You would need to justify why -m 'no message' does not fit > the bill better than just saying "is very sensible to ask for > these things", as I highly suspect that I misunderstood what > "these things" are in your five lines to come up with that > "solution" that you are now going to explain why that is not > what the end user wanted. And in this case, I do not think > it is that me being disconnected from the real world, but > that your explanation is insufficient. I'm also curious about the situation when a commit with no message is useful, but unfortunately I don't think I saw you explained clearly enough what this user request wanted to achieve or what "these things" in your message were for us to understand why it is a sensible and valid thing to ask. Did I miss some messages in the thread? -- Nanako Shiraishi http://ivory.ap.teacup.com/nanako3/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Making Git easy to use -- without RTFM, was Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-27 3:41 ` Nanako Shiraishi @ 2009-10-27 10:33 ` Johannes Schindelin 2009-10-27 17:58 ` Avery Pennarun 0 siblings, 1 reply; 93+ messages in thread From: Johannes Schindelin @ 2009-10-27 10:33 UTC (permalink / raw) To: Nanako Shiraishi; +Cc: git Hi, [culling the Cc: list, as this subthread is probably irrelevant most of the previous members] On Tue, 27 Oct 2009, Nanako Shiraishi wrote: > Quoting Johannes Schindelin <Johannes.Schindelin@gmx.de> > > [actually not, Nanako quoted Junio here, I guess] > > > I suspect the above is another example of your needing to do a better > > job explaining yourself here, but from "just commit all the changes > > without saying message", my knee-jerk reaction is "git commit -a -m > > 'no message'". > > > You would need to justify why -m 'no message' does not fit the bill > > better than just saying "is very sensible to ask for these things", as > > I highly suspect that I misunderstood what "these things" are in your > > five lines to come up with that "solution" that you are now going to > > explain why that is not what the end user wanted. And in this case, I > > do not think it is that me being disconnected from the real world, but > > that your explanation is insufficient. > > I'm also curious about the situation when a commit with no message is > useful, but unfortunately I don't think I saw you explained clearly > enough what this user request wanted to achieve or what "these things" > in your message were for us to understand why it is a sensible and valid > thing to ask. I am sure that your creative mind does not need my concrete example to come up with a situation where an empty commit message is useful. Anyhow, here it is: one of my users refused to touch SCMs _at all_, for decades. There was only one choice: have a Git branch with a purely linear history that contains the copy of the working tree at the end of the day, with whatever changes accumulated over the day, or no history at all. Sure, some people will now argue that it should be easy to educate that user to use Git properly. But that is as naive as it would be to try to educate those people so they know how unrealistic educating users is. Not because users are not intelligent -- they are -- but because they want to spend their time in a more efficient manner than to learn how to operate a version control system. You know, when there is a hurdle half of the people you see cannot get over, there are some who make the hurdle half as high, and there are others who put more hurdles there and call it a sport. In this case, I would have preferred to make the hurdle half as high, but I think I just have to wait a couple of years; reality will take care of things. Ciao, Dscho ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: Making Git easy to use -- without RTFM, was Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-27 10:33 ` Making Git easy to use -- without RTFM, was " Johannes Schindelin @ 2009-10-27 17:58 ` Avery Pennarun 0 siblings, 0 replies; 93+ messages in thread From: Avery Pennarun @ 2009-10-27 17:58 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Nanako Shiraishi, git On Tue, Oct 27, 2009 at 6:33 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote: > Anyhow, here it is: one of my users refused to touch SCMs _at all_, for > decades. There was only one choice: have a Git branch with a purely > linear history that contains the copy of the working tree at the end of > the day, with whatever changes accumulated over the day, or no history at > all. [...] > You know, when there is a hurdle half of the people you see cannot get > over, there are some who make the hurdle half as high, and there are > others who put more hurdles there and call it a sport. > > In this case, I would have preferred to make the hurdle half as high, but > I think I just have to wait a couple of years; reality will take care of > things. In this case, what would you have preferred to change in order to make the hurdle half as high? Thanks, Avery ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 0:56 ` Junio C Hamano 2009-10-15 1:47 ` Jeff King @ 2009-10-16 0:53 ` Johannes Schindelin 2009-10-16 3:00 ` Junio C Hamano 1 sibling, 1 reply; 93+ messages in thread From: Johannes Schindelin @ 2009-10-16 0:53 UTC (permalink / raw) To: Junio C Hamano Cc: Nicolas Pitre, Jeff King, Daniel Barkalow, Jay Soffian, git Hi, On Wed, 14 Oct 2009, Junio C Hamano wrote: > Nicolas Pitre <nico@fluxnic.net> writes: > > > Can't the user confusion be dealt with through some means other than > > making the tool less flexible? I don't mind extra help message to be > > displayed after a headless commit is made for example. But trying to > > make the tool more friendly should perhaps come from better education > > rather than added restrictions. > > > > My thoughts only. > > I actually share that but there apparently are people who have given up on > the education route. At some point, when you try to teach something that people (i.e. more than one person) do not get easily, you cannot do anything but admit that what you try to teach is crap. Obviously you did not have that experience. Maybe you are just more picky than me when it comes to who you try to teach. But of course, that does not make what you try to teach less crap. In this particular case, I cannot help but notice that commits performed on a detached HEAD will get lost _unless_ they are somehow put onto a named branch eventually. So the only question is whether you restrict flexibility by requiring to name the branch first before committing, instead of committing and then naming the branch. So you are talking about "retaining flexibility" in favor of making the tool less user-friendly, when all it would take from the few power-users is to name the branch before committing to it, instead of the other way round. You must be kidding me. Ciao, Dscho ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 0:53 ` Johannes Schindelin @ 2009-10-16 3:00 ` Junio C Hamano 0 siblings, 0 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-16 3:00 UTC (permalink / raw) To: Johannes Schindelin Cc: Nicolas Pitre, Jeff King, Daniel Barkalow, Jay Soffian, git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > In this particular case, I cannot help but notice that commits performed > on a detached HEAD will get lost _unless_ they are somehow put onto a > named branch eventually. So the only question is whether you restrict > flexibility by requiring to name the branch first before committing, > instead of committing and then naming the branch. You are forgetting another important case. You may not even want to keep what you will be committing to the throw-away temporary state. That is why I liked the proposal by James to introduce a third state (i.e. not on local branch, but cannot commit) at the conceptual level, even though as Daniel pointed out and Nico and I concurred later, the implementation may need to be based on the detached HEAD to avoid "git fetch" surprises. You can of course fix it in different ways. The third state could be implemented by pointing at a non local branch ref with HEAD, and then by making fetch refuse to update, just like we refuse a push from side to make the working tree state inconsistent. Either way, confusion arising from accidental (or unintended) detaching would be removed for new users, and that won't have to harm people who need to (because they _are_ used to) be able to work on detached HEAD, no? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 23:09 ` Jeff King 2009-10-14 23:34 ` Nicolas Pitre @ 2009-10-15 7:36 ` James Pickens 2009-10-15 12:54 ` Jakub Narebski ` (3 more replies) 1 sibling, 4 replies; 93+ messages in thread From: James Pickens @ 2009-10-15 7:36 UTC (permalink / raw) To: Jeff King Cc: Junio C Hamano, Nicolas Pitre, Daniel Barkalow, Jay Soffian, git On Wed, Oct 14, 2009 at 4:09 PM, Jeff King <peff@peff.net> wrote: > That makes the most sense to me. If "git checkout" could write metadata > into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout > could record an "ok to commit" bit. And could also be used to change it > after the fact. E.g.: > > $ git checkout --detach=commit origin/master > $ git commit ;# should be ok > > $ git checkout --detach=examine origin/master > $ git commit ;# complain > $ git checkout --detach=commit HEAD > $ git commit ;# ok > > I guess something like "rebase" should detach with "ok to commit", since > it is planning on attaching the commits later. I'm not sure about "git > bisect". I guess probably it should be "not ok to commit" to be on the > safe side, and then somebody can "git checkout --detach=commit" if they > want to. How about not detaching the head at all if the user checks out any ref, and reject commits if he checked out a tag or remote branch. For example: $ git checkout origin/master $ git status # On branch origin/master $ git commit ;# complain $ git checkout v1.0.1 $ git status # On tag v1.0.1 $ git commit ;# complain $ git checkout v1.0.1^0 ;# detach $ git commit ;# ok I think this would help the newbies and wouldn't cost the experts too much. Checking out anything other than a plain ref would still detach the head, and commits on a detached head would still be allowed. Perhaps as an additional safety feature, Git could refuse to switch away from a detached head if the head isn't reachable from any ref, and require -f to override: $ git checkout $sha1 $ git commit $ git checkout master ;# complain $ git checkout -f master ;# ok Maybe I'm missing something and this all can't be done, but it seems simpler than the other options I've seen in this thread. James ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 7:36 ` James Pickens @ 2009-10-15 12:54 ` Jakub Narebski 2009-10-15 14:11 ` Björn Steinbrink 2009-10-15 19:03 ` Nicolas Pitre 2009-10-15 15:36 ` Daniel Barkalow ` (2 subsequent siblings) 3 siblings, 2 replies; 93+ messages in thread From: Jakub Narebski @ 2009-10-15 12:54 UTC (permalink / raw) To: James Pickens Cc: Jeff King, Junio C Hamano, Nicolas Pitre, Daniel Barkalow, Jay Soffian, git James Pickens <jepicken@gmail.com> writes: > How about not detaching the head at all if the user checks out any ref, and > reject commits if he checked out a tag or remote branch. For example: > > $ git checkout origin/master > $ git status > # On branch origin/master > $ git commit ;# complain > > $ git checkout v1.0.1 > $ git status > # On tag v1.0.1 > $ git commit ;# complain > > $ git checkout v1.0.1^0 ;# detach > $ git commit ;# ok > > I think this would help the newbies and wouldn't cost the experts too much. > Checking out anything other than a plain ref would still detach the head, and > commits on a detached head would still be allowed. I think it is a very good idea. This makes it easy to checkout remote-tracking branch or a tag for viewing, something that was (I think) one of problems (use cases) that lead to invention of detached HEAD... and then it turned out that detached HEAD (unnamed branch) is scary for newbie git users. (So the difficulty of having to create new branch or rewind some branch to view non-committable ref was replaced by scary detached HEAD concept.) With this idea there are no problems with git commands that use detached HEAD such as git-bisect (which uses it in viewing mode, but then skips through history, so detached HEAD is a good solution here) or git-rebase (which does committing on detached HEAD for easier aborting and cleanup). Let me propose additional feature: "smart" (context sensitive) warnings, namely that in the following sequence $ git checkout origin/master $ git status # On remote-tracking branch origin/master of remote origin # ... $ git commit 'git commit' would refuse committing on non-heads ref, and propose, beside _always_ proposing detaching HEAD and committing on such detached HEAD (unnamed branch) via "git checkout HEAD^0", or "git checkout --detach [HEAD]": 1. If there is no local branch which follows 'origin/master' (which has 'origin/master' as upstream, which tracks 'origin/master') propose creating it before comitting: $ git checkout -t origin/master 2. If there is single local branch that follows 'origin/master', and it fast-forwards to 'origin/master' propose... errr, something that would mean fast-forwarding this branch and making a commit on local branch that has 'origin/master' as upstream. 3. If there is single local branch that follows 'origin/master', but it has changes / diverges from 'origin/master' we are viewing, propose... hmmm, what then? 4. If there are more than one local branch that has 'origin/master' as upstream, list all those branches in message. > Perhaps as an additional safety feature, Git could refuse to switch > away from a detached head if the head isn't reachable from any ref, > and require -f to override: > > $ git checkout $sha1 > $ git commit > $ git checkout master ;# complain > $ git checkout -f master ;# ok > > Maybe I'm missing something and this all can't be done, but it seems simpler > than the other options I've seen in this thread. I'm not sure about overloading '-f' option, unless we would require doubled '-f' for overriding both safety checks: checkout from detached HEAD, and current meaning of forcing a switch even if index or the working are differs from HEAD. So you would need $ git checkout -f -f master if you are on detached HEAD and have uncommitted changes (dirty tree or dirty index). -- Jakub Narebski Poland ShadeHawk on #git ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 12:54 ` Jakub Narebski @ 2009-10-15 14:11 ` Björn Steinbrink 2009-10-15 19:03 ` Nicolas Pitre 1 sibling, 0 replies; 93+ messages in thread From: Björn Steinbrink @ 2009-10-15 14:11 UTC (permalink / raw) To: Jakub Narebski Cc: James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Daniel Barkalow, Jay Soffian, git On 2009.10.15 05:54:52 -0700, Jakub Narebski wrote: > James Pickens <jepicken@gmail.com> writes: > > Perhaps as an additional safety feature, Git could refuse to switch > > away from a detached head if the head isn't reachable from any ref, > > and require -f to override: > > > > $ git checkout $sha1 > > $ git commit > > $ git checkout master ;# complain > > $ git checkout -f master ;# ok > > > > Maybe I'm missing something and this all can't be done, but it seems simpler > > than the other options I've seen in this thread. > > I'm not sure about overloading '-f' option, unless we would require > doubled '-f' for overriding both safety checks: checkout from detached > HEAD, and current meaning of forcing a switch even if index or the > working are differs from HEAD. So you would need > > $ git checkout -f -f master > > if you are on detached HEAD and have uncommitted changes (dirty tree > or dirty index). A dirty index/worktree doesn't necessarily stop you from checking out a different branch head/commit. Only if you have uncommitted changes to a file that also has changes between HEAD and <other_branch>, git refuses to switch. And if you want to keep your uncommitted changes, you want to use -m (3-way merge), not -f (drop changes). git checkout -f foo ~= git reset --hard && git checkout foo So -f is most likely _not_ the flag one wants to overload. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 12:54 ` Jakub Narebski 2009-10-15 14:11 ` Björn Steinbrink @ 2009-10-15 19:03 ` Nicolas Pitre 1 sibling, 0 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-15 19:03 UTC (permalink / raw) To: Jakub Narebski Cc: James Pickens, Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Thu, 15 Oct 2009, Jakub Narebski wrote: > James Pickens <jepicken@gmail.com> writes: > > > I think this would help the newbies and wouldn't cost the experts too much. > > Checking out anything other than a plain ref would still detach the head, and > > commits on a detached head would still be allowed. > > I think it is a very good idea. > > This makes it easy to checkout remote-tracking branch or a tag for > viewing, something that was (I think) one of problems (use cases) that > lead to invention of detached HEAD... and then it turned out that > detached HEAD (unnamed branch) is scary for newbie git users. (So the > difficulty of having to create new branch or rewind some branch to > view non-committable ref was replaced by scary detached HEAD concept.) I don't think detached head is scary at all (unless viewed in another context other than git) but if that encounter can be kept away from most users without denying its use then all for the better. > With this idea there are no problems with git commands that use > detached HEAD such as git-bisect (which uses it in viewing mode, but > then skips through history, so detached HEAD is a good solution here) > or git-rebase (which does committing on detached HEAD for easier > aborting and cleanup). I do like and actively use manual committing on a detached HEAD as well, so please let's not forget about that use case. > Let me propose additional feature: "smart" (context sensitive) > warnings, namely that in the following sequence > > $ git checkout origin/master > $ git status > # On remote-tracking branch origin/master of remote origin > # ... Sure. > $ git commit > > 'git commit' would refuse committing on non-heads ref, and propose, > beside _always_ proposing detaching HEAD and committing on such > detached HEAD (unnamed branch) via "git checkout HEAD^0", or > "git checkout --detach [HEAD]": ... or the current "this is not a local branch -- use checkout -b to create one" warning, just like what we have today when checking out a tag or remote branch, except that the warning is deferred to the commit operation which in fact might even not take place. > 1. If there is no local branch which follows 'origin/master' > (which has 'origin/master' as upstream, which tracks 'origin/master') > propose creating it before comitting: > > $ git checkout -t origin/master > > 2. If there is single local branch that follows 'origin/master', > and it fast-forwards to 'origin/master' propose... > errr, something that would mean fast-forwarding this branch > and making a commit on local branch that has 'origin/master' > as upstream. > > 3. If there is single local branch that follows 'origin/master', but > it has changes / diverges from 'origin/master' we are viewing, > propose... hmmm, what then? > > 4. If there are more than one local branch that has 'origin/master' > as upstream, list all those branches in message. I wouldn't go too far in that direction though. Too many suggestions would simply bring back confusion to the new user who at that point might not even understand yet what all the different concepts are. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 7:36 ` James Pickens 2009-10-15 12:54 ` Jakub Narebski @ 2009-10-15 15:36 ` Daniel Barkalow 2009-10-15 16:29 ` Michael J Gruber 2009-10-15 19:07 ` Nicolas Pitre 2009-10-15 18:51 ` Nicolas Pitre 2009-10-15 19:31 ` Daniel Barkalow 3 siblings, 2 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-15 15:36 UTC (permalink / raw) To: James Pickens; +Cc: Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On Thu, 15 Oct 2009, James Pickens wrote: > On Wed, Oct 14, 2009 at 4:09 PM, Jeff King <peff@peff.net> wrote: > > That makes the most sense to me. If "git checkout" could write metadata > > into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout > > could record an "ok to commit" bit. And could also be used to change it > > after the fact. E.g.: > > > > $ git checkout --detach=commit origin/master > > $ git commit ;# should be ok > > > > $ git checkout --detach=examine origin/master > > $ git commit ;# complain > > $ git checkout --detach=commit HEAD > > $ git commit ;# ok > > > > I guess something like "rebase" should detach with "ok to commit", since > > it is planning on attaching the commits later. I'm not sure about "git > > bisect". I guess probably it should be "not ok to commit" to be on the > > safe side, and then somebody can "git checkout --detach=commit" if they > > want to. > > How about not detaching the head at all if the user checks out any ref, and > reject commits if he checked out a tag or remote branch. For example: > > $ git checkout origin/master > $ git status > # On branch origin/master > $ git commit ;# complain > > $ git checkout v1.0.1 > $ git status > # On tag v1.0.1 > $ git commit ;# complain > > $ git checkout v1.0.1^0 ;# detach > $ git commit ;# ok > > I think this would help the newbies and wouldn't cost the experts too much. > Checking out anything other than a plain ref would still detach the head, and > commits on a detached head would still be allowed. I think reducing users' exposure to the "detached HEAD" state would just make it take longer for them to find that state familiar. It's not like the concept is actually very difficult or unusual. CVS has it as "cvs checkout -r <something>" or "cvs checkout -D <something>"; SVN has it as "svn checkout -r <something>". It was weird and scary in CVS if you did it (it was "sticky tags", and you had to find a different option to get back to normal), but SVN is easier ("svn checkout -r HEAD"). I think the description used in CVS and SVN (and, I think, others) is that you're not at the HEAD revision. I think they both account for the state where you've checked out the revision by number that's the latest revision, but you still can't grow the branch because you can't simultaneously stay on r1000 (as requested explicitly) and add a new commit. So maybe the right explanation is: $ git checkout master; git branch * master $ git checkout origin/master; git branch * origin/master (not at head) $ git checkout 123cafe^5; git branch * 123cafe^5 (not at head) $ git checkout HEAD^2; git branch * 123cafe^5^2 $ git commit; git branch * (temporary branch) Then we can say that one way that git is different from SVN is that all branches of other repositories are read-only, and you can't be at the head when you're on them (because the head of those branches are in different repositories); instead you grow the history locally, and you tell the remote branch to adopt your history. > Perhaps as an additional safety feature, Git could refuse to switch away > from a detached head if the head isn't reachable from any ref As far as I know, people don't actually seem to lose stuff this way. In part, that's because they get scared before they get there; in part, that's because they just don't think to go there; and in part, we tell them how to recover stuff at that point (using the ref log or the sha1). -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 15:36 ` Daniel Barkalow @ 2009-10-15 16:29 ` Michael J Gruber 2009-10-15 19:07 ` Nicolas Pitre 1 sibling, 0 replies; 93+ messages in thread From: Michael J Gruber @ 2009-10-15 16:29 UTC (permalink / raw) To: Daniel Barkalow Cc: James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git Daniel Barkalow venit, vidit, dixit 15.10.2009 17:36: > On Thu, 15 Oct 2009, James Pickens wrote: > >> On Wed, Oct 14, 2009 at 4:09 PM, Jeff King <peff@peff.net> wrote: >>> That makes the most sense to me. If "git checkout" could write metadata >>> into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout >>> could record an "ok to commit" bit. And could also be used to change it >>> after the fact. E.g.: >>> >>> $ git checkout --detach=commit origin/master >>> $ git commit ;# should be ok >>> >>> $ git checkout --detach=examine origin/master >>> $ git commit ;# complain >>> $ git checkout --detach=commit HEAD >>> $ git commit ;# ok >>> >>> I guess something like "rebase" should detach with "ok to commit", since >>> it is planning on attaching the commits later. I'm not sure about "git >>> bisect". I guess probably it should be "not ok to commit" to be on the >>> safe side, and then somebody can "git checkout --detach=commit" if they >>> want to. >> >> How about not detaching the head at all if the user checks out any ref, and >> reject commits if he checked out a tag or remote branch. For example: >> >> $ git checkout origin/master >> $ git status >> # On branch origin/master >> $ git commit ;# complain >> >> $ git checkout v1.0.1 >> $ git status >> # On tag v1.0.1 >> $ git commit ;# complain >> >> $ git checkout v1.0.1^0 ;# detach >> $ git commit ;# ok >> >> I think this would help the newbies and wouldn't cost the experts too much. >> Checking out anything other than a plain ref would still detach the head, and >> commits on a detached head would still be allowed. > > I think reducing users' exposure to the "detached HEAD" state would just > make it take longer for them to find that state familiar. Yep. Which is why I keep suggesting that git clone does not create any local branches at all ;) > It's not like the concept is actually very difficult or unusual. CVS has > it as "cvs checkout -r <something>" or "cvs checkout -D <something>"; SVN > has it as "svn checkout -r <something>". It was weird and scary in CVS if > you did it (it was "sticky tags", and you had to find a different option > to get back to normal), but SVN is easier ("svn checkout -r HEAD"). svn up -r HEAD > I think the description used in CVS and SVN (and, I think, others) is that > you're not at the HEAD revision. I think they both account for the state > where you've checked out the revision by number that's the latest > revision, but you still can't grow the branch because you can't > simultaneously stay on r1000 (as requested explicitly) and add a new > commit. I'd say the fundamental difference is that in CVS and SVN, there is always only one "tip", which they call HEAD. This is also why revision numbers make sense. In git and hg there can be many tips (branch heads) from which to grow the DAG. Heck, you can grow a new one from any commit ;) > So maybe the right explanation is: > > $ git checkout master; git branch > * master > $ git checkout origin/master; git branch > * origin/master (not at head) Ouch, please don't. HEAD has a completely different meaning in git. I know you know, of course. > $ git checkout 123cafe^5; git branch > * 123cafe^5 (not at head) > $ git checkout HEAD^2; git branch > * 123cafe^5^2 > $ git commit; git branch > * (temporary branch) > > Then we can say that one way that git is different from SVN is that all > branches of other repositories are read-only, and you can't be at the > head when you're on them (because the head of those branches are in > different repositories); instead you grow the history locally, and you > tell the remote branch to adopt your history. You can change your refs/remotes/origin/master, of course, it's just by convention (for a good reason) that git treats them as read-only, and porc. respects that. git's branches are simply completely different, they're movable tags, and I think that's one point new users *have* to grok. Once they're over this then even detached heads are a natural thing. >> Perhaps as an additional safety feature, Git could refuse to switch away >> from a detached head if the head isn't reachable from any ref > > As far as I know, people don't actually seem to lose stuff this way. In > part, that's because they get scared before they get there; in part, > that's because they just don't think to go there; and in part, we tell > them how to recover stuff at that point (using the ref log or the sha1). Maybe we just don't scare them enough yet :) Michael ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 15:36 ` Daniel Barkalow 2009-10-15 16:29 ` Michael J Gruber @ 2009-10-15 19:07 ` Nicolas Pitre 2009-10-15 19:22 ` Daniel Barkalow 1 sibling, 1 reply; 93+ messages in thread From: Nicolas Pitre @ 2009-10-15 19:07 UTC (permalink / raw) To: Daniel Barkalow Cc: James Pickens, Jeff King, Junio C Hamano, Jay Soffian, git On Thu, 15 Oct 2009, Daniel Barkalow wrote: > I think the description used in CVS and SVN (and, I think, others) is that > you're not at the HEAD revision. I think they both account for the state > where you've checked out the revision by number that's the latest > revision, but you still can't grow the branch because you can't > simultaneously stay on r1000 (as requested explicitly) and add a new > commit. > > So maybe the right explanation is: > > $ git checkout master; git branch > * master > $ git checkout origin/master; git branch > * origin/master (not at head) > $ git checkout 123cafe^5; git branch > * 123cafe^5 (not at head) I think this is wrong. Git has multiple heads, and insisting on "not at head" would be extremely confusing. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 19:07 ` Nicolas Pitre @ 2009-10-15 19:22 ` Daniel Barkalow 2009-10-15 22:56 ` Thomas Rast 0 siblings, 1 reply; 93+ messages in thread From: Daniel Barkalow @ 2009-10-15 19:22 UTC (permalink / raw) To: Nicolas Pitre; +Cc: James Pickens, Jeff King, Junio C Hamano, Jay Soffian, git On Thu, 15 Oct 2009, Nicolas Pitre wrote: > On Thu, 15 Oct 2009, Daniel Barkalow wrote: > > > I think the description used in CVS and SVN (and, I think, others) is that > > you're not at the HEAD revision. I think they both account for the state > > where you've checked out the revision by number that's the latest > > revision, but you still can't grow the branch because you can't > > simultaneously stay on r1000 (as requested explicitly) and add a new > > commit. > > > > So maybe the right explanation is: > > > > $ git checkout master; git branch > > * master > > $ git checkout origin/master; git branch > > * origin/master (not at head) > > $ git checkout 123cafe^5; git branch > > * 123cafe^5 (not at head) > > I think this is wrong. Git has multiple heads, and insisting on "not at > head" would be extremely confusing. Maybe "(not at a head)"? Git does have multiple heads, but what's checked out isn't one of them, and that's actually the point. -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 19:22 ` Daniel Barkalow @ 2009-10-15 22:56 ` Thomas Rast 0 siblings, 0 replies; 93+ messages in thread From: Thomas Rast @ 2009-10-15 22:56 UTC (permalink / raw) To: Daniel Barkalow Cc: Nicolas Pitre, James Pickens, Jeff King, Junio C Hamano, Jay Soffian, git Daniel Barkalow wrote: > On Thu, 15 Oct 2009, Nicolas Pitre wrote: > > > On Thu, 15 Oct 2009, Daniel Barkalow wrote: > > > > > I think the description used in CVS and SVN (and, I think, others) is that > > > you're not at the HEAD revision. [...] > > > * origin/master (not at head) > > > $ git checkout 123cafe^5; git branch > > > * 123cafe^5 (not at head) > > > > I think this is wrong. Git has multiple heads, and insisting on "not at > > head" would be extremely confusing. > > Maybe "(not at a head)"? Git does have multiple heads, but what's checked > out isn't one of them, and that's actually the point. Please don't reuse 'head' (even lowercase) in this context/meaning. I see enough people coming to IRC who are confused about the fact that they checked out some old commit, hence HEAD is just that, but they refer to the *newest* commit on whatever branch they like most as HEAD because that's what it means in SVN. Now imagine having to explain to them that their (SVN) 'HEAD' is not the same as git's 'HEAD', but can rightly be considered the equivalent of master's 'head'; and that furthermore, you are always at 'HEAD' but not always at 'head'. I think in this case '(detached)' would be more consistent with current terminology, though we may of course try to change it. (I've tried to consistently use 'tip' in the branch tip meaning, admittedly without knowing exactly how this intersects with mercurial's definition of the term.) -- Thomas Rast trast@{inf,student}.ethz.ch ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 7:36 ` James Pickens 2009-10-15 12:54 ` Jakub Narebski 2009-10-15 15:36 ` Daniel Barkalow @ 2009-10-15 18:51 ` Nicolas Pitre 2009-10-15 19:52 ` Junio C Hamano 2009-10-15 19:31 ` Daniel Barkalow 3 siblings, 1 reply; 93+ messages in thread From: Nicolas Pitre @ 2009-10-15 18:51 UTC (permalink / raw) To: James Pickens Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git On Thu, 15 Oct 2009, James Pickens wrote: > On Wed, Oct 14, 2009 at 4:09 PM, Jeff King <peff@peff.net> wrote: > > That makes the most sense to me. If "git checkout" could write metadata > > into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout > > could record an "ok to commit" bit. And could also be used to change it > > after the fact. E.g.: > > > > $ git checkout --detach=commit origin/master > > $ git commit ;# should be ok > > > > $ git checkout --detach=examine origin/master > > $ git commit ;# complain > > $ git checkout --detach=commit HEAD > > $ git commit ;# ok > > > > I guess something like "rebase" should detach with "ok to commit", since > > it is planning on attaching the commits later. I'm not sure about "git > > bisect". I guess probably it should be "not ok to commit" to be on the > > safe side, and then somebody can "git checkout --detach=commit" if they > > want to. > > How about not detaching the head at all if the user checks out any ref, and > reject commits if he checked out a tag or remote branch. For example: > > $ git checkout origin/master > $ git status > # On branch origin/master > $ git commit ;# complain > > $ git checkout v1.0.1 > $ git status > # On tag v1.0.1 > $ git commit ;# complain > > $ git checkout v1.0.1^0 ;# detach > $ git commit ;# ok > > I think this would help the newbies and wouldn't cost the experts too much. I agree. > Checking out anything other than a plain ref would still detach the > head, and commits on a detached head would still be allowed. Perhaps > as an additional safety feature, Git could refuse to switch away from > a detached head if the head isn't reachable from any ref, and require > -f to override: > > $ git checkout $sha1 > $ git commit > $ git checkout master ;# complain > $ git checkout -f master ;# ok Nah. This is obnoxious. The usual "this is not a local branch" warning could be displayed at that point, and if one really ignores the warning then any commit made that way is always reachable through the reflog. You would have had to work a bit harder to detach HEAD already anyway, so at that point you're not supposed to be such a newbie anymore. > Maybe I'm missing something and this all can't be done, but it seems simpler > than the other options I've seen in this thread. It is indeed simpler. It makes the checkout command less verbose as well. Only the commit command would need to warn the user and only if a forbidden operation is attempted (like committing on a non refs/heads/*). I think I like this. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 18:51 ` Nicolas Pitre @ 2009-10-15 19:52 ` Junio C Hamano 2009-10-15 21:26 ` Jeff King 0 siblings, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-15 19:52 UTC (permalink / raw) To: Nicolas Pitre; +Cc: James Pickens, Jeff King, Daniel Barkalow, Jay Soffian, git Nicolas Pitre <nico@fluxnic.net> writes: > It is indeed simpler. It makes the checkout command less verbose as > well. Only the commit command would need to warn the user and only if a > forbidden operation is attempted (like committing on a non > refs/heads/*). I think I like this. I like James's suggestion to allow us to store refs other than refs/heads/ in HEAD to denote this state, and keep commit and reset from updating such a ref through updating HEAD. We have code to prevent HEAD from pointing at anywhere outside refs/heads/ and that may even be an isolated single codepath we need to tweak. But I am reasonably sure that the layers above these core-level routines have their own checks to make sure HEAD is either detached or points at refs/heads/ somewhere; we would need to identify and change them as well. Also things like "git branch" need to be told that HEAD may point outside of refs/heads/ now to adjust their output style accordingly. They may probably strip refs/heads/ (or 11 bytes) assuming that attached HEAD will never point outside the local branch hierarchy. So I expect there will be tons of tiny fallouts from a change like that, but still it is conceptually simpler, and it would reduce the scope of detached HEAD to a temporary state that is not even worth being named with a branch name, which is exactly what it is. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 19:52 ` Junio C Hamano @ 2009-10-15 21:26 ` Jeff King 2009-10-15 21:54 ` Junio C Hamano 0 siblings, 1 reply; 93+ messages in thread From: Jeff King @ 2009-10-15 21:26 UTC (permalink / raw) To: Junio C Hamano Cc: Nicolas Pitre, James Pickens, Daniel Barkalow, Jay Soffian, git On Thu, Oct 15, 2009 at 12:52:55PM -0700, Junio C Hamano wrote: > I like James's suggestion to allow us to store refs other than refs/heads/ > in HEAD to denote this state, and keep commit and reset from updating such > a ref through updating HEAD. Didn't we already consider and reject this the first time around? For example, this thread has a ton of stuff about how we shouldn't prevent people from making commits on the wandering state: http://thread.gmane.org/gmane.comp.version-control.git/35777/focus=35835 And here's me even advocating this exact strategy (and I'm sure I didn't think of it; it's probably discussed elsewhere, too): http://thread.gmane.org/gmane.comp.version-control.git/35777/focus=35858 Not that I am not necessarily complaining, but I just hope this decision is "with new-found knowledge we are revisiting this decision" and not "we totally forgot about what came before". -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 21:26 ` Jeff King @ 2009-10-15 21:54 ` Junio C Hamano 2009-10-15 22:08 ` Junio C Hamano ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-15 21:54 UTC (permalink / raw) To: Jeff King Cc: Junio C Hamano, Nicolas Pitre, James Pickens, Daniel Barkalow, Jay Soffian, git Jeff King <peff@peff.net> writes: > On Thu, Oct 15, 2009 at 12:52:55PM -0700, Junio C Hamano wrote: > >> I like James's suggestion to allow us to store refs other than refs/heads/ >> in HEAD to denote this state, and keep commit and reset from updating such >> a ref through updating HEAD. > > Didn't we already consider and reject this the first time around? For > example, this thread has a ton of stuff about how we shouldn't prevent > people from making commits on the wandering state: > > http://thread.gmane.org/gmane.comp.version-control.git/35777/focus=35835 > > And here's me even advocating this exact strategy (and I'm sure I didn't > think of it; it's probably discussed elsewhere, too): > > http://thread.gmane.org/gmane.comp.version-control.git/35777/focus=35858 > > Not that I am not necessarily complaining, but I just hope this decision > is "with new-found knowledge we are revisiting this decision" and not > "we totally forgot about what came before". Maybe we are reading different messages in the same message. My understanding of James's suggestion is: (1) "git checkout $token" makes HEAD point at the refname dwim_ref() expands $token to, iff dwim_ref() is happy, and otherwise detaches HEAD; (2) "git commit" (and other things like "git reset HEAD^" that updates underlying ref thru updates to HEAD when HEAD is a symref) rejects when HEAD points at a ref outside refs/heads/, but works when HEAD points at a local branch, or when HEAD is detached. As a consequence: $ git checkout v1.6.5 ;# does not detach, cannot update $ git symbolic-ref HEAD refs/tags/v1.6.5 $ git checkout origin/next ;# ditto $ git symbolic-ref HEAD refs/remotes/origin/next These are often done by sightseers, and we can add instructions to fork and record upon an attempt to "git commit". As a bonus, we get Daniel's extra information for detached HEAD for free, as we can just read HEAD and learn what it points at. We need to design what "git branch" should say in this case. This is backward incompatible, and makes what experts are used to do slightly cumbersome to spell, i.e. $ git checkout v1.6.5^0 ;# detaches and can commit $ git checkout origin/next^0 ;# ditto $ git checkout $(git merge-base master sp/smart-http) ;# ditto These detach, and I can apply the updates series to the same base as the previous round on an unnamed branch. So in other words, the semantics for detached HEAD case does not change at all. We never forbid committing or resetting while on detached HEAD, as it is meant to be an easy way to get an unnamed throw-away state that is not even worth coming up with a unique temporary branch name, and I do not think the above contradicts with what was said in 35835. We used to have only two states on HEAD: either on a local branch or detached. James is introducing another state: on a ref that is not a local branch. As that is useful for common sightseer tasks, we can afford to forbid committing or updating for safety and we do not have to worry about hurting the established usefulness of how detached HEAD works. One drawback is that you cannot be in this sightseeing state without having a ref. You can have "look-but-not-touch" checkout on origin/next or origin/master, but you cannot sightsee the parent of origin/next the same way (it would detach). I do not know if it is a big deal, though. If it is very important to support: $ git checkout --look-but-not-touch origin/next^ then James's approach would not be very useful, as we do have to detach HEAD and implement the "do not touch" logic for detached HEAD state anyway, so we might just use the same logic we would use for origin/next^ when checking out origin/next itself. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 21:54 ` Junio C Hamano @ 2009-10-15 22:08 ` Junio C Hamano 2009-10-15 23:16 ` Nicolas Pitre 2009-10-15 23:47 ` James Pickens 2009-10-15 22:16 ` Jeff King 2009-10-16 4:29 ` Björn Steinbrink 2 siblings, 2 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-15 22:08 UTC (permalink / raw) To: Junio C Hamano Cc: Jeff King, Nicolas Pitre, James Pickens, Daniel Barkalow, Jay Soffian, git Junio C Hamano <gitster@pobox.com> writes: > $ git checkout origin/next ;# ditto > $ git symbolic-ref HEAD > refs/remotes/origin/next Ok, after reading Daniel's message to remind us that "git fetch" after this will get us into trouble, I agree that detaching HEAD is inevitable. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 22:08 ` Junio C Hamano @ 2009-10-15 23:16 ` Nicolas Pitre 2009-10-15 23:47 ` James Pickens 1 sibling, 0 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-15 23:16 UTC (permalink / raw) To: Junio C Hamano Cc: Jeff King, James Pickens, Daniel Barkalow, Jay Soffian, git On Thu, 15 Oct 2009, Junio C Hamano wrote: > Junio C Hamano <gitster@pobox.com> writes: > > > $ git checkout origin/next ;# ditto > > $ git symbolic-ref HEAD > > refs/remotes/origin/next > > Ok, after reading Daniel's message to remind us that "git fetch" after > this will get us into trouble, I agree that detaching HEAD is inevitable. Either the fetch should be refused just like a commit would, or HEAD gets detached automatically in that case. Probably the former would be less confusing, otherwise the user might expect to see the updated remote branch after the fetch and not understand that a detached HEAD remained on the previous remote branch state. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 22:08 ` Junio C Hamano 2009-10-15 23:16 ` Nicolas Pitre @ 2009-10-15 23:47 ` James Pickens 2009-10-16 0:34 ` Nicolas Pitre ` (2 more replies) 1 sibling, 3 replies; 93+ messages in thread From: James Pickens @ 2009-10-15 23:47 UTC (permalink / raw) To: Junio C Hamano Cc: Jeff King, Nicolas Pitre, Daniel Barkalow, Jay Soffian, git On Thu, Oct 15, 2009 at 3:08 PM, Junio C Hamano <gitster@pobox.com> wrote: > Junio C Hamano <gitster@pobox.com> writes: > >> $ git checkout origin/next ;# ditto >> $ git symbolic-ref HEAD >> refs/remotes/origin/next > > Ok, after reading Daniel's message to remind us that "git fetch" after > this will get us into trouble, I agree that detaching HEAD is inevitable. Some people liked the idea, so let's not give up just yet. Here are a few things Git could do when a fetch wants to update the currently checked out branch: 1. Refuse the fetch. 2. Update the ref, leaving the user with a work tree and index that don't match their HEAD. 3. Detach the HEAD, then update the ref. 4. Update the ref, then check it out. Option 1 is ok, as long as the "next step" is not too complicated. It's no good if the user has to checkout a different branch, then fetch, then checkout the original branch again. Option 2 is crap. Option 3 seems reasonable, but it might be just as scary/confusing to newbies as the current behavior, so I don't think it should be the default. Option 4 also seems reasonable, but you run into problems if the user had changed the index or work tree. In that case Git could do 'checkout --merge' automatically. This option is also less "pure" since it lets 'git fetch' modify the index and work tree. So how about this: * 'git fetch' refuses the fetch by default. * 'git fetch --detach' detaches HEAD, then updates the ref * 'git pull' detaches HEAD, updates the ref, then checks out the new ref with --merge. BTW I'm not convinced this is any better than the current UI... just thinking out loud. And I find it more than a little depressing that most of these ideas have already been discussed almost 3 years ago (thanks Jeff for the pointer). James ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 23:47 ` James Pickens @ 2009-10-16 0:34 ` Nicolas Pitre 2009-10-16 0:43 ` Johannes Schindelin 2009-10-16 5:03 ` Björn Steinbrink 2 siblings, 0 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-16 0:34 UTC (permalink / raw) To: James Pickens Cc: Junio C Hamano, Jeff King, Daniel Barkalow, Jay Soffian, git On Thu, 15 Oct 2009, James Pickens wrote: > BTW I'm not convinced this is any better than the current UI... just > thinking out loud. I concur with that. > And I find it more than a little depressing that most > of these ideas have already been discussed almost 3 years ago (thanks Jeff > for the pointer). Rehashing them from time to time is not necessarily a bad idea. Maybe something better might (or not) turn up this time. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 23:47 ` James Pickens 2009-10-16 0:34 ` Nicolas Pitre @ 2009-10-16 0:43 ` Johannes Schindelin 2009-10-16 5:03 ` Björn Steinbrink 2 siblings, 0 replies; 93+ messages in thread From: Johannes Schindelin @ 2009-10-16 0:43 UTC (permalink / raw) To: James Pickens Cc: Junio C Hamano, Jeff King, Nicolas Pitre, Daniel Barkalow, Jay Soffian, git Hi, On Thu, 15 Oct 2009, James Pickens wrote: > On Thu, Oct 15, 2009 at 3:08 PM, Junio C Hamano <gitster@pobox.com> wrote: > > Junio C Hamano <gitster@pobox.com> writes: > > > >> $ git checkout origin/next ;# ditto > >> $ git symbolic-ref HEAD > >> refs/remotes/origin/next > > > > Ok, after reading Daniel's message to remind us that "git fetch" after > > this will get us into trouble, I agree that detaching HEAD is inevitable. > > Some people liked the idea, so let's not give up just yet. Here are a few > things Git could do when a fetch wants to update the currently checked out > branch: > > 1. Refuse the fetch. > 2. Update the ref, leaving the user with a work tree and index that don't > match their HEAD. > 3. Detach the HEAD, then update the ref. > 4. Update the ref, then check it out. Everything but 1 and 4 would blatantly violate the law of the Least Surprise. And that very much includes what our beloved maintainer proposes. BTW I appreciate that finally a few users join discussion. It felt awfully lonely for a while. Ciao, Dscho ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 23:47 ` James Pickens 2009-10-16 0:34 ` Nicolas Pitre 2009-10-16 0:43 ` Johannes Schindelin @ 2009-10-16 5:03 ` Björn Steinbrink 2 siblings, 0 replies; 93+ messages in thread From: Björn Steinbrink @ 2009-10-16 5:03 UTC (permalink / raw) To: James Pickens Cc: Junio C Hamano, Jeff King, Nicolas Pitre, Daniel Barkalow, Jay Soffian, git On 2009.10.15 16:47:57 -0700, James Pickens wrote: > On Thu, Oct 15, 2009 at 3:08 PM, Junio C Hamano <gitster@pobox.com> wrote: > > Junio C Hamano <gitster@pobox.com> writes: > > > >> $ git checkout origin/next ;# ditto > >> $ git symbolic-ref HEAD > >> refs/remotes/origin/next > > > > Ok, after reading Daniel's message to remind us that "git fetch" after > > this will get us into trouble, I agree that detaching HEAD is inevitable. > > Some people liked the idea, so let's not give up just yet. Here are a few > things Git could do when a fetch wants to update the currently checked out > branch: > > 1. Refuse the fetch. > 2. Update the ref, leaving the user with a work tree and index that don't > match their HEAD. > 3. Detach the HEAD, then update the ref. > 4. Update the ref, then check it out. > > Option 1 is ok, as long as the "next step" is not too complicated. It's no > good if the user has to checkout a different branch, then fetch, then > checkout the original branch again. Not good. It makes "git fetch; git log ..origin/foo" impossible. And that's IMHO a very useful thing for people that just want to follow things and look at what happens. > Option 2 is crap. Agreed. > Option 3 seems reasonable, but it might be just as scary/confusing to > newbies as the current behavior, so I don't think it should be the default. Doesn't seem very good to me. The idea was to stop people from accidently getting on a detached HEAD, if common operations like "fetch" now suddenly detach HEAD, that's _worse_ than before. And for a single-branch remote, even "git pull" may detach HEAD then: git init; git remote add -f -t master origin git://... git checkout origin/master *wait* git pull # Will work, as the fetch refspec is not a glob But that "pull" does: git fetch origin refs/heads/master:refs/remotes/origin/master Which detaches HEAD before merging/fast-forwarding. Bad. And seeing that the requests for "clone just a single branch" seem to increase in #git, I guess that such non-globbing refspecs for remote.origin.fetch might become more common in the future. > Option 4 also seems reasonable, but you run into problems if the user had > changed the index or work tree. In that case Git could do 'checkout > --merge' automatically. This option is also less "pure" since it lets 'git > fetch' modify the index and work tree. Same as for option 1, it kills "git fetch; git log ..origin/foo". And that would basically turn "fetch" into a hypothetical "pull --reset". That's IMHO better done in a separate command. > So how about this: > * 'git fetch' refuses the fetch by default. > * 'git fetch --detach' detaches HEAD, then updates the ref > * 'git pull' detaches HEAD, updates the ref, then checks out the new ref > with --merge. "fetch --detach" doesn't feel right to me. Wrong class of commands to have such an option. And I'm not sure about adding a third mode to "pull" (besides "merge" and "rebase") that only triggers for special cases. Again, I'd prefer a separate command. If we store "where did I come from" instead of just "where am I" in HEAD when detached, those problems don't seem to show up (but just storing that information correctly seems hard enough, see the other mail I wrote a few minutes ago). "git fetch" just updates the remote tracking branch, you stay at where you are, "git log ..origin/foo" keeps working. It could give a special hint that you might want to use "git checkout origin/foo" or "git new-command" to update your working tree to the newest version, when your working tree is based upon an old version of that remote tracking branch. And "git pull" might perform a fast-forward automatically (figuring out the right remote from the extra info in HEAD), but refuse to do merges (if upstream has been rewritten), pointing the user to "git checkout" or "git new-command". (Interestingly, "pull --rebase" wouldn't suffer from such history rewriting, as it looks at the reflog for the remote tracking branch, but I guess a working "git pull --rebase" while "git pull" fails is bound to cause major user confusion). "git new-command" could act like "svn up", doing a fetch and a "checkout --merge <remote_tracking_branch>" to just get the user up-to-date keeping local uncommitted modifications. I can't tell why, but my feeling is that this should be a new command, and not part of pull, as said above. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 21:54 ` Junio C Hamano 2009-10-15 22:08 ` Junio C Hamano @ 2009-10-15 22:16 ` Jeff King 2009-10-15 22:17 ` Jeff King 2009-10-16 4:29 ` Björn Steinbrink 2 siblings, 1 reply; 93+ messages in thread From: Jeff King @ 2009-10-15 22:16 UTC (permalink / raw) To: Junio C Hamano Cc: Nicolas Pitre, James Pickens, Daniel Barkalow, Jay Soffian, git On Thu, Oct 15, 2009 at 02:54:18PM -0700, Junio C Hamano wrote: > Maybe we are reading different messages in the same message. > > My understanding of James's suggestion is: > > (1) "git checkout $token" makes HEAD point at the refname dwim_ref() > expands $token to, iff dwim_ref() is happy, and otherwise detaches > HEAD; > > (2) "git commit" (and other things like "git reset HEAD^" that updates > underlying ref thru updates to HEAD when HEAD is a symref) rejects > when HEAD points at a ref outside refs/heads/, but works when HEAD > points at a local branch, or when HEAD is detached. Right. I thought the idea of "don't complain at checkout time, but complain at commit" had been considered and rejected. But I guess you could argue that the difference between this and the original discussion is that we are going to have _both_ the detached HEAD state and the "refs/tags/* in HEAD" state, and treat them differently. I feel like the latter idea was discussed in more detail (I made reference to it in the latter email I linked to, but I don't think that was the origin of it), but I can't seem to find any discussion. So I will buy that this is somewhat of a new idea. I am still confused about what happens with this, though: $ git checkout origin/next $ git fetch ;# updates origin/next Do we refuse the fetch? Does the user now have a working tree and index that doesn't match their HEAD? > This is backward incompatible, and makes what experts are used to do > slightly cumbersome to spell, i.e. > > $ git checkout v1.6.5^0 ;# detaches and can commit > $ git checkout origin/next^0 ;# ditto > $ git checkout $(git merge-base master sp/smart-http) ;# ditto I think it is less cumbersome if we add "git checkout -d v1.6.5" (well, same number of characters, but a lot less ugly). Assuming that the rest of it is a good idea. -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 22:16 ` Jeff King @ 2009-10-15 22:17 ` Jeff King 0 siblings, 0 replies; 93+ messages in thread From: Jeff King @ 2009-10-15 22:17 UTC (permalink / raw) To: Junio C Hamano Cc: Nicolas Pitre, James Pickens, Daniel Barkalow, Jay Soffian, git On Thu, Oct 15, 2009 at 06:16:57PM -0400, Jeff King wrote: > So I will buy that this is somewhat of a new idea. I am still confused > about what happens with this, though: > > $ git checkout origin/next > $ git fetch ;# updates origin/next > > Do we refuse the fetch? Does the user now have a working tree and index > that doesn't match their HEAD? OK, nevermind about this, we just crossed emails. -Peff ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 21:54 ` Junio C Hamano 2009-10-15 22:08 ` Junio C Hamano 2009-10-15 22:16 ` Jeff King @ 2009-10-16 4:29 ` Björn Steinbrink 2009-10-16 6:02 ` Daniel Barkalow 2 siblings, 1 reply; 93+ messages in thread From: Björn Steinbrink @ 2009-10-16 4:29 UTC (permalink / raw) To: Junio C Hamano Cc: Jeff King, Nicolas Pitre, James Pickens, Daniel Barkalow, Jay Soffian, git On 2009.10.15 14:54:18 -0700, Junio C Hamano wrote: > If it is very important to support: > > $ git checkout --look-but-not-touch origin/next^ > > then James's approach would not be very useful, as we do have to detach > HEAD and implement the "do not touch" logic for detached HEAD state > anyway, so we might just use the same logic we would use for origin/next^ > when checking out origin/next itself. I don't have any numbers backing this up, but my gut feeling says that most cases of "Where have my commits gone?" that I have seen on #git were due to "git checkout HEAD~2"-like actions. Either because the user assumed SVN-like behaviour (you can't commit until you do "svn up", like "git reset --merge HEAD@{1}") or thought that "git checkout <committish>" would act like "git reset --hard <committish>". For the latter I fail to envision any solution except for education (and I have no idea why the user expected checkout to work like reset). The former can be solved by the proposed extra information in HEAD, forbidding changes to HEAD that make it reference a commit that's not reachable through the head stored in the extra information[*1*] and providing some command that acts like "svn up". This seems quite different from the plain "forbid committing" or "detach and know how you get there", but more like "detach and know where you're coming from". [*1*] If certain updates to HEAD aren't forbidden, a "checkout deadbeef" (or a reset or update-ref) would possibly invalidate the extra information in HEAD, which would require implicit detaching, making the concept useless. For example: A---B---C---D---E (master) \ / F---G---H---I (foo) git checkout master git checkout master~2 # Put refs/heads/master into the extra info git reset --hard HEAD^ # Allow? git reset --hard foo~2 # Allow? Change extra info? It's also in master git checkout master git checkout foo~2 Is that checkout allowed? "foo~2" is also reachable through master. Does "checkout" do some smart parsing and puts refs/heads/foo into the extra info? Or should refs/heads/master end up there? git checkout master git checkout foo~1 Basically, same deal as above, but foo~1 is not reachable through master. And finally the pure commit id cases: git checkout master git checkout $(git rev-parse master^) Is that to be allowed? We can't derive the extra info from the argument given to checkout, but could check that it's reachable from master (currently referenced HEAD at the time of the command being run) And: git checkout master git checkout $(git rev-parse foo^) Neither can we guess what the extra info should be from the argument given to checkout, nor is the given commit reachable through master. So this should be forbidden and should require ^0? This whole thing is indeed a whole lot less complex with a SVN-like model, where you basically work with the linearly growing reflog only. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 4:29 ` Björn Steinbrink @ 2009-10-16 6:02 ` Daniel Barkalow 2009-10-16 8:27 ` Björn Steinbrink 2009-10-16 15:44 ` Nicolas Pitre 0 siblings, 2 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-16 6:02 UTC (permalink / raw) To: Björn Steinbrink Cc: Junio C Hamano, Jeff King, Nicolas Pitre, James Pickens, Jay Soffian, git [-- Attachment #1: Type: TEXT/PLAIN, Size: 2511 bytes --] On Fri, 16 Oct 2009, Björn Steinbrink wrote: > On 2009.10.15 14:54:18 -0700, Junio C Hamano wrote: > > If it is very important to support: > > > > $ git checkout --look-but-not-touch origin/next^ > > > > then James's approach would not be very useful, as we do have to detach > > HEAD and implement the "do not touch" logic for detached HEAD state > > anyway, so we might just use the same logic we would use for origin/next^ > > when checking out origin/next itself. > > I don't have any numbers backing this up, but my gut feeling says that > most cases of "Where have my commits gone?" that I have seen on #git > were due to "git checkout HEAD~2"-like actions. Either because the user > assumed SVN-like behaviour (you can't commit until you do "svn up", like > "git reset --merge HEAD@{1}") or thought that "git checkout > <committish>" would act like "git reset --hard <committish>". > > For the latter I fail to envision any solution except for > education (and I have no idea why the user expected checkout to work > like reset). > > The former can be solved by the proposed extra information in HEAD, > forbidding changes to HEAD that make it reference a commit that's not > reachable through the head stored in the extra information[*1*] and providing > some command that acts like "svn up". > > This seems quite different from the plain "forbid committing" or "detach > and know how you get there", but more like "detach and know where you're > coming from". What's the state before the "git checkout HEAD~2"? If it's: $ git checkout origin/some-obscure-branch (get curious about the commit a bit back) $ git checkout HEAD~2 And then the user doesn't know how to get back to where they were, then it should work if git had stored "origin/some-obscure-branch~2" at this point (having substituted "origin/some-obscure-branch" (the previous extra info) for HEAD). Then we could have a "git up" that would discard modifiers from the extra info and check that out. Or users might find "git checkout origin/some-obscure-branch" obvious enough if git is reporting something related. I know I often find my git.git repos on "* (no branch)", and I don't remember if I checked that out as origin/master or origin/next. And that's an important clue as to when I'd been doing there previously, and what I might want to do next. Perhaps these users are having a similar problem, where they're relying on git to remember what they were doing? -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 6:02 ` Daniel Barkalow @ 2009-10-16 8:27 ` Björn Steinbrink 2009-10-16 15:44 ` Nicolas Pitre 1 sibling, 0 replies; 93+ messages in thread From: Björn Steinbrink @ 2009-10-16 8:27 UTC (permalink / raw) To: Daniel Barkalow Cc: Junio C Hamano, Jeff King, Nicolas Pitre, James Pickens, Jay Soffian, git On 2009.10.16 02:02:09 -0400, Daniel Barkalow wrote: > On Fri, 16 Oct 2009, Björn Steinbrink wrote: > > > On 2009.10.15 14:54:18 -0700, Junio C Hamano wrote: > > > If it is very important to support: > > > > > > $ git checkout --look-but-not-touch origin/next^ > > > > > > then James's approach would not be very useful, as we do have to detach > > > HEAD and implement the "do not touch" logic for detached HEAD state > > > anyway, so we might just use the same logic we would use for origin/next^ > > > when checking out origin/next itself. > > > > I don't have any numbers backing this up, but my gut feeling says that > > most cases of "Where have my commits gone?" that I have seen on #git > > were due to "git checkout HEAD~2"-like actions. Either because the user > > assumed SVN-like behaviour (you can't commit until you do "svn up", like > > "git reset --merge HEAD@{1}") or thought that "git checkout > > <committish>" would act like "git reset --hard <committish>". > > > > For the latter I fail to envision any solution except for > > education (and I have no idea why the user expected checkout to work > > like reset). > > > > The former can be solved by the proposed extra information in HEAD, > > forbidding changes to HEAD that make it reference a commit that's not > > reachable through the head stored in the extra information[*1*] and providing > > some command that acts like "svn up". > > > > This seems quite different from the plain "forbid committing" or "detach > > and know how you get there", but more like "detach and know where you're > > coming from". > > What's the state before the "git checkout HEAD~2"? > > If it's: > > $ git checkout origin/some-obscure-branch > (get curious about the commit a bit back) > $ git checkout HEAD~2 IIRC, most of the time it was: git checkout master # not detaching git checkout HEAD~2 Another version I recall (but that's what I use myself regularly, so I might be biased and think that it's more common that it actually was) is: git checkout master git log # Find commit, copy hash git checkout <hash> # Pasting the copied hash > And then the user doesn't know how to get back to where they were, then it > should work if git had stored "origin/some-obscure-branch~2" at this point > (having substituted "origin/some-obscure-branch" (the previous extra info) > for HEAD). Then we could have a "git up" that would discard modifiers from > the extra info and check that out. Or users might find "git checkout > origin/some-obscure-branch" obvious enough if git is reporting something > related. I'd not put "origin/some-obscure-branch~2" in there, but just "origin/some-obscure-branch". Rationale: The ~2 modifier may become invalid when you do "git fetch". And I don't see any value in having that modifier, and even if there are some corner-cases, those could use "git describe" or so, to get the modifiers on the fly. > I know I often find my git.git repos on "* (no branch)", and I don't > remember if I checked that out as origin/master or origin/next. And that's > an important clue as to when I'd been doing there previously, and what I > might want to do next. Perhaps these users are having a similar problem, > where they're relying on git to remember what they were doing? Hm, maybe. I'm more inclined to think that they assumed that "git checkout <branch_head>" 'binds' them to that branch head. But git allows them to jump around freely, the 'binding' is very weak. SVN has: "svn up": Get an older/newer version of the branch I'm on "svn switch": Switch to a different branch You cannot jump around without binding yourself to any branch. git has: "git checkout": Go anywhere, bind to that till the next checkout. With "git checkout <non-branch-head>" working like a temporary unnamed branch head. In my view, there's the huge conceptual difference that svn has named branches, while git only has named branch heads, that have a history (reflog) that isn't necessarily even remotely similar to that of the branch it currently points at. G---H---I (bar) / / A---B---C---D---E (master) \ F (foo) In SVN, you'd have a history that describes how "bar" came into its current state, consisting of: G, H, I (Not following the copy at G). In git, you have a history that describes how commit I came into existence (not branch head "bar"!), that is: A, B, C, D, E, G, H, I. And the actual history for "bar" in git (the reflog) might be as weird as: E, F, H, I, B, I. Jumping wildly across the commit DAG. My view is that with git you're never "on a branch", but you have an active branch head (possibly unnamed [detached HEAD]) that marks a tip, where the DAG grows. A branch, to me, has an extent. In the above graph, G, H, I is a branch, and F is a branch, but "bar" is not. "bar" has no extent, it's just where the "G, H, I" branch might possibly grow. When you do "git checkout bar~2", you're not on "no branch". Your active branch head is just unnamed. The branch is yet to be born (unless you consider e.g. "A, B, C, G" to be your branch), but at least after doing a "git commit", you'll have: J (HEAD) / G---H---I (bar) / / A---B---C---D---E (master) \ F (foo) And then you clearly do have a branch "J" there. At least if you stop saying that a branch is just its head. And "git branch" saying that you're on "no branch" makes no sense at all then. Git simply doesn't expose branches in a sense of "a series of commit". To get that, you need things like "git log master..bar" to get the "G, H, I" branch. SVN has this clear "this branch has this name" concept, git does not. I prefer gits way. But maybe it should simply not use the term "branch" when it means "branch head". And the glossary even somewhat agrees with me, although it disagrees with itself: branch A "branch" is an active line of development. The most recent commit on a branch is referred to as the tip of that branch. The tip of the branch is referenced by a branch head, which moves forward as additional development is done on the branch. A single git repository can track an arbitrary number of branches, but your working tree is associated with just one of them (the "current" or "checked out" branch), and HEAD points to that branch. So a branch is an active line of development. If I do "git checkout foo~2" and "git commit", I clearly do have an active line of development. So it's not "no branch". And a "branch head" references the tip (point of growth) of a branch. It's not identical to a branch. But then there comes HEAD, which is said to point to a branch, while it of course points to a branch head. I guess the glossary is outdated WRT detached HEAD, but if you ignore the implementation details, it could still be said that in case of a detached HEAD, HEAD points to an unnamed branch head. The user manual also makes this distinction, but says that "when no confusion will result, we often just use the term 'branch' both for branches and for branch heads". And the command man pages follow that "just use 'branch'" way: "git checkout" is said to checkout (and possibly create) a branch, not a branch head. "git branch": - List, create or delete branches - --contains/--merged/--no-merged => show branches that... But the clear winner is (from git-branch(1)): "If the <commit> argument is missing it defaults to HEAD (i.e. the tip of the current branch)." Combine that with a detached HEAD and the according "git branch" output. The <commit> argument will default to the tip of no branch! Epic. Don't get me wrong though. I like git's model, and think that its anonymous branches with named branch heads offer a lot more than e.g. SVN's named branches (and namespace pollution is just a minor factor). But I'm more and more convinced that suggesting the unknowing user who didn't read the "we term A for A and B" notice in the manual, that git does have named branches (branches being a series of commits) is a bad thing that leads to confusion (in contrast to what the manual assumes). Examples: User asking about deleting a "branch" without deleting its commits: http://colabti.de/irclogger/irclogger_log/git?date=2009-10-14#l2113 User asking whether deleting master will mess up other "branches": http://colabti.de/irclogger/irclogger_log/git?date=2009-10-13#l2407 (I thought that there were two more in the last week, but I couldn't find them, so maybe I was wrong, or they used some other word than "delete", which I used to search the logs). In both cases, the user wanted to delete the branch head, but was afraid that that would kill the commits, as they were told that they will delete the "branch" and assumed the "branch" to be all commits reachable through the branch head. And I kind of doubt that this just applies to SVN refugees that are used to SVN's meaning of branches, but also to people that are new to any kind of VCS and "naively" apply the branch-analogy to real-world trees, where branches are more than just their tips. And I believe that this is closely related to the detached HEAD thing. See above for the "no branch" stuff that now doesn't even make any sense to me anymore (even less after reading the git-branch(1) man page ;-)). But also the fact that checkout is hardly about branches, but about (possibly unnamed) branch heads. One might have certain branch heads that are never rewound and thus might be more or less equal to a branch, but that seems like it's almost(?) a special case if you consider what "checkout" can actually do. I'm not sure how this can be alleviated. Just saying "branch head" instead of "branch" is more correct, but probably still doesn't really express those differences that make git what it is. Making "git branch" say "* (unnamed branch head)" instead of "* (no branch)" seems like a good start, but the user manual would need a very close look to catch all the text that stops to make sense when you suddenly start to make a stronger difference between a branch and a branch head. I'll look into that over the weekend, but won't promise anything. Björn, hoping that he didn't run too far off the track ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 6:02 ` Daniel Barkalow 2009-10-16 8:27 ` Björn Steinbrink @ 2009-10-16 15:44 ` Nicolas Pitre 1 sibling, 0 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-16 15:44 UTC (permalink / raw) To: Daniel Barkalow Cc: Björn Steinbrink, Junio C Hamano, Jeff King, James Pickens, Jay Soffian, git On Fri, 16 Oct 2009, Daniel Barkalow wrote: > What's the state before the "git checkout HEAD~2"? It is HEAD@{1}. > I know I often find my git.git repos on "* (no branch)", and I don't > remember if I checked that out as origin/master or origin/next. Just have a look at the output of "git reflog". Pretty unambiguous IMHO. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 7:36 ` James Pickens ` (2 preceding siblings ...) 2009-10-15 18:51 ` Nicolas Pitre @ 2009-10-15 19:31 ` Daniel Barkalow 2009-10-15 20:34 ` Junio C Hamano 2009-10-16 12:15 ` Julian Phillips 3 siblings, 2 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-15 19:31 UTC (permalink / raw) To: James Pickens; +Cc: Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On Thu, 15 Oct 2009, James Pickens wrote: > On Wed, Oct 14, 2009 at 4:09 PM, Jeff King <peff@peff.net> wrote: > > That makes the most sense to me. If "git checkout" could write metadata > > into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout > > could record an "ok to commit" bit. And could also be used to change it > > after the fact. E.g.: > > > > $ git checkout --detach=commit origin/master > > $ git commit ;# should be ok > > > > $ git checkout --detach=examine origin/master > > $ git commit ;# complain > > $ git checkout --detach=commit HEAD > > $ git commit ;# ok > > > > I guess something like "rebase" should detach with "ok to commit", since > > it is planning on attaching the commits later. I'm not sure about "git > > bisect". I guess probably it should be "not ok to commit" to be on the > > safe side, and then somebody can "git checkout --detach=commit" if they > > want to. > > How about not detaching the head at all if the user checks out any ref, and > reject commits if he checked out a tag or remote branch. For example: > > $ git checkout origin/master > $ git status > # On branch origin/master > $ git commit ;# complain $ git checkout origin/master $ git fetch $ git checkout origin/next Uncommited file '...' would be overwritten. If HEAD is a symref to refs/remotes/origin/master, and you update refs/remotes/origin/master, git will subsequently see that your index doesn't match HEAD, and when you switch branches, it will try to apply a revert to the branch you're switching to. It's the same issue as pushing into a non-bare repository. -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 19:31 ` Daniel Barkalow @ 2009-10-15 20:34 ` Junio C Hamano 2009-10-15 21:35 ` Daniel Barkalow 2009-10-16 12:15 ` Julian Phillips 1 sibling, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-15 20:34 UTC (permalink / raw) To: Daniel Barkalow Cc: James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git Daniel Barkalow <barkalow@iabervon.org> writes: > $ git checkout origin/master > $ git fetch > $ git checkout origin/next > Uncommited file '...' would be overwritten. > > If HEAD is a symref to refs/remotes/origin/master, and you update > refs/remotes/origin/master, git will subsequently see that your index > doesn't match HEAD, and when you switch branches, it will try to apply a > revert to the branch you're switching to. It's the same issue as pushing > into a non-bare repository. I think the idea here is to allow HEAD to point at outside refs/heads/, e.g. refs/remotes/origin/master, but forbid commit and other commands from updating HEAD and its underlying ref via update_ref() unless HEAD is detached or points at a local branch. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 20:34 ` Junio C Hamano @ 2009-10-15 21:35 ` Daniel Barkalow 2009-10-15 21:48 ` Nicolas Pitre 0 siblings, 1 reply; 93+ messages in thread From: Daniel Barkalow @ 2009-10-15 21:35 UTC (permalink / raw) To: Junio C Hamano; +Cc: James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git On Thu, 15 Oct 2009, Junio C Hamano wrote: > Daniel Barkalow <barkalow@iabervon.org> writes: > > > $ git checkout origin/master > > $ git fetch > > $ git checkout origin/next > > Uncommited file '...' would be overwritten. > > > > If HEAD is a symref to refs/remotes/origin/master, and you update > > refs/remotes/origin/master, git will subsequently see that your index > > doesn't match HEAD, and when you switch branches, it will try to apply a > > revert to the branch you're switching to. It's the same issue as pushing > > into a non-bare repository. > > I think the idea here is to allow HEAD to point at outside refs/heads/, > e.g. refs/remotes/origin/master, but forbid commit and other commands from > updating HEAD and its underlying ref via update_ref() unless HEAD is > detached or points at a local branch. $ git checkout origin/master $ git fetch (Some error) I think it would be much more confusing for many users if you couldn't do: $ git checkout origin/master (look at origin/master) (wait a day) $ git fetch $ git checkout origin/next (look at origin/next) Part of the original point of detached HEAD was to support this pattern without creating an undesired local branch (which falls out of date), having problems with updating the tracking branches, or having problems with direct changes to the ref that HEAD points to. Currently, HEAD is never a symref to anything that will ever be updated normally except though the symref. That's a really handy property that avoids making us deal with lots of special cases in weird places. And those special cases would not only be annoying to have to handle again, but they'd be complexity that users would have to be exposed to. -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 21:35 ` Daniel Barkalow @ 2009-10-15 21:48 ` Nicolas Pitre 0 siblings, 0 replies; 93+ messages in thread From: Nicolas Pitre @ 2009-10-15 21:48 UTC (permalink / raw) To: Daniel Barkalow Cc: Junio C Hamano, James Pickens, Jeff King, Jay Soffian, git On Thu, 15 Oct 2009, Daniel Barkalow wrote: > On Thu, 15 Oct 2009, Junio C Hamano wrote: > > > Daniel Barkalow <barkalow@iabervon.org> writes: > > > > > $ git checkout origin/master > > > $ git fetch > > > $ git checkout origin/next > > > Uncommited file '...' would be overwritten. > > > > > > If HEAD is a symref to refs/remotes/origin/master, and you update > > > refs/remotes/origin/master, git will subsequently see that your index > > > doesn't match HEAD, and when you switch branches, it will try to apply a > > > revert to the branch you're switching to. It's the same issue as pushing > > > into a non-bare repository. > > > > I think the idea here is to allow HEAD to point at outside refs/heads/, > > e.g. refs/remotes/origin/master, but forbid commit and other commands from > > updating HEAD and its underlying ref via update_ref() unless HEAD is > > detached or points at a local branch. > > $ git checkout origin/master > $ git fetch > (Some error) Right. So we're back to your initial proposal I guess (storing some info/state in .git/HEAD when detached). Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-15 19:31 ` Daniel Barkalow 2009-10-15 20:34 ` Junio C Hamano @ 2009-10-16 12:15 ` Julian Phillips 2009-10-16 14:30 ` Björn Steinbrink 1 sibling, 1 reply; 93+ messages in thread From: Julian Phillips @ 2009-10-16 12:15 UTC (permalink / raw) To: Daniel Barkalow Cc: James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On Thu, 15 Oct 2009, Daniel Barkalow wrote: > On Thu, 15 Oct 2009, James Pickens wrote: > >> How about not detaching the head at all if the user checks out any ref, and >> reject commits if he checked out a tag or remote branch. For example: >> >> $ git checkout origin/master >> $ git status >> # On branch origin/master >> $ git commit ;# complain > > $ git checkout origin/master > $ git fetch > $ git checkout origin/next > Uncommited file '...' would be overwritten. How about: $ git checkout origin/master $ git fetch Refusing to fetch, as it would update a checkedout branch "git fetch -f" will force the update, but you will need to run "git reset --hard HEAD" to update your checkout to match. ? -- Julian --- If you care, you just get disappointed all the time. If you don't care nothing matters so you are never upset. -- Calvin ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 12:15 ` Julian Phillips @ 2009-10-16 14:30 ` Björn Steinbrink 2009-10-16 17:31 ` Julian Phillips 0 siblings, 1 reply; 93+ messages in thread From: Björn Steinbrink @ 2009-10-16 14:30 UTC (permalink / raw) To: Julian Phillips Cc: Daniel Barkalow, James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On 2009.10.16 13:15:35 +0100, Julian Phillips wrote: > On Thu, 15 Oct 2009, Daniel Barkalow wrote: > > >On Thu, 15 Oct 2009, James Pickens wrote: > > > >>How about not detaching the head at all if the user checks out any ref, and > >>reject commits if he checked out a tag or remote branch. For example: > >> > >>$ git checkout origin/master > >>$ git status > >># On branch origin/master > >>$ git commit ;# complain > > > >$ git checkout origin/master > >$ git fetch > >$ git checkout origin/next > >Uncommited file '...' would be overwritten. > > How about: > > $ git checkout origin/master > $ git fetch > Refusing to fetch, as it would update a checkedout branch > "git fetch -f" will force the update, but you will need to run "git > reset --hard HEAD" to update your checkout to match. That would redefine -f (currently means "allow non-fast-forward updates"), the flag that allows the checked out branch head to be updated is -u, --update-head-ok, and is for internal use only. And suggesting "reset --hard" seems wrong, that just kills any uncommitted changes. And such uncommitted changes would be lost in the big "undo the fetch update" diff. So you'd have to do: git reset --soft HEAD@{1} git checkout --merge HEAD@{1} to keep them, while updating to the new state of the remote tracking branch. Not quite intuitive, is it? Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 14:30 ` Björn Steinbrink @ 2009-10-16 17:31 ` Julian Phillips 2009-10-16 18:29 ` Daniel Barkalow ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: Julian Phillips @ 2009-10-16 17:31 UTC (permalink / raw) To: Björn Steinbrink Cc: Daniel Barkalow, James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On Fri, 16 Oct 2009, Bj?rn Steinbrink wrote: > On 2009.10.16 13:15:35 +0100, Julian Phillips wrote: >> On Thu, 15 Oct 2009, Daniel Barkalow wrote: >> >>> On Thu, 15 Oct 2009, James Pickens wrote: >>> >>>> How about not detaching the head at all if the user checks out any ref, and >>>> reject commits if he checked out a tag or remote branch. For example: >>>> >>>> $ git checkout origin/master >>>> $ git status >>>> # On branch origin/master >>>> $ git commit ;# complain >>> >>> $ git checkout origin/master >>> $ git fetch >>> $ git checkout origin/next >>> Uncommited file '...' would be overwritten. >> >> How about: >> >> $ git checkout origin/master >> $ git fetch >> Refusing to fetch, as it would update a checkedout branch >> "git fetch -f" will force the update, but you will need to run "git >> reset --hard HEAD" to update your checkout to match. > > That would redefine -f (currently means "allow non-fast-forward > updates"), the flag that allows the checked out branch head to be > updated is -u, --update-head-ok, and is for internal use only. > > And suggesting "reset --hard" seems wrong, that just kills any > uncommitted changes. Ok, so the commands were wrong. Not important. It was the approach that I was trying to suggest rather than the actual commands. The point I was trying to make was how, as a user, I would be happy to git behave. So, I try to run fetch, git says "ooh, now that would be dangerous - you can force it happen by running "git foo", but you will then be in situation X, which you can then recover from by running "git bar", though you may need to run "git stash" to save any edits you have made" or something similar. Now as a user I know that I have tried to do something a bit unusual, but I don't have to run to the mailing list or #git saying "I just did X Y Z and everything is now FUBARed". I can even proceed to do the unusal thing, as git itself has given me the information I need to sort things out afterwards. > And such uncommitted changes would be lost in the big "undo the fetch > update" diff. So you'd have to do: > git reset --soft HEAD@{1} > git checkout --merge HEAD@{1} > > to keep them, while updating to the new state of the remote tracking > branch. Not quite intuitive, is it? I don't care what git has to do, I'm talking about the user experience - if we have to write some new code to support it, that really isn't a terribly hard thing to do. UIs should be driven down from the user interaction not up from the implementation. -- Julian --- Captain: "Catalyzer's a nothing part, captain." Mal: "It's nothing until you don't got one. Then it appears to be everything." --Episode #8, "Out of Gas" ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 17:31 ` Julian Phillips @ 2009-10-16 18:29 ` Daniel Barkalow 2009-10-16 19:05 ` Junio C Hamano 2009-10-17 7:55 ` Björn Steinbrink 2 siblings, 0 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-16 18:29 UTC (permalink / raw) To: Julian Phillips Cc: Björn Steinbrink, James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On Fri, 16 Oct 2009, Julian Phillips wrote: > It was the approach that I was trying to suggest rather than the actual > commands. The point I was trying to make was how, as a user, I would be happy > to git behave. > > So, I try to run fetch, git says "ooh, now that would be dangerous - you can > force it happen by running "git foo", but you will then be in situation X, > which you can then recover from by running "git bar", though you may need to > run "git stash" to save any edits you have made" or something similar. > > Now as a user I know that I have tried to do something a bit unusual, but I > don't have to run to the mailing list or #git saying "I just did X Y Z and > everything is now FUBARed". I can even proceed to do the unusal thing, as git > itself has given me the information I need to sort things out afterwards. The thing is that that sequence shouldn't be unusual or dangerous or require sorting things out afterwards. In the current version of git, it's a completely normal thing to do that behaves nicely and does what the user almost certainly wants. We *could* horribly break it, and then add messages to tell the user they're doing something that's now horribly broken, and tell the user how to cope with the fact that what they want to do involves something that's horribly broken, and roll our eyes when users who have only used working systems like SVN or git 1.6.X ignore the message and can't figure out what's going on. Or we could just not break it in the first place. SVN doesn't think that your working directory is supposed to change when someone else makes a commit. Git shouldn't think your working directory should change when you find out that someone made a commit. If you want to see now commits, you do "svn up" or "git checkout". -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 17:31 ` Julian Phillips 2009-10-16 18:29 ` Daniel Barkalow @ 2009-10-16 19:05 ` Junio C Hamano 2009-10-16 19:48 ` Julian Phillips 2009-10-17 7:55 ` Björn Steinbrink 2 siblings, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-16 19:05 UTC (permalink / raw) To: Julian Phillips Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git Julian Phillips <julian@quantumfyre.co.uk> writes: >> And such uncommitted changes would be lost in the big "undo the fetch >> update" diff. So you'd have to do: >> git reset --soft HEAD@{1} >> git checkout --merge HEAD@{1} >> >> to keep them, while updating to the new state of the remote tracking >> branch. Not quite intuitive, is it? > > I don't care what git has to do, I'm talking about the user experience But Björn is showing two commands the _user_ has to type, iow, the comment is about the user experience. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 19:05 ` Junio C Hamano @ 2009-10-16 19:48 ` Julian Phillips 2009-10-16 20:19 ` Nicolas Pitre 2009-10-16 20:19 ` Junio C Hamano 0 siblings, 2 replies; 93+ messages in thread From: Julian Phillips @ 2009-10-16 19:48 UTC (permalink / raw) To: Junio C Hamano Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git On Fri, 16 Oct 2009, Junio C Hamano wrote: > Julian Phillips <julian@quantumfyre.co.uk> writes: > >>> And such uncommitted changes would be lost in the big "undo the fetch >>> update" diff. So you'd have to do: >>> git reset --soft HEAD@{1} >>> git checkout --merge HEAD@{1} >>> >>> to keep them, while updating to the new state of the remote tracking >>> branch. Not quite intuitive, is it? >> >> I don't care what git has to do, I'm talking about the user experience > > But Bj?rn is showing two commands the _user_ has to type, iow, the comment > is about the user experience. Only Currently. My point was that _if_ we wanted to support this sort of thing, then we can make is simpler to do by providing a simple command for the user. The point I wanted to make was that the decision on what to do should be driven by the user's experience - not by the fact that it is easier to implement something else. My interest in this thread is solely that it might provide a mechanism to find out which tag was checked out. So, I'm just chucking in my $0.02 as a user. My suggestions are probably complete rubbish, as I haven't really had time to think them through... Sorry. -- Julian --- Look, just gimme some inner peace, or I'll mop the floor with ya! -- Homer Simpson El Viaje Misterioso de Nuestro Homer ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 19:48 ` Julian Phillips @ 2009-10-16 20:19 ` Nicolas Pitre 2009-10-17 15:15 ` Julian Phillips 2009-10-16 20:19 ` Junio C Hamano 1 sibling, 1 reply; 93+ messages in thread From: Nicolas Pitre @ 2009-10-16 20:19 UTC (permalink / raw) To: Julian Phillips Cc: Junio C Hamano, Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Jay Soffian, git On Fri, 16 Oct 2009, Julian Phillips wrote: > My interest in this thread is solely that it might provide a mechanism to find > out which tag was checked out. So, I'm just chucking in my $0.02 as a user. Try this: $ git checkout v1.5.5 Note: moving to 'v1.5.5' which isn't a local branch If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new_branch_name> HEAD is now at 1d2375d... GIT 1.5.5 [look around, and then ...] $ git checkout HEAD~2 Previous HEAD position was 1d2375d... GIT 1.5.5 HEAD is now at f61cc48... git-svn: fix following renamed paths when tracking a single path [go out for lunch ... and forget what this was about.] $ git reflog -3 f61cc48 HEAD@{0}: checkout: moving from 1d2375d... to HEAD~2 1d2375d HEAD@{1}: checkout: moving from master to v1.5.5 c274db7 HEAD@{2}: pull : Fast forward Here I have all the information to see what I did, and from what state. I even know that I did a pull on the master branch before moving away from it. The -3 limits the log to 3 entries. With no limit you get it all in your default pager. So there is no need for another mechanism to find out what tag was actually checked out -- you have it all already. Nicolas ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 20:19 ` Nicolas Pitre @ 2009-10-17 15:15 ` Julian Phillips 2009-10-17 17:04 ` Björn Steinbrink 0 siblings, 1 reply; 93+ messages in thread From: Julian Phillips @ 2009-10-17 15:15 UTC (permalink / raw) To: Nicolas Pitre Cc: Junio C Hamano, Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Jay Soffian, Git Mailing List On Fri, 16 Oct 2009, Nicolas Pitre wrote: > On Fri, 16 Oct 2009, Julian Phillips wrote: > >> My interest in this thread is solely that it might provide a mechanism to find >> out which tag was checked out. So, I'm just chucking in my $0.02 as a user. > > Try this: > > $ git checkout v1.5.5 > Note: moving to 'v1.5.5' which isn't a local branch > If you want to create a new branch from this checkout, you may do so > (now or later) by using -b with the checkout command again. Example: > git checkout -b <new_branch_name> > HEAD is now at 1d2375d... GIT 1.5.5 > > [look around, and then ...] > > $ git checkout HEAD~2 > Previous HEAD position was 1d2375d... GIT 1.5.5 > HEAD is now at f61cc48... git-svn: fix following renamed paths when tracking a single path > > [go out for lunch ... and forget what this was about.] > > $ git reflog -3 > f61cc48 HEAD@{0}: checkout: moving from 1d2375d... to HEAD~2 > 1d2375d HEAD@{1}: checkout: moving from master to v1.5.5 > c274db7 HEAD@{2}: pull : Fast forward > > Here I have all the information to see what I did, and from what state. > I even know that I did a pull on the master branch before moving away > from it. The -3 limits the log to 3 entries. With no limit you get it > all in your default pager. > > So there is no need for another mechanism to find out what tag was > actually checked out -- you have it all already. What I want is a way for my build process to reliably know what branch or tag is currently being built. "git symbolic-ref HEAD" will give me the branch name, but doesn't work for tags. "git describe" will find _a_ tag, but I can't tell if it's actually the one checked out. Using the reflog isn't something that had occured to me, but it seems a bit ... uncontrolled ... for a script. I'd rather have a plumbing level command that just told me what I had actually checked out. Though I may well look into using the reflog until such a command is available (or I find out there already is one). -- Julian --- I doubt, therefore I might be. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 15:15 ` Julian Phillips @ 2009-10-17 17:04 ` Björn Steinbrink 2009-10-17 17:35 ` Julian Phillips 0 siblings, 1 reply; 93+ messages in thread From: Björn Steinbrink @ 2009-10-17 17:04 UTC (permalink / raw) To: Julian Phillips Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens, Jeff King, Jay Soffian, Git Mailing List On 2009.10.17 16:15:13 +0100, Julian Phillips wrote: > On Fri, 16 Oct 2009, Nicolas Pitre wrote: > > >On Fri, 16 Oct 2009, Julian Phillips wrote: > > > >>My interest in this thread is solely that it might provide a mechanism to find > >>out which tag was checked out. So, I'm just chucking in my $0.02 as a user. > > > >Try this: > > > >$ git checkout v1.5.5 > >Note: moving to 'v1.5.5' which isn't a local branch > >If you want to create a new branch from this checkout, you may do so > >(now or later) by using -b with the checkout command again. Example: > > git checkout -b <new_branch_name> > >HEAD is now at 1d2375d... GIT 1.5.5 > > > >[look around, and then ...] > > > >$ git checkout HEAD~2 > >Previous HEAD position was 1d2375d... GIT 1.5.5 > >HEAD is now at f61cc48... git-svn: fix following renamed paths when tracking a single path > > > >[go out for lunch ... and forget what this was about.] > > > >$ git reflog -3 > >f61cc48 HEAD@{0}: checkout: moving from 1d2375d... to HEAD~2 > >1d2375d HEAD@{1}: checkout: moving from master to v1.5.5 > >c274db7 HEAD@{2}: pull : Fast forward > > > >Here I have all the information to see what I did, and from what state. > >I even know that I did a pull on the master branch before moving away > >from it. The -3 limits the log to 3 entries. With no limit you get it > >all in your default pager. > > > >So there is no need for another mechanism to find out what tag was > >actually checked out -- you have it all already. > > What I want is a way for my build process to reliably know what > branch or tag is currently being built. "git symbolic-ref HEAD" > will give me the branch name, but doesn't work for tags. "git > describe" will find _a_ tag, but I can't tell if it's actually the > one checked out. Do you have multiple (annotated) tags for the same commit? Otherwise, I don't see why "git describe HEAD" should print the wrong one. If there's a tag that can be resolved to the same commit that HEAD can be resolved, then "git describe HEAD" must output that one. Otherwise, that'd be a clear bug to me. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 17:04 ` Björn Steinbrink @ 2009-10-17 17:35 ` Julian Phillips 2009-10-17 17:48 ` Björn Steinbrink 0 siblings, 1 reply; 93+ messages in thread From: Julian Phillips @ 2009-10-17 17:35 UTC (permalink / raw) To: Björn Steinbrink Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens, Jeff King, Jay Soffian, Git Mailing List On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote: > On 2009.10.17 16:15:13 +0100, Julian Phillips wrote: >> On Fri, 16 Oct 2009, Nicolas Pitre wrote: >> >>> On Fri, 16 Oct 2009, Julian Phillips wrote: >>> >>>> My interest in this thread is solely that it might provide a mechanism to find >>>> out which tag was checked out. So, I'm just chucking in my $0.02 as a user. >>> >>> Try this: >>> >>> $ git checkout v1.5.5 >>> Note: moving to 'v1.5.5' which isn't a local branch >>> If you want to create a new branch from this checkout, you may do so >>> (now or later) by using -b with the checkout command again. Example: >>> git checkout -b <new_branch_name> >>> HEAD is now at 1d2375d... GIT 1.5.5 >>> >>> [look around, and then ...] >>> >>> $ git checkout HEAD~2 >>> Previous HEAD position was 1d2375d... GIT 1.5.5 >>> HEAD is now at f61cc48... git-svn: fix following renamed paths when tracking a single path >>> >>> [go out for lunch ... and forget what this was about.] >>> >>> $ git reflog -3 >>> f61cc48 HEAD@{0}: checkout: moving from 1d2375d... to HEAD~2 >>> 1d2375d HEAD@{1}: checkout: moving from master to v1.5.5 >>> c274db7 HEAD@{2}: pull : Fast forward >>> >>> Here I have all the information to see what I did, and from what state. >>> I even know that I did a pull on the master branch before moving away >>> from it. The -3 limits the log to 3 entries. With no limit you get it >>> all in your default pager. >>> >>> So there is no need for another mechanism to find out what tag was >>> actually checked out -- you have it all already. >> >> What I want is a way for my build process to reliably know what >> branch or tag is currently being built. "git symbolic-ref HEAD" >> will give me the branch name, but doesn't work for tags. "git >> describe" will find _a_ tag, but I can't tell if it's actually the >> one checked out. > > Do you have multiple (annotated) tags for the same commit? Potentially, yes. Releasing isn't the only thing that requires keeping track of things. It's even possible that the person creating the newer tag doesn't yet know that a release tag has been applied if the person who applied it hasn't yet pushed it back. > Otherwise, I don't see why "git describe HEAD" should print the wrong > one. If there's a tag that can be resolved to the same commit that HEAD > can be resolved, then "git describe HEAD" must output that one. > Otherwise, that'd be a clear bug to me. Oh, definately no bug. git describe works exactly as expected, the problem is that the tag checked out isn't always the latest tag applied to that commit. -- Julian --- Jayne: Shee-nio high tech Alliance crap!" --Episode #9, "Ariel" ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 17:35 ` Julian Phillips @ 2009-10-17 17:48 ` Björn Steinbrink 2009-10-17 22:28 ` Julian Phillips 0 siblings, 1 reply; 93+ messages in thread From: Björn Steinbrink @ 2009-10-17 17:48 UTC (permalink / raw) To: Julian Phillips Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens, Jeff King, Jay Soffian, Git Mailing List On 2009.10.17 18:35:38 +0100, Julian Phillips wrote: > On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote: > >Do you have multiple (annotated) tags for the same commit? > > Potentially, yes. Releasing isn't the only thing that requires > keeping track of things. It's even possible that the person > creating the newer tag doesn't yet know that a release tag has been > applied if the person who applied it hasn't yet pushed it back. OK, I'd consider that namespace pollution, as things like "this-version-sucks" doesn't seem like it show go into public repos, but anyway. If your release tags fix into a certain "unique" format, you could use describe with --match, like: git describe --match 'v[0-9]*' > >Otherwise, I don't see why "git describe HEAD" should print the > >wrong one. If there's a tag that can be resolved to the same > >commit that HEAD can be resolved, then "git describe HEAD" must > >output that one. Otherwise, that'd be a clear bug to me. > > Oh, definately no bug. git describe works exactly as expected, the > problem is that the tag checked out isn't always the latest tag > applied to that commit. I misworded that one. Should be "If there's only tag that can be ...". IOW it was meant for "only one tag per commit", which is what I assumed to be the case. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 17:48 ` Björn Steinbrink @ 2009-10-17 22:28 ` Julian Phillips 0 siblings, 0 replies; 93+ messages in thread From: Julian Phillips @ 2009-10-17 22:28 UTC (permalink / raw) To: Björn Steinbrink Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens, Jeff King, Jay Soffian, Git Mailing List On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote: > On 2009.10.17 18:35:38 +0100, Julian Phillips wrote: >> On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote: >>> Do you have multiple (annotated) tags for the same commit? >> >> Potentially, yes. Releasing isn't the only thing that requires >> keeping track of things. It's even possible that the person >> creating the newer tag doesn't yet know that a release tag has been >> applied if the person who applied it hasn't yet pushed it back. > > OK, I'd consider that namespace pollution, as things like > "this-version-sucks" doesn't seem like it show go into public repos, but > anyway. If your release tags fix into a certain "unique" format, you > could use describe with --match, like: > git describe --match 'v[0-9]*' Well - that only helps if we only ever build the release tags. Which isn't the case. The other tags are there for similar purposes and also should go into the version string - but only when they were the tag checked out. Is it really that unreasonable to want to know exactly what it was that was checked out? It's one of the few things that I miss from Subversion. -- Julian --- printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled :-)\n"); linux-2.6.6/drivers/message/fusion/mptbase.c ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 19:48 ` Julian Phillips 2009-10-16 20:19 ` Nicolas Pitre @ 2009-10-16 20:19 ` Junio C Hamano 2009-10-17 15:32 ` Julian Phillips 1 sibling, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-16 20:19 UTC (permalink / raw) To: Julian Phillips Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git Julian Phillips <julian@quantumfyre.co.uk> writes: > On Fri, 16 Oct 2009, Junio C Hamano wrote: > >> Julian Phillips <julian@quantumfyre.co.uk> writes: >> ... >>> I don't care what git has to do, I'm talking about the user experience >> >> But Bj?rn is showing two commands the _user_ has to type, iow, the comment >> is about the user experience. > > Only Currently. My point was that _if_ we wanted to support this sort > of thing, then we can make is simpler to do by providing a simple > command for the user. > > The point I wanted to make was that the decision on what to do should > be driven by the user's experience - not by the fact that it is easier > to implement something else. Sorry, but I do not see in what way what you said in the thread connects to the above three lines. Are you talking about this one from you a few messages back? How about: $ git checkout origin/master $ git fetch Refusing to fetch, as it would update a checkedout branch "git fetch -f" will force the update, but you will need to run "git reset --hard HEAD" to update your checkout to match. I am not seeing "not the implementation ease but the user experience" drive in this suggestion. If you are driving from the user experience point of view, I would have instead suggested: How about: $ git checkout origin/master $ git fetch and fetch happily updates the tracked branch, without affecting the HEAD state (nor index nor the work tree, of course). User experience here is: * Let's checkout what the upstream has on the master. I am at least aware that git is distributed and does not go to the network unless I tell it to, and am aware that origin/master is the state of the upsream _when I told git to look at it the last time_. So I'll get the state I talked with the upstream the last time, and that is what I want to look at. * Hmm, there may be even more updates since I talked with the upstream the last time. Let's tell git to fetch. I already know that this updates origin/master to a more recent state. Isn't it much cleaner and less confusing? And with these kind of awareness, the user can choose to do various things from here, e.g.: * Oh, fetch did fetched something. I want the updated state. Let's check it out with "git checkout origin/master"; or * Ok, what changed since I last talked with the upstream? I have one end of the state already checked out, and I updated origin/master with their latest, so I can say "git diff HEAD origin/master". Notice in the latter the user can be a neophyte who hasn't learned reflogs yet. > My interest in this thread is solely that it might provide a mechanism > to find out which tag was checked out. Hmm, what is lacking in "git describe HEAD" for that? I am not complaining that you might be asking for something that exists, but I _do_ want to know if something that exists is not a satisfactory solution and if so how it can be improved. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 20:19 ` Junio C Hamano @ 2009-10-17 15:32 ` Julian Phillips 2009-10-17 17:43 ` Junio C Hamano 0 siblings, 1 reply; 93+ messages in thread From: Julian Phillips @ 2009-10-17 15:32 UTC (permalink / raw) To: Junio C Hamano Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git On Fri, 16 Oct 2009, Junio C Hamano wrote: > Julian Phillips <julian@quantumfyre.co.uk> writes: > >> On Fri, 16 Oct 2009, Junio C Hamano wrote: >> >>> Julian Phillips <julian@quantumfyre.co.uk> writes: >>> ... >>>> I don't care what git has to do, I'm talking about the user experience >>> >>> But Bj?rn is showing two commands the _user_ has to type, iow, the comment >>> is about the user experience. >> >> Only Currently. My point was that _if_ we wanted to support this sort >> of thing, then we can make is simpler to do by providing a simple >> command for the user. >> >> The point I wanted to make was that the decision on what to do should >> be driven by the user's experience - not by the fact that it is easier >> to implement something else. > > Sorry, but I do not see in what way what you said in the thread connects > to the above three lines. Are you talking about this one from you a few > messages back? > > How about: > > $ git checkout origin/master > $ git fetch > Refusing to fetch, as it would update a checkedout branch > "git fetch -f" will force the update, but you will need to run "git > reset --hard HEAD" to update your checkout to match. > > I am not seeing "not the implementation ease but the user experience" > drive in this suggestion. If you are driving from the user experience > point of view, I would have instead suggested: > > How about: > > $ git checkout origin/master > $ git fetch > > and fetch happily updates the tracked branch, without affecting the > HEAD state (nor index nor the work tree, of course). True. I was saying that having git stop and explain things is better than making a mess for the user to clear up. Having it just work would of course be even better. Hoist by my own petard indead ... >> My interest in this thread is solely that it might provide a mechanism >> to find out which tag was checked out. > > Hmm, what is lacking in "git describe HEAD" for that? I am not > complaining that you might be asking for something that exists, but I _do_ > want to know if something that exists is not a satisfactory solution and > if so how it can be improved. What is lacking is the "checked out" part. "git describe HEAD" will tell me _a_ tag that matches the currently checked out state. However, it makes no guarantee that it was the one I checked out. If I tag the code with "v1.0.0", and a colleague later tags it with "this_version_sucks", then when I check out and build the code for the customer the version it reports could well be "this_version_sucks" instead of "v1.0.0" ... Nicolas Pitre suggested using the reflog, which does seem to include the information that I want, but I feel a little uneasy about accessing it via a script - how certain is it that the format of the message won't change? Is accessing the reflog the sort of thing people expect as part of the scripting interface? -- Julian --- Those who would repeat the past must control the teaching of history. -- Bene Gesserit Coda ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 15:32 ` Julian Phillips @ 2009-10-17 17:43 ` Junio C Hamano 2009-10-17 22:19 ` Julian Phillips 0 siblings, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-17 17:43 UTC (permalink / raw) To: Julian Phillips Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git Julian Phillips <julian@quantumfyre.co.uk> writes: >>> My interest in this thread is solely that it might provide a mechanism >>> to find out which tag was checked out. >> >> Hmm, what is lacking in "git describe HEAD" for that? I am not >> complaining that you might be asking for something that exists, but I _do_ >> want to know if something that exists is not a satisfactory solution and >> if so how it can be improved. > > What is lacking is the "checked out" part. "git describe HEAD" will > tell me _a_ tag that matches the currently checked out state. > However, it makes no guarantee that it was the one I checked out. If > I tag the code with "v1.0.0", and a colleague later tags it with > "this_version_sucks", then when I check out and build the code for the > customer the version it reports could well be "this_version_sucks" > instead of "v1.0.0" ... I think I understand why you think showing what you gave to your last "git checkout" (e.g. "checkout origin/master" or "checkout v1.0.0") and using that as a build identification token is a good idea. But "origin/master" is a moving target---it depends on when you checked it out. describe uses tags and does not use branch heads for a good reason. "v1.0.0" also is to a lessor degree, as you may have tagged v1.0.0 locally and somebody else also has used the tag for a different version, but a tag is far less likely to move due to social convention. "describe --long" would make sure this won't be an issue anyway, though. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 17:43 ` Junio C Hamano @ 2009-10-17 22:19 ` Julian Phillips 0 siblings, 0 replies; 93+ messages in thread From: Julian Phillips @ 2009-10-17 22:19 UTC (permalink / raw) To: Junio C Hamano Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git On Sat, 17 Oct 2009, Junio C Hamano wrote: > Julian Phillips <julian@quantumfyre.co.uk> writes: > >>>> My interest in this thread is solely that it might provide a mechanism >>>> to find out which tag was checked out. >>> >>> Hmm, what is lacking in "git describe HEAD" for that? I am not >>> complaining that you might be asking for something that exists, but I _do_ >>> want to know if something that exists is not a satisfactory solution and >>> if so how it can be improved. >> >> What is lacking is the "checked out" part. "git describe HEAD" will >> tell me _a_ tag that matches the currently checked out state. >> However, it makes no guarantee that it was the one I checked out. If >> I tag the code with "v1.0.0", and a colleague later tags it with >> "this_version_sucks", then when I check out and build the code for the >> customer the version it reports could well be "this_version_sucks" >> instead of "v1.0.0" ... > > I think I understand why you think showing what you gave to your last "git > checkout" (e.g. "checkout origin/master" or "checkout v1.0.0") and using > that as a build identification token is a good idea. But "origin/master" > is a moving target---it depends on when you checked it out. describe uses > tags and does not use branch heads for a good reason. For my purposes the branch that I built from is much more useful than the output from describe. Releases are always made from tags, but for builds used in the lab it is generally much more useful to know which branch was built directly rather than being able to find the exact commit that was built. > "v1.0.0" also is to a lessor degree, as you may have tagged v1.0.0 locally > and somebody else also has used the tag for a different version, but a tag > is far less likely to move due to social convention. "describe --long" > would make sure this won't be an issue anyway, though. For any particular release only one person is given the job of making the release tag, so we don't have the problem of multiple instances of the same tag - but we do need to make sure that the version output is the correct tag. -- Julian --- Water, taken in moderation cannot hurt anybody. -- Mark Twain ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 17:31 ` Julian Phillips 2009-10-16 18:29 ` Daniel Barkalow 2009-10-16 19:05 ` Junio C Hamano @ 2009-10-17 7:55 ` Björn Steinbrink 2009-10-17 8:11 ` Junio C Hamano 2009-10-17 15:02 ` Julian Phillips 2 siblings, 2 replies; 93+ messages in thread From: Björn Steinbrink @ 2009-10-17 7:55 UTC (permalink / raw) To: Julian Phillips Cc: Daniel Barkalow, James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On 2009.10.16 18:31:23 +0100, Julian Phillips wrote: > On Fri, 16 Oct 2009, Bj?rn Steinbrink wrote: > >On 2009.10.16 13:15:35 +0100, Julian Phillips wrote: > >>How about: > >> > >>$ git checkout origin/master > >>$ git fetch > >>Refusing to fetch, as it would update a checkedout branch > >>"git fetch -f" will force the update, but you will need to run "git > >>reset --hard HEAD" to update your checkout to match. > > > >That would redefine -f (currently means "allow non-fast-forward > >updates"), the flag that allows the checked out branch head to be > >updated is -u, --update-head-ok, and is for internal use only. > > > >And suggesting "reset --hard" seems wrong, that just kills any > >uncommitted changes. > > Ok, so the commands were wrong. Not important. > > It was the approach that I was trying to suggest rather than the > actual commands. The point I was trying to make was how, as a user, > I would be happy to git behave. Your approach explicitly included "mess up the index/worktree state", otherwise, "git fetch" would not have to tell the user that he has to do a "git reset --hard HEAD". I honestly can't believe that you would be happy with git messing up your work. > So, I try to run fetch, git says "ooh, now that would be dangerous - > you can force it happen by running "git foo", but you will then be > in situation X, which you can then recover from by running "git > bar", though you may need to run "git stash" to save any edits you > have made" or something similar. But why make "git fetch" with non-"obscure" refspecs dangerous to begin with? If we detach but keep some extra information, there's no need to make "git fetch" dangerous, _and_ we can still provide a command that just fetches the most recent version of the "checked out" remote tracking branch and checks that out. May it be another mode of operation for "git pull" or some "git up" command or whatever. > >And such uncommitted changes would be lost in the big "undo the fetch > >update" diff. So you'd have to do: > >git reset --soft HEAD@{1} > >git checkout --merge HEAD@{1} > > > >to keep them, while updating to the new state of the remote tracking > >branch. Not quite intuitive, is it? > > I don't care what git has to do, I'm talking about the user > experience - if we have to write some new code to support it, that > really isn't a terribly hard thing to do. UIs should be driven down > from the user interaction not up from the implementation. Those commands are those that git would have to show to you, instead of "git reset --hard HEAD", i.e. they're what you, as the user, have to do. And while "git reset --hard HEAD" might be remotely understandable to the user, that command sequence is very unlikely to be understood by most. And providing a command that does just this sequence is insane, it's just a bandaid for git doing crap to your worktree/index state. So let's better not start with git doing that crap at all. My current "idea" (I don't think I'll have time to implement that any time soon) is: Keep some extra information in HEAD (or somewhere else) when HEAD is detached about the ref that HEAD is "weakly" bound to. For example, "git checkout origin/master" might create a weak binding to refs/remotes/origin/master (for other [corner] cases, see the other mail I wrote, in which I outlined some cases I considered interesting). "git update" can use the branch.<name>.{remote,merge} setup, or alternatively the "weak binding" information, to fetch from the right remote, and checks whether a fast-forward of HEAD to the according upstream branch head is possible. If so, it does a "git checkout --merge <upstream>" (possibly leaving conflicts for the uncommitted changes, just like "svn update"). If a fast-forward is not possible, it complains, telling the user that he needs to use "git merge/rebase/pull" instead, and might want to create a branch head, in case of a detached HEAD. If there's also going to be a rule that forbids commits on some kind of detached HEAD, than the command could also tell the user (when a fast-forward is not possible) that upstream possibly rewrote history, and that the user might want to use "git checkout --merge <upstream>" (or maybe "git update -f"?) to just go to the new upstream version (not sure if that hint should be shown in addition to or instead of the "git merge/rebase/pull" hint). Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 7:55 ` Björn Steinbrink @ 2009-10-17 8:11 ` Junio C Hamano 2009-10-17 8:40 ` Björn Steinbrink 2009-10-17 15:02 ` Julian Phillips 1 sibling, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-17 8:11 UTC (permalink / raw) To: Björn Steinbrink Cc: Julian Phillips, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git Björn Steinbrink <B.Steinbrink@gmx.de> writes: > ... If so, it does a "git checkout --merge > <upstream>" (possibly leaving conflicts for the uncommitted changes, > just like "svn update"). Up to this point I was reading with quite a lot of interest. But here I strongly disagree to the point of getting actually disgusted. "svn up" is one of the areas Subversion folks failed to make their system a better CVS. It has the same "local changes are lost in the merge conflict mess in an irreversible way" failure mode, and we shouldn't be making it easy to new people. It is not something we should emulate. You can and should instead refuse the update, and suggest committing first so that the user has a safe record of what he has done and the merge with upstream can be retried if necessary. As you need to have that "refuse but guide the lost soul by telling what to do" mode anyway when... > ... If a fast-forward is not possible, it > complains, telling the user that he needs to use "git merge/rebase/pull" > instead, and might want to create a branch head, in case of a detached > HEAD. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 8:11 ` Junio C Hamano @ 2009-10-17 8:40 ` Björn Steinbrink 2009-10-17 9:04 ` Junio C Hamano 0 siblings, 1 reply; 93+ messages in thread From: Björn Steinbrink @ 2009-10-17 8:40 UTC (permalink / raw) To: Junio C Hamano Cc: Julian Phillips, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git On 2009.10.17 01:11:23 -0700, Junio C Hamano wrote: > Björn Steinbrink <B.Steinbrink@gmx.de> writes: > > > ... If so, it does a "git checkout --merge > > <upstream>" (possibly leaving conflicts for the uncommitted changes, > > just like "svn update"). > > Up to this point I was reading with quite a lot of interest. But here I > strongly disagree to the point of getting actually disgusted. > > "svn up" is one of the areas Subversion folks failed to make their system > a better CVS. It has the same "local changes are lost in the merge > conflict mess in an irreversible way" failure mode, and we shouldn't be > making it easy to new people. It is not something we should emulate. > > You can and should instead refuse the update, and suggest committing first > so that the user has a safe record of what he has done and the merge with > upstream can be retried if necessary. As you need to have that "refuse > but guide the lost soul by telling what to do" mode anyway when... Hm, probably I (mentally) focussed to much on "people that just want to look" and didn't really think that they'd have much to lose. Not sure. Over the time, I got so used to do "git checkout --merge <something>" with some I-don't-care-much debugging or whatever change, that I lost track of how bad that was with svn. If I have just I care about, I commit, and then "git update" would no longer be an option anyway. But yeah, not a good option to give to the uninitiated user... Interestingly, I irregularly give advice to use "git stash; git checkout; git stash apply" instead of "git checkout -m" on #git, as that allows you to try again if you messed up the conflict resolution, and even allows you to completely go back to the initial state. Maybe that would be an option? But I fail to come up with a convenient and at the same time error safe way for such a "stash wrap". The only thing that comes to mind would be to have "git update" completely wrapping the thing: git update - Stashes uncommitted changes - fetches - checks out - "stash apply --index", if that fails, just "stash apply" If there are conflicts, show options (similar to what rebase does): git update --retry # Start over - reset --hard - "stash apply --index", if that fails, just "stash apply" git update --abort - git reset --hard HEAD@{1} - "stash apply --index" - "stash drop stash@{0}" git update --done - Check whether there are still unmerged files, if so: complain - otherwise: "stash drop stash@{0}" OTOH, it might be easier to just tell the user to do the stash thing himself. But I wonder how many users would really know how to get back to the initial state then. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 8:40 ` Björn Steinbrink @ 2009-10-17 9:04 ` Junio C Hamano 2009-10-17 17:07 ` James Pickens 2009-10-17 19:41 ` Björn Steinbrink 0 siblings, 2 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-17 9:04 UTC (permalink / raw) To: Björn Steinbrink Cc: Julian Phillips, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git Björn Steinbrink <B.Steinbrink@gmx.de> writes: > Interestingly, I irregularly give advice to use "git stash; git > checkout; git stash apply" instead of "git checkout -m" on #git, as that > allows you to try again if you messed up the conflict resolution, and > even allows you to completely go back to the initial state. Maybe that > would be an option? As I already said many times (here and elsewhere), "up" is an inferior and more dangerous model we would be better off not following if we can. It is not even entirely CVS/SVN's fault that their "scm up" is an error prone operation. They use a centralized model, in which there is _no_ way to record your local modification and run a retryable merge, so they have an excuse to force users to do things in "work, then update without recording wip anywhere" order. You can afford to (and it is even more natural to) do things in "work, save and then merge" order with git. I simply cannot believe people who advocate for helping uninitiated would even think of modelling any "user friendliness" features around "up" model. The "save" part of the work-save-then-merge sequence should be made very visible to help people get used to the "not up, but work-save-then-merge" mental model. I do not think it would help people in the long run to make the "save" step less visible by wrapping the sequence into an unreliable "up" script, especially because the script would sometimes work but other times *has to* force users to know that what is happening behind the scene is work-save-then-merge in order to resolve and recover from conflicts anyway. > OTOH, it might be easier to just tell the user to do the stash thing > himself. But I wonder how many users would really know how to get back > to the initial state then. I agree with the first sentence, but I do not understand what "the initial state" you talk about here in the second sentence, sorry. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 9:04 ` Junio C Hamano @ 2009-10-17 17:07 ` James Pickens 2009-10-17 19:41 ` Björn Steinbrink 1 sibling, 0 replies; 93+ messages in thread From: James Pickens @ 2009-10-17 17:07 UTC (permalink / raw) To: Junio C Hamano Cc: Björn Steinbrink, Julian Phillips, Daniel Barkalow, Jeff King, Nicolas Pitre, Jay Soffian, git On Sat, Oct 17, 2009, Junio C Hamano <gitster@pobox.com> wrote: > As I already said many times (here and elsewhere), "up" is an inferior and > more dangerous model we would be better off not following if we can. I agree that the "up" model is inferior, but I have to say, "up" is one of the most common things my users ask about. It is very common for users to have some work in progress that they aren't ready to commit, and they want to get up to date with the latest code from the central repository. Most of the time, they haven't modified any files that have also been modified upstream, so all they need is "git pull". But once in a while, they will have modified the same file, and the pull will be rejected, and they don't know what to do. These are not sophisticated users, so telling them to commit first, then pull, and rebase later on to clean up the history (since the work they committed wasn't finished) is no good. They don't care to preserve their exact state and just want to get up to date with the central repo. If they ask me what to do, I tell them that if they're ready to commit, do so, otherwise use 'git stash; git pull; git stash pop'. To a typical user, this looks like Git is inferior since it requires 3 commands to do what only takes 1 command in CVS/SVN. One of my users didn't ask, and I later found out that he had been doing this: $ git pull ;# rejected due to modifications in file1 $ mv file1 file1.bak $ git checkout HEAD file1 $ git pull ;# rejected due to modifications in file2 $ mv file2 file2.bak $ git checkout HEAD file2 $ git pull ;# ok <manually merge file1.bak with file1> <manually merge file2.bak with file2> So I think an "scm up" like command is not an unreasonable thing to want. There is a valid, and fairly common, use case. There are ways to get the same result in Git, but they're cumbersome compared to just typing "scm up". It shouldn't be the default, but I think a lot of users would appreciate having it. James ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 9:04 ` Junio C Hamano 2009-10-17 17:07 ` James Pickens @ 2009-10-17 19:41 ` Björn Steinbrink 2009-10-18 22:47 ` Junio C Hamano 1 sibling, 1 reply; 93+ messages in thread From: Björn Steinbrink @ 2009-10-17 19:41 UTC (permalink / raw) To: Junio C Hamano Cc: Julian Phillips, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git On 2009.10.17 02:04:02 -0700, Junio C Hamano wrote: > The "save" part of the work-save-then-merge sequence should be made very > visible to help people get used to the "not up, but work-save-then-merge" > mental model. I do not think it would help people in the long run to make > the "save" step less visible by wrapping the sequence into an unreliable > "up" script, especially because the script would sometimes work but other > times *has to* force users to know that what is happening behind the scene > is work-save-then-merge in order to resolve and recover from conflicts > anyway. Hm, which cases would that be? I basically see three cases: 1) No uncommitted changes => No problem 2) Uncommitted changes merge cleanly => No problem 3) Uncommitted changes causes conflicts => - User can resolve - User can start over (git update --retry) - User can give up (git update --abort) Of course the user can clearly see that some state was saved (otherwise you couldn't retry or abort), but I don't see how the user is "forced" in any way, he just gets those two commands to work with (which internally just wrap reset + stash apply, making things more convenient). I do see problems with a "stash around merge" thing ("stash" around rebase seems easier, as that could just create a commit and reset later, but I'm not exactly sure that such smartness is a good idea). As soon as the merge has conflicts, you need to know that you have to unstash after committing the merge, but what I have in mind is fast-forward only (or possibly reset, when upstream was rewritten). Primarily for users that don't commit at all, but just look at things [*1*]. And also for the semi-detached HEAD case, in which you may not commit and in which doing a merge/rebase is therefore not an option, but git still knows what to fetch/checkout by using the discussed extra info in HEAD, or by examining the reflog. > > OTOH, it might be easier to just tell the user to do the stash thing > > himself. But I wonder how many users would really know how to get back > > to the initial state then. > > I agree with the first sentence, but I do not understand what "the initial > state" you talk about here in the second sentence, sorry. The state they were in before they did the "git stash" part. *work on stuff not ready to be committed* git pull # refused git stash git pull git stash apply # Conflicts, user decides that he wants go back At that point, you need the reflog (also handle fast-forwards), and do: git reset --hard HEAD@{1} git stash apply --index Of course, a more correct way might be to use commit and rebase instead: *work on stuff not ready to be committed* git pull # refused git add -A # Or whatever git commit git pull --rebase # conflicts, decide to abort git rebase --abort git reset HEAD^ But that still needs the extra "reset HEAD^" step to really get back to the state with your uncommitted changes. The problem with "svn up" is that there's no other way, and no way back. Git has other ways, but no convenient one for non-committers and no "obvious" way to go back, should you decide that you actually prefer not to update after seeing the conflicts. Anyway, this isn't _my_ itch and to some (large) degree I'm trying to guess what someone else would expect. If at all, I'm more interested in a command that figures out which remote tracking branch I checked out, and that updates it, and updates my work tree/index as well. Uncommitted changes aren't important to me there. So I'll simply give up on that part. Björn [*1*] One could also say: Users that don't give a damn about git, but just need it to get the code and maybe have some minor, uncommitted modifications on top. I'm _not_ thinking about users that actually commit and do stuff. Those should use merge/rebase/pull, and get a complaint from "git update" if the update is not a fast-forward one, telling them what to use instead. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 19:41 ` Björn Steinbrink @ 2009-10-18 22:47 ` Junio C Hamano 2009-10-19 8:44 ` Björn Steinbrink 0 siblings, 1 reply; 93+ messages in thread From: Junio C Hamano @ 2009-10-18 22:47 UTC (permalink / raw) To: Björn Steinbrink Cc: Junio C Hamano, Julian Phillips, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git Björn Steinbrink <B.Steinbrink@gmx.de> writes: > On 2009.10.17 02:04:02 -0700, Junio C Hamano wrote: >> The "save" part of the work-save-then-merge sequence should be made very >> visible to help people get used to the "not up, but work-save-then-merge" >> mental model. I do not think it would help people in the long run to make >> the "save" step less visible by wrapping the sequence into an unreliable >> "up" script, especially because the script would sometimes work but other >> times *has to* force users to know that what is happening behind the scene >> is work-save-then-merge in order to resolve and recover from conflicts >> anyway. > > Hm, which cases would that be? I basically see three cases: > > 1) No uncommitted changes => No problem > 2) Uncommitted changes merge cleanly => No problem > 3) Uncommitted changes causes conflicts => > - User can resolve > - User can start over (git update --retry) > - User can give up (git update --abort) By "--abort", if you meant to discard the local change, that is only suitable for people who would say "what I was doing was minor anyway, and I'll redo them based on the updated upstream", and may not be so useful, I think. The user may want to pretend that he did not even start "update" (i.e. not pulled while he was still working on something) at this point, and if you meant by "give up" (aka --abort) to "reset --hard @{1} && unstash", I think it makes quite a lot of sense. Then the user has an option to fork a topic at that point: git update --abort git checkout -b topic work on more with committing git checkout master git update But then this starts to look more like an enhanced failure recovery mode for "git pull" command. In addition, I think that you would internally implement the "save" step with "stash" (which would be a sane thing to do), but then you would need to worry about the case where the user was in the middle of a merge (or "revert", "cherry-pick", "checkout -m") that did not complete. "git pull" fails upfront, says why and tells users what to do. "git update" should do the same. > I do see problems with a "stash around merge" thing ("stash" around > rebase seems easier, as that could just create a commit and reset later, > but I'm not exactly sure that such smartness is a good idea). As soon as > the merge has conflicts, you need to know that you have to unstash after > committing the merge, but what I have in mind is fast-forward only (or > possibly reset, when upstream was rewritten). Primarily for users that > don't commit at all, but just look at things [*1*]. Ok. If you have a clean way to guarantee that "update" users won't commit, I think the above would sort of make sense and my earlier worries about (1) a user who wish he did not fetch and (2) a user who was doing something more complex and had conflicts already would go away. If the sole target audience is "minor changes only, never committing" people, then I would even rescind my earlier suggestion on --abort; it should mean "remove the minor changes and get pristine copy of the upstream---the user will redo the minor changes to adjust to the updated upstream from scratch", to keep the end user experience simpler and clearer. I am undecided if it is a good thing to divide the userbase into two classes, "update" people and "work-commit-fetch-merge-resolve" people. > [*1*] One could also say: Users that don't give a damn about git, but > just need it to get the code and maybe have some minor, uncommitted > modifications on top. I'm _not_ thinking about users that actually > commit and do stuff. Those should use merge/rebase/pull, and get a > complaint from "git update" if the update is not a fast-forward one, > telling them what to use instead. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-18 22:47 ` Junio C Hamano @ 2009-10-19 8:44 ` Björn Steinbrink 0 siblings, 0 replies; 93+ messages in thread From: Björn Steinbrink @ 2009-10-19 8:44 UTC (permalink / raw) To: Junio C Hamano Cc: Julian Phillips, Daniel Barkalow, James Pickens, Jeff King, Nicolas Pitre, Jay Soffian, git On 2009.10.18 15:47:13 -0700, Junio C Hamano wrote: > Björn Steinbrink <B.Steinbrink@gmx.de> writes: > > On 2009.10.17 02:04:02 -0700, Junio C Hamano wrote: > > 1) No uncommitted changes => No problem > > 2) Uncommitted changes merge cleanly => No problem > > 3) Uncommitted changes causes conflicts => > > - User can resolve > > - User can start over (git update --retry) > > - User can give up (git update --abort) > > By "--abort", if you meant to discard the local change, that is only > suitable for people who would say "what I was doing was minor anyway, and > I'll redo them based on the updated upstream", and may not be so useful, I > think. The user may want to pretend that he did not even start "update" > (i.e. not pulled while he was still working on something) at this point, > and if you meant by "give up" (aka --abort) to "reset --hard @{1} && > unstash", I think it makes quite a lot of sense. Then the user has an > option to fork a topic at that point: > > git update --abort > git checkout -b topic > work on more with committing > git checkout master > git update Yes, I meant the latter. The former would just be "git reset --hard" and is pointless to be rewrapped in "git update --abort". Maybe "abort" is the wrong word there? I'm not a native speaker and basically took that from "git rebase", which returns you to your (unchanged) branch head, i.e. the state you were in before you started the rebase. > But then this starts to look more like an enhanced failure recovery mode > for "git pull" command. Yeah, I notice that, also while working on my "proof-of-concept" implementation. Currently, I simply suggest "git pull" to the user when the update is not a fast-forward one. I'm probably influenced by a latent hatred for "git pull"... Explaining that it is fetch+merge/rebase and uses defaults from the config which are automagically setup is probably something my fingers can do on their own by now. Confusion about "git pull" probably beats misunderstandings about HEAD. If it wasn't so inconvenient for people that actually commit, I'd even dare to suggest: git update - FF update only, using branch.<name>.{remote,merge} - suggests "git update --merge" or "git update --rebase" if non-ff git update --merge - Does a merge git update --rebase - Does a rebase And "git pull" would stop using branch.<name>.{remote,merge} and require command line arguments. That would at least raise awareness that "git update --merge" is doing a merge, unlike "git pull", which many new users simply treat as magic, not realizing what actually happens (and thus they create butt-ugly criss-cross merge histories). Of course, I can't tell whether being aware that a merge happens actually makes the user realize that they shouldn't update/pull/merge 50 times a day. But passing --merge all the time seems just too inconvenient. And having a config option to make --merge or --rebase the default would probably end up with --merge as the "default default", ultimately turning "git update" into "git pull". Anyway, I'm probably getting quite far off the track here. > In addition, I think that you would internally implement the "save" step > with "stash" (which would be a sane thing to do), but then you would need > to worry about the case where the user was in the middle of a merge (or > "revert", "cherry-pick", "checkout -m") that did not complete. "git pull" > fails upfront, says why and tells users what to do. "git update" should > do the same. Yup, got the same check in my PoC > > I do see problems with a "stash around merge" thing ("stash" around > > rebase seems easier, as that could just create a commit and reset later, > > but I'm not exactly sure that such smartness is a good idea). As soon as > > the merge has conflicts, you need to know that you have to unstash after > > committing the merge, but what I have in mind is fast-forward only (or > > possibly reset, when upstream was rewritten). Primarily for users that > > don't commit at all, but just look at things [*1*]. > > Ok. If you have a clean way to guarantee that "update" users won't > commit, I think the above would sort of make sense and my earlier worries > about (1) a user who wish he did not fetch and (2) a user who was doing > something more complex and had conflicts already would go away. Currently it's just: test -z "$(git rev-list -1 $upstream..)" As a "is a fast-forward" check, suggesting the user to use "git pull" instead of "git update", if it is not. Maybe I should use "git merge-base" there instead? Is that better? Not sure whether history simplication might break the rev-list based test... > If the sole target audience is "minor changes only, never committing" > people, then I would even rescind my earlier suggestion on --abort; it > should mean "remove the minor changes and get pristine copy of the > upstream---the user will redo the minor changes to adjust to the updated > upstream from scratch", to keep the end user experience simpler and > clearer. Hmhm... If the user can't resolve the conflict, but still keep those changes, he might want to ask someone else for help. And then he might want to present his changes to that other person, so I think allowing the user to go back to the old commit with his changes on top is better. Maybe "git update --drop" could do the "drop the user's changes", if the user wants to do so. No support for going back is what's bad about "svn update" (and, I guess, "git checkout --merge"). > I am undecided if it is a good thing to divide the userbase into two > classes, "update" people and "work-commit-fetch-merge-resolve" people. I expect that there are already two userbases. Developers in one userbase and users that just want the latest code in the other. And these users might have some uncommitted stuff (either self-made or possibly found somewhere, or maybe a bit of both). I just wonder what's easier/better: to cater to each one or trying to unify them by trying to educate the one that actually doesn't care. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 7:55 ` Björn Steinbrink 2009-10-17 8:11 ` Junio C Hamano @ 2009-10-17 15:02 ` Julian Phillips 1 sibling, 0 replies; 93+ messages in thread From: Julian Phillips @ 2009-10-17 15:02 UTC (permalink / raw) To: Björn Steinbrink Cc: Daniel Barkalow, James Pickens, Jeff King, Junio C Hamano, Nicolas Pitre, Jay Soffian, git On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote: > On 2009.10.16 18:31:23 +0100, Julian Phillips wrote: >> On Fri, 16 Oct 2009, Bj?rn Steinbrink wrote: >>> On 2009.10.16 13:15:35 +0100, Julian Phillips wrote: >>>> How about: >>>> >>>> $ git checkout origin/master >>>> $ git fetch >>>> Refusing to fetch, as it would update a checkedout branch >>>> "git fetch -f" will force the update, but you will need to run "git >>>> reset --hard HEAD" to update your checkout to match. >>> >>> That would redefine -f (currently means "allow non-fast-forward >>> updates"), the flag that allows the checked out branch head to be >>> updated is -u, --update-head-ok, and is for internal use only. >>> >>> And suggesting "reset --hard" seems wrong, that just kills any >>> uncommitted changes. >> >> Ok, so the commands were wrong. Not important. >> >> It was the approach that I was trying to suggest rather than the >> actual commands. The point I was trying to make was how, as a user, >> I would be happy to git behave. > > Your approach explicitly included "mess up the index/worktree state", > otherwise, "git fetch" would not have to tell the user that he has to do > a "git reset --hard HEAD". I honestly can't believe that you would be > happy with git messing up your work. > >> So, I try to run fetch, git says "ooh, now that would be dangerous - >> you can force it happen by running "git foo", but you will then be >> in situation X, which you can then recover from by running "git >> bar", though you may need to run "git stash" to save any edits you >> have made" or something similar. > > But why make "git fetch" with non-"obscure" refspecs dangerous to begin > with? If we detach but keep some extra information, there's no need to > make "git fetch" dangerous, _and_ we can still provide a command that > just fetches the most recent version of the "checked out" remote > tracking branch and checks that out. May it be another mode of operation > for "git pull" or some "git up" command or whatever. My entire argument was in the context of the mail that I orginally replied to, i.e. assuming that the decision to not detach had been taken. If that is not the case, then everything I had said is irrelevant. I wasn't arguing against detaching, but rather trying to say that _if_ we are not going to detach then I think it would better like this than that. I don't personally have any input on the detach or not, as I have been using git for too long to know if detaching is a problem for others. I can tell from my bash prompt if I'm detached or on a branch - and that's fine for me. -- Julian --- Wedding is destiny, and hanging likewise. -- John Heywood ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 20:42 ` Junio C Hamano 2009-10-14 20:48 ` Nicolas Pitre @ 2009-10-14 23:52 ` Eric Raible 1 sibling, 0 replies; 93+ messages in thread From: Eric Raible @ 2009-10-14 23:52 UTC (permalink / raw) To: git Junio C Hamano <gitster <at> pobox.com> writes: > It won't help to alleviate my irritation if I need to give -f to each and > every invocation of "git commit" while detached, though. I'm missing something fundamental here, I think. I simply don't see the advantage of branching after committing over branching before committing. At worst, a temporary is cheap, eh? So what is the value of even allowing committing while HEAD is detached (aside from the historical argument)? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-14 4:44 [PATCH] Proof-of-concept patch to remember what the detached HEAD was Daniel Barkalow ` (2 preceding siblings ...) 2009-10-14 18:56 ` Jay Soffian @ 2009-10-16 22:36 ` Christoph Bartoschek 2009-10-17 7:43 ` Junio C Hamano 3 siblings, 1 reply; 93+ messages in thread From: Christoph Bartoschek @ 2009-10-16 22:36 UTC (permalink / raw) To: git Daniel Barkalow wrote: > The upshot of the messages should be: > > $ git checkout origin/master > Since you can't actually change "origin/master" yourself, you'll just > be sightseeing unless you create a local branch to hold new local work. > > $ git branch > * (not a local branch, but "origin/master") > > $ git commit > You've been sightseeing "origin/master". The commit can't change that > value, so your commit isn't held in any branch. If you want to create > a branch to hold it, here's how. I appreciate such a message for git branch as a user. Today I had the following problem: I wanted to compile Qt Creator 1.3 from their repository. I cloned it with git clone and then issued git checkout origin/1.3.0-beta. First there came a the warning and I was not sure whether the checkout succeeded at all. I had to ask in the IRC channel whether the checkout was ok. But then I was not able to verify that the checkout indeed matched the 1.3.0-beta. "git status" and "git branch" did not help here. Having an improved "git branch" would help a lot, especially if one returns some weeks later to the directory and wants to know what the checkout is. Christoph ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-16 22:36 ` Christoph Bartoschek @ 2009-10-17 7:43 ` Junio C Hamano 2009-10-17 8:19 ` Björn Steinbrink 2009-10-17 20:35 ` Daniel Barkalow 0 siblings, 2 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-17 7:43 UTC (permalink / raw) To: Christoph Bartoschek; +Cc: git, Daniel Barkalow Christoph Bartoschek <bartoschek@gmx.de> writes: [jc: added Daniel back to cc list; please do not cull the cc list without good reason] > Daniel Barkalow wrote: > >> The upshot of the messages should be: >> >> $ git checkout origin/master >> Since you can't actually change "origin/master" yourself, you'll just >> be sightseeing unless you create a local branch to hold new local work. >> >> $ git branch >> * (not a local branch, but "origin/master") >> >> $ git commit >> You've been sightseeing "origin/master". The commit can't change that >> value, so your commit isn't held in any branch. If you want to create >> a branch to hold it, here's how. > ... > But then I was not able to verify that the checkout indeed matched the > 1.3.0-beta. "git status" and "git branch" did not help here. This is not going to help you, but "git reflog" would have helped here. The reason my suggesting "git reflog" now won't help you is because the word "reflog" does not connect the question "how did I get here" unless and until you know git already; in other words, it is not your fault that you got lost, but it is showing a wart in the UI. If the question you were asking was "does the files I have in my work tree after issuing that scary checkout actually match origin/1.3.0-beta?", you could have asked that question in a more direct way, and the command to do so is "git diff origin/1.3.0-beta". I do not think this would be asking the user to be doing something unreasonably unintuitive. If the question you were asking was (and it was not, from the description of your experience, but you could be in that situation when you "return some weeks later") "how does the checked out history relate to 1.3.0-beta?", then there is a way to ask the question in a very direct way, and the command to do so is "git show-branch HEAD origin/1.3.0-beta" (or give the same argument to "gitk"). Although it is not _so_ unreasonable to expect "git status" to show the information, I suspect it would not be practical. After all, whenever somebody is lost, everything is "status". For a person who is lost and does not know where in the history he is, it might be reasonable to expect "status" to give the relationship between your HEAD and some branch/tag, while for another person who was hit by "git gui" complaining that he has too many loose objects, it might be reasonable for him to expect "status" to give the number of loose objects in the repository. IOW, "status" is too broad a word and following the path to cram everything into "status" so that any new person who gets lost can get necessary infor from the command will unfortunately lead to insanity. The second item in the Daniel's transcript above may be an improvement but I think it is a wrong economy to record and show 'but "origin/master"' (which cannot be correct forever and has to be invalidated once the user starts committing or resetting) in the message. I am wondering if a similar effect to help new users can be had by rewording the message to: $ git branch * (not a local branch; see "git reflog" to learn how you got here) The user can see how he got there even after doing something else after the checkout (see Nico's write-up in $gmane/130527). The difference is between giving fish and teaching how to catch one himself. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 7:43 ` Junio C Hamano @ 2009-10-17 8:19 ` Björn Steinbrink 2009-10-17 17:42 ` Junio C Hamano 2009-10-17 20:35 ` Daniel Barkalow 1 sibling, 1 reply; 93+ messages in thread From: Björn Steinbrink @ 2009-10-17 8:19 UTC (permalink / raw) To: Junio C Hamano; +Cc: Christoph Bartoschek, git, Daniel Barkalow On 2009.10.17 00:43:31 -0700, Junio C Hamano wrote: > Christoph Bartoschek <bartoschek@gmx.de> writes: > > Daniel Barkalow wrote: > > > >> The upshot of the messages should be: > >> > >> $ git checkout origin/master > >> Since you can't actually change "origin/master" yourself, you'll just > >> be sightseeing unless you create a local branch to hold new local work. > >> > >> $ git branch > >> * (not a local branch, but "origin/master") > >> > >> $ git commit > >> You've been sightseeing "origin/master". The commit can't change that > >> value, so your commit isn't held in any branch. If you want to create > >> a branch to hold it, here's how. [...] > The second item in the Daniel's transcript above may be an improvement but > I think it is a wrong economy to record and show 'but "origin/master"' > (which cannot be correct forever and has to be invalidated once the user > starts committing or resetting) in the message. I don't think it's entirely wrong to record that information, git just has to know when to invalidate it, possibly requiring the user to really detach HEAD. git checkout origin/master git checkout origin/master~3 git checkout HEAD^2~5 git reset --hard HEAD~2 Those commands are all about walking the ancestry of origin/master in some way. So it seems reasonable to assume that HEAD is still weakly bound to origin/master. And based upon that, there could be something like "git update", and things like "git status" could show that you're browsing through the ancestry of origin/master, and that "git commit" message could maybe say "You've been sightseeing 'origin/master' [currently at 'origin/master~3^2~7'] ...". > I am wondering if a similar effect to help new users can be had by > rewording the message to: > > $ git branch > * (not a local branch; see "git reflog" to learn how you got here) > > The user can see how he got there even after doing something else after > the checkout (see Nico's write-up in $gmane/130527). The difference is > between giving fish and teaching how to catch one himself. That could be used when the user actively detached HEAD, invalidating the "weak binding". Maybe implicitly by "git commit" or "git reset <something_we_can't_keep_track_of>", or maybe explicitly, if committing on a "semi-detached HEAD" becomes forbidden. Or maybe it could always be shown, in addition to "You are here", you also get told "Do this to find out how you got there". Does seem like a good idea. Björn ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 8:19 ` Björn Steinbrink @ 2009-10-17 17:42 ` Junio C Hamano 0 siblings, 0 replies; 93+ messages in thread From: Junio C Hamano @ 2009-10-17 17:42 UTC (permalink / raw) To: Björn Steinbrink Cc: Junio C Hamano, Christoph Bartoschek, git, Daniel Barkalow Björn Steinbrink <B.Steinbrink@gmx.de> writes: > On 2009.10.17 00:43:31 -0700, Junio C Hamano wrote: >> Christoph Bartoschek <bartoschek@gmx.de> writes: >> > Daniel Barkalow wrote: >> > >> >> The upshot of the messages should be: >> >> >> >> $ git checkout origin/master >> >> Since you can't actually change "origin/master" yourself, you'll just >> >> be sightseeing unless you create a local branch to hold new local work. >> >> >> >> $ git branch >> >> * (not a local branch, but "origin/master") >> >> >> >> $ git commit >> >> You've been sightseeing "origin/master". The commit can't change that >> >> value, so your commit isn't held in any branch. If you want to create >> >> a branch to hold it, here's how. > > [...] > >> The second item in the Daniel's transcript above may be an improvement but >> I think it is a wrong economy to record and show 'but "origin/master"' >> (which cannot be correct forever and has to be invalidated once the user >> starts committing or resetting) in the message. > > I don't think it's entirely wrong to record that information, git just > has to know when to invalidate it, possibly requiring the user to really > detach HEAD. Isn't it redundant information to begin with? See $gmane/130527 > git checkout origin/master > git checkout origin/master~3 > git checkout HEAD^2~5 > git reset --hard HEAD~2 > > Those commands are all about walking the ancestry of origin/master in > some way. So it seems reasonable to assume that HEAD is still weakly > bound to origin/master. But as "walking" gets longer, the information will become less and less relevant and at some point it becomes misleading. I cannot explain why "let's take pains to maintain and carefully invalidate an extra piece of redundant information so that we can show information the end user shouldn't be trained to trust to begin with because it is unreliable" is a good idea. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was 2009-10-17 7:43 ` Junio C Hamano 2009-10-17 8:19 ` Björn Steinbrink @ 2009-10-17 20:35 ` Daniel Barkalow 1 sibling, 0 replies; 93+ messages in thread From: Daniel Barkalow @ 2009-10-17 20:35 UTC (permalink / raw) To: Junio C Hamano; +Cc: Christoph Bartoschek, git On Sat, 17 Oct 2009, Junio C Hamano wrote: > Christoph Bartoschek <bartoschek@gmx.de> writes: > > [jc: added Daniel back to cc list; please do not cull the cc list without > good reason] > > > Daniel Barkalow wrote: > > > >> The upshot of the messages should be: > >> > >> $ git checkout origin/master > >> Since you can't actually change "origin/master" yourself, you'll just > >> be sightseeing unless you create a local branch to hold new local work. > >> > >> $ git branch > >> * (not a local branch, but "origin/master") > >> > >> $ git commit > >> You've been sightseeing "origin/master". The commit can't change that > >> value, so your commit isn't held in any branch. If you want to create > >> a branch to hold it, here's how. > > ... > > But then I was not able to verify that the checkout indeed matched the > > 1.3.0-beta. "git status" and "git branch" did not help here. > > This is not going to help you, but "git reflog" would have helped here. > > The reason my suggesting "git reflog" now won't help you is because the > word "reflog" does not connect the question "how did I get here" unless > and until you know git already; in other words, it is not your fault that > you got lost, but it is showing a wart in the UI. > > If the question you were asking was "does the files I have in my work tree > after issuing that scary checkout actually match origin/1.3.0-beta?", you > could have asked that question in a more direct way, and the command to do > so is "git diff origin/1.3.0-beta". I do not think this would be asking > the user to be doing something unreasonably unintuitive. > > If the question you were asking was (and it was not, from the description > of your experience, but you could be in that situation when you "return > some weeks later") "how does the checked out history relate to 1.3.0-beta?", > then there is a way to ask the question in a very direct way, and the > command to do so is "git show-branch HEAD origin/1.3.0-beta" (or give the > same argument to "gitk"). > > Although it is not _so_ unreasonable to expect "git status" to show the > information, I suspect it would not be practical. After all, whenever > somebody is lost, everything is "status". For a person who is lost and > does not know where in the history he is, it might be reasonable to expect > "status" to give the relationship between your HEAD and some branch/tag, > while for another person who was hit by "git gui" complaining that he has > too many loose objects, it might be reasonable for him to expect "status" > to give the number of loose objects in the repository. IOW, "status" is > too broad a word and following the path to cram everything into "status" > so that any new person who gets lost can get necessary infor from the > command will unfortunately lead to insanity. > > The second item in the Daniel's transcript above may be an improvement but > I think it is a wrong economy to record and show 'but "origin/master"' > (which cannot be correct forever and has to be invalidated once the user > starts committing or resetting) in the message. It's easy to invalidate it for reasons of the user going elsewhere: you invalidate it when you invalidate MERGE_HEAD (which, incidentally, locates a bug in my original patch: there's a third "unlink(git_path("MERGE_HEAD"));" I didn't think of, in builtin-merge.c). I think the case of it going stale, mainly due to updating a ref it uses, is a matter of having whatever wants to describe HEAD check if the extended sha1 still expands to the same sha1. I also think that it fits with the git world model to distinguish "lvalues" from "non-lvalues". An "lvalue" is something where you can make a commit and change the value while the expression stays the same; you can assign to it. If your current position is not an "lvalue" and you commit, your current position must become a new temporary "lvalue", diverging from the thing you can't change. But if you don't assign to it, there's no problem with having a non-lvalue be your current position. > I am wondering if a similar effect to help new users can be had by > rewording the message to: > > $ git branch > * (not a local branch; see "git reflog" to learn how you got here) > > The user can see how he got there even after doing something else after > the checkout (see Nico's write-up in $gmane/130527). The difference is > between giving fish and teaching how to catch one himself. The reflog hint is a good one in general; on the other hand, I think it would be generally helpful to have the information in a more machine-readable fashion, for a "git checkout (whatever I gave to reset or checkout before)". Perhaps the right implementation is actually to have machine-readable descriptions in the HEAD reflog? That would actually lead to the interesting: $ git checkout topic $ git checkout origin/master $ git checkout HEAD@{1} $ git branch * topic Actually, we turn out to have a flaw in our reflog explanation: when rebase finishes, it doesn't log that it's back to a particular branch. -Daniel *This .sig left intentionally blank* ^ permalink raw reply [flat|nested] 93+ messages in thread
end of thread, other threads:[~2009-10-27 17:59 UTC | newest] Thread overview: 93+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-10-14 4:44 [PATCH] Proof-of-concept patch to remember what the detached HEAD was Daniel Barkalow 2009-10-14 5:07 ` Junio C Hamano 2009-10-14 5:08 ` Jeff King 2009-10-14 10:33 ` Johannes Schindelin 2009-10-14 15:39 ` Jeff King 2009-10-14 18:34 ` Junio C Hamano 2009-10-14 18:40 ` Jeff King 2009-10-14 15:56 ` Daniel Barkalow 2009-10-14 18:56 ` Jay Soffian 2009-10-14 19:15 ` Daniel Barkalow 2009-10-14 20:18 ` Nicolas Pitre 2009-10-14 20:37 ` Daniel Barkalow 2009-10-14 20:42 ` Junio C Hamano 2009-10-14 20:48 ` Nicolas Pitre 2009-10-14 22:34 ` Junio C Hamano 2009-10-14 23:09 ` Jeff King 2009-10-14 23:34 ` Nicolas Pitre 2009-10-15 0:56 ` Junio C Hamano 2009-10-15 1:47 ` Jeff King 2009-10-15 3:08 ` Nicolas Pitre 2009-10-15 4:21 ` Jeff King 2009-10-16 1:04 ` Johannes Schindelin 2009-10-16 1:36 ` Nicolas Pitre 2009-10-16 2:07 ` Johannes Schindelin 2009-10-16 2:45 ` Nicolas Pitre 2009-10-16 2:56 ` Junio C Hamano 2009-10-17 7:24 ` Sean Estabrooks 2009-10-26 22:22 ` Johannes Schindelin 2009-10-27 3:41 ` Nanako Shiraishi 2009-10-27 10:33 ` Making Git easy to use -- without RTFM, was " Johannes Schindelin 2009-10-27 17:58 ` Avery Pennarun 2009-10-16 0:53 ` Johannes Schindelin 2009-10-16 3:00 ` Junio C Hamano 2009-10-15 7:36 ` James Pickens 2009-10-15 12:54 ` Jakub Narebski 2009-10-15 14:11 ` Björn Steinbrink 2009-10-15 19:03 ` Nicolas Pitre 2009-10-15 15:36 ` Daniel Barkalow 2009-10-15 16:29 ` Michael J Gruber 2009-10-15 19:07 ` Nicolas Pitre 2009-10-15 19:22 ` Daniel Barkalow 2009-10-15 22:56 ` Thomas Rast 2009-10-15 18:51 ` Nicolas Pitre 2009-10-15 19:52 ` Junio C Hamano 2009-10-15 21:26 ` Jeff King 2009-10-15 21:54 ` Junio C Hamano 2009-10-15 22:08 ` Junio C Hamano 2009-10-15 23:16 ` Nicolas Pitre 2009-10-15 23:47 ` James Pickens 2009-10-16 0:34 ` Nicolas Pitre 2009-10-16 0:43 ` Johannes Schindelin 2009-10-16 5:03 ` Björn Steinbrink 2009-10-15 22:16 ` Jeff King 2009-10-15 22:17 ` Jeff King 2009-10-16 4:29 ` Björn Steinbrink 2009-10-16 6:02 ` Daniel Barkalow 2009-10-16 8:27 ` Björn Steinbrink 2009-10-16 15:44 ` Nicolas Pitre 2009-10-15 19:31 ` Daniel Barkalow 2009-10-15 20:34 ` Junio C Hamano 2009-10-15 21:35 ` Daniel Barkalow 2009-10-15 21:48 ` Nicolas Pitre 2009-10-16 12:15 ` Julian Phillips 2009-10-16 14:30 ` Björn Steinbrink 2009-10-16 17:31 ` Julian Phillips 2009-10-16 18:29 ` Daniel Barkalow 2009-10-16 19:05 ` Junio C Hamano 2009-10-16 19:48 ` Julian Phillips 2009-10-16 20:19 ` Nicolas Pitre 2009-10-17 15:15 ` Julian Phillips 2009-10-17 17:04 ` Björn Steinbrink 2009-10-17 17:35 ` Julian Phillips 2009-10-17 17:48 ` Björn Steinbrink 2009-10-17 22:28 ` Julian Phillips 2009-10-16 20:19 ` Junio C Hamano 2009-10-17 15:32 ` Julian Phillips 2009-10-17 17:43 ` Junio C Hamano 2009-10-17 22:19 ` Julian Phillips 2009-10-17 7:55 ` Björn Steinbrink 2009-10-17 8:11 ` Junio C Hamano 2009-10-17 8:40 ` Björn Steinbrink 2009-10-17 9:04 ` Junio C Hamano 2009-10-17 17:07 ` James Pickens 2009-10-17 19:41 ` Björn Steinbrink 2009-10-18 22:47 ` Junio C Hamano 2009-10-19 8:44 ` Björn Steinbrink 2009-10-17 15:02 ` Julian Phillips 2009-10-14 23:52 ` Eric Raible 2009-10-16 22:36 ` Christoph Bartoschek 2009-10-17 7:43 ` Junio C Hamano 2009-10-17 8:19 ` Björn Steinbrink 2009-10-17 17:42 ` Junio C Hamano 2009-10-17 20:35 ` Daniel Barkalow
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).