Git development
 help / color / mirror / Atom feed
* Re: master^ is not a local branch -- huh?!?
From: Ron Garret @ 2010-01-30  6:23 UTC (permalink / raw)
  To: git
In-Reply-To: <76718491001292052x7f46d479lfeff7b66121502c3@mail.gmail.com>

In article 
<76718491001292052x7f46d479lfeff7b66121502c3@mail.gmail.com>,
 Jay Soffian <jaysoffian@gmail.com> wrote:

> On Fri, Jan 29, 2010 at 9:59 PM, Junio C Hamano <gitster@pobox.com> wrote:
> > Ron Garret <ron1@flownet.com> writes:
> >
> >> 1.  The term "detached HEAD" is inherently misleading.  A detached HEAD
> >> isn't detached from anything, it's just pointing to the middle of a
> >> branch, which is to say, to a commit that happens to already have
> >> descendants.  For that matter, the name HEAD is itself misleading, since
> >> HEAD need not be the head of a branch (though normally it is).  A better
> >> name for HEAD would have been CURRENT or ACTIVE.  I recognize it's
> >> probably too late to change it now.
> >
> > This description, especially the phrase "middle of a branch" shows that
> > you don't understand git yet.  A git branch is _not_ a line (nor multiple
> > lines) of development.  It is merely a _point_ in the history.
> >
> > "A commit that is in the middle of an ancestry chain with existing
> > descendants" can be at the tip of a branch and does not have anything to
> > do with detached HEAD state.
> >
> > When HEAD points at a branch, making a commit advances _that_ branch.  And
> > we say you are "on that branch".  When HEAD is detached, because it is not
> > attached to anything, it advances no branch.  "detached HEAD" is detached
> > in the very real sense.  It is not attached to _any_ branch.
> 
> Let me try wording this slightly different, because I think I can see
> Ron's confusion.

[snip]

> So that was a really long explanation, but I hope it clears things up.

Yes, that was very helpful, thank you.

Might it make more sense to talk about "anonymous branches" or "unnamed 
branches" instead of "detached heads"?  I think something like the 
following would be much easier to grasp:

WARNING: Your HEAD is now pointing to a commit that is not a named
branch head.  As a result of this, any commits off of this one may
be lost during the next garbage collection.  If you want to prevent
this, you should give this branch head a name by doing ...

rg

^ permalink raw reply

* Re: [PATCH] fast-import: Stream very large blobs directly to pack
From: Junio C Hamano @ 2010-01-30  6:19 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Sverre Rabbelier, git, Nicolas Pitre
In-Reply-To: <7vockc45ut.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> "Shawn O. Pearce" <spearce@spearce.org> writes:
>
>> I was intentionally slating this for maint, to fix a bug a user
>> reported when handling large streams.
>
> I personally see that as adding a new feature (especially with new option
> and config).

Sorry, but I take it back.  The new codepath triggers even without any
explicit request and _fixes_ the situation where old code simply failed,
so it is worth queuing for the maintenance track.

Do you want to do the deflatebound thing, or are we Ok without?

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Ron Garret @ 2010-01-30  6:16 UTC (permalink / raw)
  To: git
In-Reply-To: <7vvdek70ma.fsf@alter.siamese.dyndns.org>

In article <7vvdek70ma.fsf@alter.siamese.dyndns.org>,
 Junio C Hamano <gitster@pobox.com> wrote:

> Michael Witten <mfwitten@gmail.com> writes:
> 
> > Isn't the difference between 'checkout' and 'reset' almost essentially
> > a matter of whether the branch reference (HEAD), index, and tree are
> > modified? Couldn't these commands be merged into one command or make
> > use of one command?
> 
> I don't think that reduces any confusion.

Ahem... as the confused one here I respectfully disagree.

> By exposing orthogonal options like --index, --head, etc., you are opening
> yourself to nonsensical combinations that were never possible with the
> existing command set, and I suspect it would make it even more confusing,
> not less.

No, because it would make it much easier to map intent back into a 
command that implements that intent.  Don't forget, this whole thing 
began because I wanted to do something very simple, tried what seemed to 
be the obvious way to do it, and stumbled accidentally on an advanced 
feature.  That would not have happened if I'd been able to just do a git 
update --tree master^.

> What does "git update --detach $commit" _really_ mean, for example?

What difference does that make?  Sure, there would be ways to shoot 
yourself in the foot with git update, but there is no shortage of ways 
to shoot yourself in the foot now.  And now if you shoot yourself in the 
foot you have to start by trying to figure out where the bullet came 
from.

BTW, nothing prevents you from providing the usual repertoire of 
higher-level functionality as thin layers on top of something like git 
update.

> You can of course say "it detaches the HEAD at $commit, but otherwise does
> not change anything else", but such a mechanical description does not give
> an answer that helps end users.  "What would I do after doing that?" and
> "What would I use this for?" are the questions they need an answer to.

Sure.  So document the combinations that make sense, and then say "You 
can mix and match the options in other ways, but you probably shouldn't 
unless you really know what you're doing."  Done.

> Flexibility and orthogonality is often good, but uncontrolled flexibility
> is not.

That seems to me to run directly counter to the design philosophy behind 
git.

rg

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Junio C Hamano @ 2010-01-30  6:03 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Mark Lodato, Sverre Rabbelier, Git List, Ron1, Jacob Helwig
In-Reply-To: <alpine.LFD.2.00.1001292305500.1681@xanadu.home>

Nicolas Pitre <nico@fluxnic.net> writes:

> First, I'm afraid that "Checking out commit 'foobar'" might be confusing 
> as this may happen through either a remote branch, a tag, or any random 
> commit.  It seems to me that "Checking out 'v2.5'" is less confusing 
> than "Checking out commit 'v2.5'".  But that's a minor detail and 
> probably a personal preference.
> ...
> To the contrary: this "detached HEAD" is exactly what you need if you 
> want to relate to any documentation or perform a search for more 
> information.  Like it or not, this detached HEAD term is exactly what 
> this Git concept is all about and how it is designated everywhere.  The 
> sooner Git users see and learn about it the better.

As I am not good at keeping track of different proposals to change this
word here and that word there, I expect this will probably need at least
few rotations of earth to get input from people in different timezones,
and I think this is post 1.7.0 item anyway, I'll queue the attached draft
in 'pu' and keep it there, to make it easier for others to tweak the
message.

-- >8 --
Subject: [PATCH] Reword "detached HEAD" notification

The old "advice" message explained how to create a branch after going into
a detached HEAD state but didn't make it clear why the user may want to do
so.  Also "moving to ... which isn't a local branch" was unclear if it is
complaining, if it is describing the new state, or if it is explaining why
the HEAD is detached (the true reason is the last one).

Give the established phrase 'detached HEAD' first to make it easy for
users to look up the concept in documentation, and briefly describe what
can be done in the state (i.e. play around without having to clean up)
before telling the user how to keep what was done during the temporary
state.

Allow the long description to be hidden by setting advice.detachedHead
configuration to false.

We might want to customize the advice depending on how the commit to check
out was spelled (e.g. instead of "new-branch-name", we way want to say
"topic" when "git checkout origin/topic" triggered this message) in later
updates, but this encapsulates that into a separate function and it should
be a good first step.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt |    5 +++++
 advice.c                 |    2 ++
 advice.h                 |    1 +
 builtin-checkout.c       |   18 ++++++++++++++++--
 t/t7201-co.sh            |   32 ++++++++++++++++++++++----------
 5 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 17901e2..fee44d8 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -138,6 +138,11 @@ advice.*::
 		Advice on how to set your identity configuration when
 		your information is guessed from the system username and
 		domain name. Default: true.
+
+	detachedHead::
+		Advice shown when you used linkgit::git-checkout[1] to
+		move to the detach HEAD state, to instruct how to create
+		a local branch after the fact.  Default: true.
 --
 
 core.fileMode::
diff --git a/advice.c b/advice.c
index 936d98b..0be4b5f 100644
--- a/advice.c
+++ b/advice.c
@@ -5,6 +5,7 @@ int advice_status_hints = 1;
 int advice_commit_before_merge = 1;
 int advice_resolve_conflict = 1;
 int advice_implicit_identity = 1;
+int advice_detached_head = 1;
 
 static struct {
 	const char *name;
@@ -15,6 +16,7 @@ static struct {
 	{ "commitbeforemerge", &advice_commit_before_merge },
 	{ "resolveconflict", &advice_resolve_conflict },
 	{ "implicitidentity", &advice_implicit_identity },
+	{ "detachedhead", &advice_detached_head },
 };
 
 int git_default_advice_config(const char *var, const char *value)
diff --git a/advice.h b/advice.h
index 9b7a3ad..3244ebb 100644
--- a/advice.h
+++ b/advice.h
@@ -8,6 +8,7 @@ extern int advice_status_hints;
 extern int advice_commit_before_merge;
 extern int advice_resolve_conflict;
 extern int advice_implicit_identity;
+extern int advice_detached_head;
 
 int git_default_advice_config(const char *var, const char *value);
 
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 5277817..c5ab783 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -488,6 +488,20 @@ static void report_tracking(struct branch_info *new)
 	strbuf_release(&sb);
 }
 
+static void detach_advice(const char *old_path, const char *new_name)
+{
+	const char fmt[] =
+	"Note: checking out '%s'.\n\n"
+	"You are in 'detached HEAD' state. You can look around, make experimental\n"
+	"changes and commit them, and you can discard any commits you make in this\n"
+	"state without impacting any branches by performing another checkout.\n\n"
+	"If you want to create a new branch to retain commits you create, you may\n"
+	"do so (now or later) by using -b with the checkout command again. Example:\n\n"
+	"  git checkout -b new_branch_name\n\n";
+
+	fprintf(stderr, fmt, new_name);
+}
+
 static void update_refs_for_switch(struct checkout_opts *opts,
 				   struct branch_info *old,
 				   struct branch_info *new)
@@ -522,8 +536,8 @@ static void update_refs_for_switch(struct checkout_opts *opts,
 		update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
 			   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);
+			if (old->path && advice_detached_head)
+				detach_advice(old->path, new->name);
 			describe_detached_head("HEAD is now at", new->commit);
 		}
 	}
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 6442f71..d20ed61 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -166,19 +166,31 @@ test_expect_success 'checkout -m with merge conflict' '
 	! test -s current
 '
 
-test_expect_success 'checkout to detach HEAD' '
+test_expect_success 'checkout to detach HEAD (with advice declined)' '
 
+	git config advice.detachedHead false &&
 	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>
-HEAD is now at 7329388... Initial A one, A two
-EOF
-) &&
-	test_cmp messages.expect messages &&
+	grep "HEAD is now at 7329388" messages &&
+	test 1 -eq $(wc -l <messages) &&
+	H=$(git rev-parse --verify HEAD) &&
+	M=$(git show-ref -s --verify refs/heads/master) &&
+	test "z$H" = "z$M" &&
+	if git symbolic-ref HEAD >/dev/null 2>&1
+	then
+		echo "OOPS, HEAD is still symbolic???"
+		false
+	else
+		: happy
+	fi
+'
+
+test_expect_success 'checkout to detach HEAD' '
+	git config advice.detachedHead true &&
+	git checkout -f renamer && git clean -f &&
+	git checkout renamer^ 2>messages &&
+	grep "HEAD is now at 7329388" messages &&
+	test 1 -lt $(wc -l <messages) &&
 	H=$(git rev-parse --verify HEAD) &&
 	M=$(git show-ref -s --verify refs/heads/master) &&
 	test "z$H" = "z$M" &&
-- 
1.7.0.rc0.187.g226c

^ permalink raw reply related

* Re: master^ is not a local branch -- huh?!?
From: Mark Lodato @ 2010-01-30  5:53 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Junio C Hamano, Sverre Rabbelier, Git List, Ron1, Jacob Helwig
In-Reply-To: <alpine.LFD.2.00.1001292305500.1681@xanadu.home>

On Fri, Jan 29, 2010 at 11:39 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
> First, I'm afraid that "Checking out commit 'foobar'" might be confusing
> as this may happen through either a remote branch, a tag, or any random
> commit.  It seems to me that "Checking out 'v2.5'" is less confusing
> than "Checking out commit 'v2.5'".  But that's a minor detail and
> probably a personal preference.

I'm fine with "Checking out 'v2.5'".

> I consider that starting the explanation paragraph with " any commits
> you make will be lost" is even more unfriendly, and misleading.  That is
> sure to scare people needlessly.

See wording below.

> I think your wording is just too far on the negative side, and makes Git
> look like an even more difficult tool than it actually is.  And you help
> no one by stating things that are not exactly true even if the truth
> implies that you need to know what you're doing.

What is not true?  Sure, they're not really "lost", but there's no
concise yet fully correct way to say the full truth.  Would you prefer
"discarded"?

> The _whole_ and only
> point of a detached HEAD is actually to be able to make commits even
> without having to create a new branch first.

Wrong.  I have never (purposefully) made a commit on a detached HEAD,
yet I use a detached HEAD all the time.  Why?  Because I checkout a
particular commit to look at code at a given location.  For example, I
recently ran "git checkout v1.6.6.1".  I did not intend to make any
commits on this; I just wanted to look at and compile code at a
particular version.  I think most users do the same thing.  The reason
for the warning is that folks make a mistake of trying to commit
without first switching back to (or creating) a branch.


Anyway, how about the following message, which is more in line with
Junio's last version?

-- >8 -- not a patch -- >8 --
Checking out 'master^0'.

This is not a local branch head, so you are in a 'detached HEAD' state.
If you only plan to look at files, this is fine.  However, any commits you
make will not update a branch, and may be discarded when you check out
another branch or commit.

If you want to create a new branch to retain commits you create, 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 a9d7c95... Merge branch 'maint'
-- 8< -- not a patch -- 8< --

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Jay Soffian @ 2010-01-30  5:45 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Junio C Hamano, Ron Garret, git
In-Reply-To: <alpine.LFD.2.00.1001300011290.1681@xanadu.home>

On Sat, Jan 30, 2010 at 12:15 AM, Nicolas Pitre <nico@fluxnic.net> wrote:
> Could you please take this really nice explanation and make it into a
> patch adding a "Detached HEAD" section in the git-checkout.txt manual
> page please?

Will do, and I'll even make the branches go upwards. :-)

j.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Nicolas Pitre @ 2010-01-30  5:25 UTC (permalink / raw)
  To: Jay Soffian
  Cc: Mark Lodato, Junio C Hamano, Sverre Rabbelier, Git List, Ron1,
	Jacob Helwig
In-Reply-To: <76718491001292111y2d15620ei8a12c081a9283a07@mail.gmail.com>

On Sat, 30 Jan 2010, Jay Soffian wrote:

> This sounds right to me too. There's nothing wrong with having a
> detached HEAD, and nothing wrong with creating commits in that state.
> You're effectively creating an anonymous branch in the DAG and it's
> subject to garbage collection if you move away from that anonymous
> branch w/o naming it.
> 
> Pedantic note: you don't lose those commits at the next checkout. They
> are merely subject to garbage collection (and not until they age out
> of HEAD's reflog). I know you know that, just being precise. :-)

Being the actual author of the code managing the separate HEAD reflog, I 
do know that indeed.  ;-)


Nicolas

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Junio C Hamano @ 2010-01-30  5:21 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Jay Soffian, Ron Garret, git
In-Reply-To: <alpine.LFD.2.00.1001300011290.1681@xanadu.home>

Nicolas Pitre <nico@fluxnic.net> writes:

> Could you please take this really nice explanation and make it into a 
> patch adding a "Detached HEAD" section in the git-checkout.txt manual 
> page please?

Good suggestion.

I'd be happier if the description didn't say "SHA-1", but instead said
"object name".

Also it would be nicer (just a personal preference) if a picture that
forks only one branch forks it upwards, like this:

             o---o
            /    
    ---o---o---o

not downwards, like this:

    ---o---o---o
            \
             o---o

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Junio C Hamano @ 2010-01-30  5:18 UTC (permalink / raw)
  To: Jay Soffian; +Cc: Ron Garret, git
In-Reply-To: <76718491001292052x7f46d479lfeff7b66121502c3@mail.gmail.com>

Jay Soffian <jaysoffian@gmail.com> writes:

> So that was a really long explanation, but I hope it clears things up.
> I think the disconnect between you and Junio is that you're thinking
> of branches in the DAG sense of the word, while Junio is talking about
> them in the context of git.

Yeah, in short, a "branch" is a point, not a line (or lines) of
development that leads to a point, as I said in the beginning.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Nicolas Pitre @ 2010-01-30  5:15 UTC (permalink / raw)
  To: Jay Soffian; +Cc: Junio C Hamano, Ron Garret, git
In-Reply-To: <76718491001292052x7f46d479lfeff7b66121502c3@mail.gmail.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 612 bytes --]

On Fri, 29 Jan 2010, Jay Soffian wrote:

> > When HEAD points at a branch, making a commit advances _that_ branch.  And
> > we say you are "on that branch".  When HEAD is detached, because it is not
> > attached to anything, it advances no branch.  "detached HEAD" is detached
> > in the very real sense.  It is not attached to _any_ branch.
> 
> Let me try wording this slightly different, because I think I can see
> Ron's confusion.
[...]

Could you please take this really nice explanation and make it into a 
patch adding a "Detached HEAD" section in the git-checkout.txt manual 
page please?


Nicolas

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Jay Soffian @ 2010-01-30  5:11 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Mark Lodato, Junio C Hamano, Sverre Rabbelier, Git List, Ron1,
	Jacob Helwig
In-Reply-To: <alpine.LFD.2.00.1001292352540.1681@xanadu.home>

On Sat, Jan 30, 2010 at 12:05 AM, Nicolas Pitre <nico@fluxnic.net> wrote:
> Thinking more about it, I still consider that making 'git commit' more
> noisy is the wrong approach.  Again, the problem is not about making
> commits on a detached HEAD.  but rather about losing those commits at
> the next 'git checkout'.  Probably a warning should be made when that
> checkout is attempted after one or more commits were made on a detached
> HEAD instead, and refuse the checkout by default unless it is forced (-f
> is already taken for some other force meaning).  The warning should say
> how not to lose those commits by suggesting a branch creation, or give
> the hint for performing the checkout anyway.

This sounds right to me too. There's nothing wrong with having a
detached HEAD, and nothing wrong with creating commits in that state.
You're effectively creating an anonymous branch in the DAG and it's
subject to garbage collection if you move away from that anonymous
branch w/o naming it.

Pedantic note: you don't lose those commits at the next checkout. They
are merely subject to garbage collection (and not until they age out
of HEAD's reflog). I know you know that, just being precise. :-)

j.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Junio C Hamano @ 2010-01-30  5:09 UTC (permalink / raw)
  To: Ron Garret; +Cc: git
In-Reply-To: <ron1-8B7921.19261029012010@news.gmane.org>

Ron Garret <ron1@flownet.com> writes:

>> When HEAD points at a branch, making a commit advances _that_ branch.  And
>> we say you are "on that branch".  When HEAD is detached, because it is not
>> attached to anything, it advances no branch.  "detached HEAD" is detached
>> in the very real sense.  It is not attached to _any_ branch.
>
> OK.  The docs do not make that clear at all.  In fact, the following 
> statement, copied straight from the manual, flatly contradicts what you 
> just said:

There are many places in the documentation that simply predate the
introduction of detached HEAD.  The description talks as if you cannot be
in any state other than on a particular branch.  For example, "git pull"
talks about choosing where to fetch from and what to merge to the head
based on what your current branch is---obviously such a description is
ancient and doesn't talk about what should happen when you do not simply
have any "current" branch.

So it is understandable that you get confused and it is all
documentation's fault, not yours.

> "The special symbol "HEAD" can always be used to refer to the current 
> branch."
>
> Always.  Except when it can't.

Exactly.

We would need to update the documentation.  While doing so, a general
guideline would be to keep in mind that they were written back when you
had to always be on _a_ branch (and they called it "current branch",
"branch HEAD points at", etc.).  When they describe that "the current
branch is updated in such and such way", what happens in a detached HEAD
state is that only the HEAD pointer that directly points at the "currently
checked out commit" is updated, without affecting _any_ branch.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Jay Soffian @ 2010-01-30  5:06 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Ron Garret, git
In-Reply-To: <alpine.LFD.2.00.1001292232130.1681@xanadu.home>

On Fri, Jan 29, 2010 at 11:03 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
> Have a look at http://eagain.net/articles/git-for-computer-scientists/
>
> That's one of the clearest explanation of the Git branching model I've
> seen.

Ah, I never realized this before, but it doesn't include any
discussion/graphic of what a detached HEAD is. It only shows HEAD
referring to a named branch.

> There is no contradiction.  The "detached HEAD" corresponds to HEAD
> pointing at no branch in particular.  There is just no current branch in
> that case.

Again (referring to my last message), I think Ron's confusion is that
"branch" can mean either a branch in the DAG which is your repo's
history, or it can mean a named branch (something under .git/refs),
and they aren't necessarily the same, although around here when we say
"branch" we almost always mean a named branch.

When HEAD is detached and you create a commit, you're effectively
creating a branch in the DAG, but this branch is anonymous and subject
to garbage collection.

j.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Nicolas Pitre @ 2010-01-30  5:05 UTC (permalink / raw)
  To: Mark Lodato
  Cc: Junio C Hamano, Sverre Rabbelier, Git List, Ron1, Jacob Helwig
In-Reply-To: <alpine.LFD.2.00.1001292305500.1681@xanadu.home>

On Fri, 29 Jan 2010, Nicolas Pitre wrote:

> On Fri, 29 Jan 2010, Mark Lodato wrote:
> 
> > This discussion brings up another good point: The main worry about a
> > detached head is losing commits.  Back in 2008, it was suggested to
> > have a warning when committing on a detached HEAD:
> > 
> > http://kerneltrap.org/mailarchive/git/2008/9/2/3169744
> > 
> > This was before the advice system, so folks complained about it
> > getting in the way, and it was never implemented.  Since we now have a
> > way to easily turn off the warning, perhaps we should bring this topic
> > up again (probably as a separate thread.)
> 
> Possibly.  I don't like the message proposed in that patch though.  
> Since the warning when actually detaching HEAD is about to become way 
> more prominent, the per-commit warning doesn't have to be that noisy 
> anymore.

Thinking more about it, I still consider that making 'git commit' more 
noisy is the wrong approach.  Again, the problem is not about making 
commits on a detached HEAD.  but rather about losing those commits at 
the next 'git checkout'.  Probably a warning should be made when that 
checkout is attempted after one or more commits were made on a detached 
HEAD instead, and refuse the checkout by default unless it is forced (-f 
is already taken for some other force meaning).  The warning should say 
how not to lose those commits by suggesting a branch creation, or give 
the hint for performing the checkout anyway.


Nicolas

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Jay Soffian @ 2010-01-30  4:52 UTC (permalink / raw)
  To: Junio C Hamano, Ron Garret; +Cc: git
In-Reply-To: <7vbpgc8fhb.fsf@alter.siamese.dyndns.org>

On Fri, Jan 29, 2010 at 9:59 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Ron Garret <ron1@flownet.com> writes:
>
>> 1.  The term "detached HEAD" is inherently misleading.  A detached HEAD
>> isn't detached from anything, it's just pointing to the middle of a
>> branch, which is to say, to a commit that happens to already have
>> descendants.  For that matter, the name HEAD is itself misleading, since
>> HEAD need not be the head of a branch (though normally it is).  A better
>> name for HEAD would have been CURRENT or ACTIVE.  I recognize it's
>> probably too late to change it now.
>
> This description, especially the phrase "middle of a branch" shows that
> you don't understand git yet.  A git branch is _not_ a line (nor multiple
> lines) of development.  It is merely a _point_ in the history.
>
> "A commit that is in the middle of an ancestry chain with existing
> descendants" can be at the tip of a branch and does not have anything to
> do with detached HEAD state.
>
> When HEAD points at a branch, making a commit advances _that_ branch.  And
> we say you are "on that branch".  When HEAD is detached, because it is not
> attached to anything, it advances no branch.  "detached HEAD" is detached
> in the very real sense.  It is not attached to _any_ branch.

Let me try wording this slightly different, because I think I can see
Ron's confusion.

HEAD normally refers to a named branch. For example "master"
(technically, HEAD would contain "ref: refs/heads/master"), but we'll
just say "master" for now.

Meanwhile, the branch named "master" refers to a specific commit by
its SHA-1 hash.

The particular commit which "master" refers to is a branch head.

Now, when you create a commit in this state, the branch named "master"
is updated with the SHA-1 of the new commit. So let's say you create a
new repo and have three commits. Your history would look like this:

a---b---c master (HEAD is "ref: refs/heads/master")

That is, if you look at .git/HEAD, it will say "ref:
refs/heads/master" and if you look at .git/refs/heads/master it will
have the SHA-1 of commit "c". If you create a new commit:

a---b---c---d master (HEAD is "ref: refs/heads/master")

.git/HEAD still says "ref: refs/heads/master" but now
.git/refs/heads/master has the SHA-1 of commit "d".

Okay, now let's talk about what happens when you type:

$ git checkout master^

At this point, git updates HEAD to contain the SHA-1 of "c":

a---b---c---d master (HEAD is c's SHA-1)

You now have a "detached HEAD" because HEAD doesn't refer to any named
branch. Instead it refers to a specific commit by its SHA-1. So let's
create a new commit while HEAD is detached:

a---b---c---d master
         \
          e   (HEAD is e's SHA-1)

So, yes, you've created a "branch" in the DAG sense of the word. But
this branch is anonymous since it has no name. That means that commit
"e" is subject to garbage collection and may be removed. If you want
to keep it around, then you need to create a name for it. Git provides
you a number of ways to "name" commits:

$ git checkout -b foo # (1)
$ git branch foo      # (2)
$ git tag foo         # (3)

(1) will create .git/refs/heads/foo, make it have the SHA-1 of commit
"e", then update HEAD to say "ref: refs/heads/foo". You are now "on"
branch "foo" and any commits you create will update
.git/refs/heads/foo:

a---b---c---d master
         \
          e  foo (HEAD is "ref: refs/heads/foo")

(2) will also create .refs/heads/foo, and make it have the SHA-1 of
commit "e", but will leave HEAD as it is:

a---b---c---d master
         \
          e  foo (HEAD is SHA-1 of "e")

You still have a detached HEAD and any commits you create that descend
from "e" are still subject to garbage collection (although "e" itself
is not), as follows:

a---b---c---d master
         \
          e  <-- foo
           \
            f (HEAD is SHA-1 of "f")

(3) creates .refs/tags/foo, but is otherwise the same as (2).

So that was a really long explanation, but I hope it clears things up.
I think the disconnect between you and Junio is that you're thinking
of branches in the DAG sense of the word, while Junio is talking about
them in the context of git.

j.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Nicolas Pitre @ 2010-01-30  4:39 UTC (permalink / raw)
  To: Mark Lodato
  Cc: Junio C Hamano, Sverre Rabbelier, Git List, Ron1, Jacob Helwig
In-Reply-To: <ca433831001291959m76ed6adap32a17c10e465af1f@mail.gmail.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 4993 bytes --]

On Fri, 29 Jan 2010, Mark Lodato wrote:

> On Fri, Jan 29, 2010 at 10:11 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
> > On Fri, 29 Jan 2010, Mark Lodato wrote:
> >> On Fri, Jan 29, 2010 at 8:22 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
> >> > On Fri, 29 Jan 2010, Mark Lodato wrote:
> >> >
> >> >> Still, I find it slightly confusing and unfriendly.  How about the following?
> >> >
> >> >> Checking out commit 'master^0'.
> >> >>
> >> >> Since this is not a local branch head, any commits you make will be lost
> >> >> when you check out another branch or commit.  (In git terminology, HEAD
> >> >> is detached.)  If you just wish to look at files without committing,
> >> >> this is fine.  If you wish to make commits and retain them, you may
> >> >> create a new branch by running:
> >> >>
> >> >>   git checkout -b <new_branch_name>
> >> >
> >> > This gives the impression that any commit you make on a detached HEAD
> >> > are going to be lost, unless you create a new branch first.
> >>
> >> What about "...you may want to create..."?  This does not imply that
> >> creating a new branch now is the *only* way, just the most likely.  If
> >> a user knows another way, that user probably does not need this
> >> warning in the first place.
> >
> > Still, you don't know what way the unsuspected user will take to get
> > there.
> 
> Sorry, I don't understand.  What do you mean by "take to get there"?
> Are you referring to how the user arrived in this detached HEAD state,

Yes.

> or what the user wishes to do next?  Either way, I still am not sure
> why this wording is no good.  Could please elaborate?

First, I'm afraid that "Checking out commit 'foobar'" might be confusing 
as this may happen through either a remote branch, a tag, or any random 
commit.  It seems to me that "Checking out 'v2.5'" is less confusing 
than "Checking out commit 'v2.5'".  But that's a minor detail and 
probably a personal preference.

>   Note: 'master^0' isn't a local branch head;
> 
> This isn't very friendly.  It sounds like an admonition.  Rather, I
> suggest that the first sentence be similar to, but distinct from,
> "Switched to branch foo," to inform the user that they did something
> different, which may or may not be intentional.

I consider that starting the explanation paragraph with " any commits 
you make will be lost" is even more unfriendly, and misleading.  That is 
sure to scare people needlessly.

>   You are in 'detached HEAD' state. You can look around, make experimental
>   changes and commit them, and you can discard any commits you make in this
>   state without impacting any branches by checking out another branch.
> 
> First, we shouldn't start off with the term "detached HEAD".  I used a
> parenthetical comment to mention it, in case the user wants to look it
> up or refer to this state.  Otherwise, the term conveys no meaning,
> unless one understand enough about git to not need this advice.

To the contrary: this "detached HEAD" is exactly what you need if you 
want to relate to any documentation or perform a search for more 
information.  Like it or not, this detached HEAD term is exactly what 
this Git concept is all about and how it is designated everywhere.  The 
sooner Git users see and learn about it the better.

> Second, this advice should be a warning that commits may be lost
> unless one knows what one is doing.  Saying "you can discard commits"
> makes it sound like a feature!  Sure, that may be so for advanced
> users, but for beginners (for whom this advice is intended), this is a
> common trap.  I tried to word the advice so that the users will know
> that they should not commit without first creating a branch (or
> knowing what they're doing), but that if they don't commit, there's no
> problem.  The wording quoted above does not convey this meaning to me.

I think your wording is just too far on the negative side, and makes Git 
look like an even more difficult tool than it actually is.  And you help 
no one by stating things that are not exactly true even if the truth 
implies that you need to know what you're doing.  The _whole_ and only 
point of a detached HEAD is actually to be able to make commits even 
without having to create a new branch first.

> This discussion brings up another good point: The main worry about a
> detached head is losing commits.  Back in 2008, it was suggested to
> have a warning when committing on a detached HEAD:
> 
> http://kerneltrap.org/mailarchive/git/2008/9/2/3169744
> 
> This was before the advice system, so folks complained about it
> getting in the way, and it was never implemented.  Since we now have a
> way to easily turn off the warning, perhaps we should bring this topic
> up again (probably as a separate thread.)

Possibly.  I don't like the message proposed in that patch though.  
Since the warning when actually detaching HEAD is about to become way 
more prominent, the per-commit warning doesn't have to be that noisy 
anymore.


Nicolas

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Nicolas Pitre @ 2010-01-30  4:03 UTC (permalink / raw)
  To: Ron Garret; +Cc: git
In-Reply-To: <ron1-8B7921.19261029012010@news.gmane.org>

On Fri, 29 Jan 2010, Ron Garret wrote:

> In article <7vbpgc8fhb.fsf@alter.siamese.dyndns.org>,
>  Junio C Hamano <gitster@pobox.com> wrote:
> 
> > "A commit that is in the middle of an ancestry chain with existing
> > descendants" can be at the tip of a branch and does not have anything to
> > do with detached HEAD state.
> 
> Ah, then you're right.  I really don't get it yet.

Have a look at http://eagain.net/articles/git-for-computer-scientists/

That's one of the clearest explanation of the Git branching model I've 
seen.

> > When HEAD points at a branch, making a commit advances _that_ branch.  And
> > we say you are "on that branch".  When HEAD is detached, because it is not
> > attached to anything, it advances no branch.  "detached HEAD" is detached
> > in the very real sense.  It is not attached to _any_ branch.
> 
> OK.  The docs do not make that clear at all.  In fact, the following 
> statement, copied straight from the manual, flatly contradicts what you 
> just said:
> 
> "The special symbol "HEAD" can always be used to refer to the current 
> branch."
> 
> Always.  Except when it can't.

There is no contradiction.  The "detached HEAD" corresponds to HEAD 
pointing at no branch in particular.  There is just no current branch in 
that case.

> Soooo.....
> 
> Sometimes HEAD can refer to a branch head which is a pointer to a 
> commit, and sometimes HEAD can refer to a commit directly without 
> indirecting through a branch head (lower case), in which case it is 
> detached.  Is that right?

Exact.

> If that's true, then I'm back to wondering what good is a detached head.  
> Why would you ever want one?  What can you do with a detached head that 
> you could not do just as easily without one?

By definition, remote tracking branches are "read-only" because we want 
those branch heads to reflect what the remote repository they're 
tracking has.  In other words, you're not supposed to add commits to a 
remote branch or it would move that branch to the new commit which is no 
longer a representation of the corresponding remote repository.  In 
order to actually add commits on top of a remote branch, you first have 
to make a local branch being a copy of the remote branch of interest 
(which in practice means only making the local branch point at the same 
commit node as the remote branch) and then any commit will advance that 
local branch and leave the remote branch behind.

But what if you just want to check out the content corresponding to that 
remote branch without adding any new commits?  What if you wish to do 
the same with a tag instead of a branch (a tag being immutable)?

If you could have HEAD pointing to a tag or a remote branch then many 
operations such as 'git commit' would need to be blocked in order to 
preserve the read-only nature of such references.

The detached HEAD solves the issue really neatly in those cases.  
Instead of having HEAD pointing to a remote branch record, the detached 
HEAD points directly at the provided commit from the remote branch head 
or tag, and any commit operation will simply update that direct 
reference alone, creating a fork point in the history graph.

If you wish to preserve this branch in the graph sense then you can 
create a new branch head with the current HEAD position.  Or if you 
don't care about those commits you made on the detached HEAD, then 
simply moving HEAD to anything else with another checkout command will 
drop and forget about that string of commits you created.

So a detached HEAD is useful for checking out a read-only branch or tag 
without having to forbid a bunch of operations or needing for you to 
create a dummy temporary local branch just for the purpose of such a 
checkout.  Many operations with intermediate states such as 'git rebase' 
or 'git bisect' can be implemented without polluting the branch 
namespace, etc.


Nicolas

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Mark Lodato @ 2010-01-30  3:59 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Junio C Hamano, Sverre Rabbelier, Git List, Ron1, Jacob Helwig
In-Reply-To: <alpine.LFD.2.00.1001292208470.1681@xanadu.home>

On Fri, Jan 29, 2010 at 10:11 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
> On Fri, 29 Jan 2010, Mark Lodato wrote:
>> On Fri, Jan 29, 2010 at 8:22 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
>> > On Fri, 29 Jan 2010, Mark Lodato wrote:
>> >
>> >> Still, I find it slightly confusing and unfriendly.  How about the following?
>> >
>> >> Checking out commit 'master^0'.
>> >>
>> >> Since this is not a local branch head, any commits you make will be lost
>> >> when you check out another branch or commit.  (In git terminology, HEAD
>> >> is detached.)  If you just wish to look at files without committing,
>> >> this is fine.  If you wish to make commits and retain them, you may
>> >> create a new branch by running:
>> >>
>> >>   git checkout -b <new_branch_name>
>> >
>> > This gives the impression that any commit you make on a detached HEAD
>> > are going to be lost, unless you create a new branch first.
>>
>> What about "...you may want to create..."?  This does not imply that
>> creating a new branch now is the *only* way, just the most likely.  If
>> a user knows another way, that user probably does not need this
>> warning in the first place.
>
> Still, you don't know what way the unsuspected user will take to get
> there.

Sorry, I don't understand.  What do you mean by "take to get there"?
Are you referring to how the user arrived in this detached HEAD state,
or what the user wishes to do next?  Either way, I still am not sure
why this wording is no good.  Could please elaborate?

> Do you still have a problem with the latest version of the text from
> Junio?  Looks like you based your modification on an earlier version.

Yes, I do.  I thought his earlier version was more clear.  Particularly:

  Note: 'master^0' isn't a local branch head;

This isn't very friendly.  It sounds like an admonition.  Rather, I
suggest that the first sentence be similar to, but distinct from,
"Switched to branch foo," to inform the user that they did something
different, which may or may not be intentional.

  You are in 'detached HEAD' state. You can look around, make experimental
  changes and commit them, and you can discard any commits you make in this
  state without impacting any branches by checking out another branch.

First, we shouldn't start off with the term "detached HEAD".  I used a
parenthetical comment to mention it, in case the user wants to look it
up or refer to this state.  Otherwise, the term conveys no meaning,
unless one understand enough about git to not need this advice.

Second, this advice should be a warning that commits may be lost
unless one knows what one is doing.  Saying "you can discard commits"
makes it sound like a feature!  Sure, that may be so for advanced
users, but for beginners (for whom this advice is intended), this is a
common trap.  I tried to word the advice so that the users will know
that they should not commit without first creating a branch (or
knowing what they're doing), but that if they don't commit, there's no
problem.  The wording quoted above does not convey this meaning to me.

  If you want to create a new branch to retain commits you create, you may
  do so (now or later) by using -b with the checkout command again. Example:

    git checkout -b <new_branch_name>

I basically retained this, with rewording.


This discussion brings up another good point: The main worry about a
detached head is losing commits.  Back in 2008, it was suggested to
have a warning when committing on a detached HEAD:

http://kerneltrap.org/mailarchive/git/2008/9/2/3169744

This was before the advice system, so folks complained about it
getting in the way, and it was never implemented.  Since we now have a
way to easily turn off the warning, perhaps we should bring this topic
up again (probably as a separate thread.)

^ permalink raw reply

* Re: [PATCH] fast-import: Stream very large blobs directly to pack
From: Junio C Hamano @ 2010-01-30  3:41 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Sverre Rabbelier, Junio C Hamano, git, Nicolas Pitre
In-Reply-To: <20100129183705.GB22101@spearce.org>

"Shawn O. Pearce" <spearce@spearce.org> writes:

> Sverre Rabbelier <srabbelier@gmail.com> wrote:
>> On Fri, Jan 29, 2010 at 02:23, Shawn O. Pearce <spearce@spearce.org> wrote:
>> > index 60d0aa2..8114f93 100644
>> 
>> Looks like you based it off an old version of fast-import, at least
>> not on what is in master atm, since that has my fast-import series.
>> Rebasing shouldn't be too hard, you'll just have to move the option
>> parsing to the appropriate function.
>
> I was intentionally slating this for maint, to fix a bug a user
> reported when handling large streams.

I personally see that as adding a new feature (especially with new option
and config).

> But yea... I guess I also owe Junio a rebased form for master so
> he has less merge conflicts to resolve.

Thanks.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Ron Garret @ 2010-01-30  3:26 UTC (permalink / raw)
  To: git
In-Reply-To: <7vbpgc8fhb.fsf@alter.siamese.dyndns.org>

In article <7vbpgc8fhb.fsf@alter.siamese.dyndns.org>,
 Junio C Hamano <gitster@pobox.com> wrote:

> Ron Garret <ron1@flownet.com> writes:
> 
> > 1.  The term "detached HEAD" is inherently misleading.  A detached HEAD 
> > isn't detached from anything, it's just pointing to the middle of a 
> > branch, which is to say, to a commit that happens to already have 
> > descendants.  For that matter, the name HEAD is itself misleading, since 
> > HEAD need not be the head of a branch (though normally it is).  A better 
> > name for HEAD would have been CURRENT or ACTIVE.  I recognize it's 
> > probably too late to change it now.
> 
> This description, especially the phrase "middle of a branch" shows that
> you don't understand git yet.

That could well be, but it's not for lack of trying :-)

> A git branch is _not_ a line (nor multiple
> lines) of development.  It is merely a _point_ in the history.

By "middle of a branch" I simply meant "a commit that already has one or 
more descendants" (or, to be even more precise, a commit that has one or 
more commits that reference that commit as one of their predecessors).  
I do understand that histories aren't linear.

> "A commit that is in the middle of an ancestry chain with existing
> descendants" can be at the tip of a branch and does not have anything to
> do with detached HEAD state.

Ah, then you're right.  I really don't get it yet.

> When HEAD points at a branch, making a commit advances _that_ branch.  And
> we say you are "on that branch".  When HEAD is detached, because it is not
> attached to anything, it advances no branch.  "detached HEAD" is detached
> in the very real sense.  It is not attached to _any_ branch.

OK.  The docs do not make that clear at all.  In fact, the following 
statement, copied straight from the manual, flatly contradicts what you 
just said:

"The special symbol "HEAD" can always be used to refer to the current 
branch."

Always.  Except when it can't.

Soooo.....

Sometimes HEAD can refer to a branch head which is a pointer to a 
commit, and sometimes HEAD can refer to a commit directly without 
indirecting through a branch head (lower case), in which case it is 
detached.  Is that right?

If that's true, then I'm back to wondering what good is a detached head.  
Why would you ever want one?  What can you do with a detached head that 
you could not do just as easily without one?

rg

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Nicolas Pitre @ 2010-01-30  3:15 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Junio C Hamano, Sverre Rabbelier, Git List, Ron1, Jacob Helwig
In-Reply-To: <alpine.DEB.1.00.1001300312450.3749@intel-tinevez-2-302>

On Sat, 30 Jan 2010, Johannes Schindelin wrote:

> Hi,
> 
> On Fri, 29 Jan 2010, Nicolas Pitre wrote:
> 
> > With all due respects, I don't share Dscho's sentiment about Git's 
> > alleged non user-friendliness.
> 
> Of course you don't.  You are a Git oldtimer.  Probably you do not even 
> have much exposure to complete programming newbies.

Welllll... That depends.

If you mean people who, despite a CS degree, are still unable to figure 
out if some loop exit condition should be > or >= except by testing the 
compiled code and see if a crash occurs, then yes I do feel the pain of 
being exposed to such people way too often for my taste.  And frankly I 
just don't care if those people can't grok the Git UI.

Git is meant to be a tool for people performing a minimum of development 
tasks.  If those people can't grasp the Git UI and concepts with little 
effort then they're either 1) uninterested or 2) incompetent.  For the 
uninterested people there are GUIs out there.  And don't get me started 
on the incompetent ones.

And for the rest of the world, such as my boss, there is gitweb.

> Well, guess what.  I have.  And guess what even more: they are the 
> majority, not you and me.

Did you ever got them to use P4?  I'm convinced that learning how to use 
P4 for a Git user is way more painful than a P4 user to learn Git.  
Similarly for Arch or many other alternatives.

HG looks easier?  Sure.  But it isn't exactly as flexible and powerful 
as Git is though.  You prefer a less powerful but simpler tool? OK just 
go with HG then -- I have no problem with that.  Even SVN might be just 
what you need.  But if you prefer the power of Git then there is a price 
to pay for it.  Making Git simpler would inevitably reduces its power.

I hope newbies won't stay newbies all their life.  If the majority of 
all the people are newbies then no need to wonder why there is so much 
crap being produced by the computing industry then.  Learning isn't only 
a nasty thing that they force you to do at school and which you get over 
with once you escape from there.

Incidentally we've been getting more positive feedback than negative 
ones about Git from newbies on this list lately.  That might be because 
our UI, although still not perfect, improved quite a bit, and most 
probably because the documentation surrounding Git has improved 
tremendously too.


Nicolas

^ permalink raw reply

* [PATCH] git-svn: persistent memoization
From: Andrew Myrick @ 2010-01-30  3:14 UTC (permalink / raw)
  To: git; +Cc: normalperson, sam, Andrew Myrick

Make memoization of the svn:mergeinfo processing functions persistent with
Memoize::Storable so that the memoization tables don't need to be regenerated
every time the user runs git-svn fetch.

The Memoize::Storable hashes are stored in ENV{GIT_DIR}/svn/caches.

Signed-off-by: Andrew Myrick <amyrick@apple.com>
---
 git-svn.perl |   42 +++++++++++++++++++++++++++++++++++++-----
 1 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 1f201e4..f7a9410 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -1632,10 +1632,11 @@ use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent
             $_use_svnsync_props $no_reuse_existing $_minimize_url
 	    $_use_log_author $_add_author_from $_localtime/;
 use Carp qw/croak/;
-use File::Path qw/mkpath/;
+use File::Path qw/mkpath make_path/;
 use File::Copy qw/copy/;
 use IPC::Open3;
 use Memoize;  # core since 5.8.0, Jul 2002
+use Memoize::Storable;
 
 my ($_gc_nr, $_gc_period);
 
@@ -3078,10 +3079,39 @@ sub has_no_changes {
 		command_oneline("rev-parse", "$commit~1^{tree}"));
 }
 
-BEGIN {
-	memoize 'lookup_svn_merge';
-	memoize 'check_cherry_pick';
-	memoize 'has_no_changes';
+# The GIT_DIR environment variable is not always set until after the command
+# line arguments are processed, so we can't memoize in a BEGIN block.
+{
+	my $memoized = 0;
+
+	sub memoize_svn_mergeinfo_functions {
+		return if $memoized;
+		$memoized = 1;
+
+		my $cache_path = "$ENV{GIT_DIR}/svn/caches/";
+		make_path($cache_path) unless -d $cache_path;
+
+		tie my %lookup_svn_merge_cache =>
+			'Memoize::Storable',"$cache_path/lookup_svn_merge.db", 'nstore';
+		memoize 'lookup_svn_merge',
+			SCALAR_CACHE => 'FAULT',
+			LIST_CACHE => ['HASH' => \%lookup_svn_merge_cache],
+		;
+
+		tie my %check_cherry_pick_cache =>
+			'Memoize::Storable',"$cache_path/check_cherry_pick.db", 'nstore';
+		memoize 'check_cherry_pick',
+			SCALAR_CACHE => 'FAULT',
+			LIST_CACHE => ['HASH' => \%check_cherry_pick_cache],
+		;
+
+		tie my %has_no_changes_cache =>
+			'Memoize::Storable',"$cache_path/has_no_changes.db", 'nstore';
+		memoize 'has_no_changes',
+			SCALAR_CACHE => ['HASH' => \%has_no_changes_cache],
+			LIST_CACHE => 'FAULT',
+		;
+	}
 }
 
 sub parents_exclude {
@@ -3125,6 +3155,8 @@ sub find_extra_svn_parents {
 	my ($self, $ed, $mergeinfo, $parents) = @_;
 	# aha!  svk:merge property changed...
 
+	memoize_svn_mergeinfo_functions();
+
 	# We first search for merged tips which are not in our
 	# history.  Then, we figure out which git revisions are in
 	# that tip, but not this revision.  If all of those revisions
-- 
1.6.6.1.4.g3df0a5.dirty

^ permalink raw reply related

* Re: master^ is not a local branch -- huh?!?
From: Nicolas Pitre @ 2010-01-30  3:11 UTC (permalink / raw)
  To: Mark Lodato
  Cc: Junio C Hamano, Sverre Rabbelier, Git List, Ron1, Jacob Helwig
In-Reply-To: <ca433831001291840o751fa02eve1ae301537674325@mail.gmail.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1407 bytes --]

On Fri, 29 Jan 2010, Mark Lodato wrote:

> On Fri, Jan 29, 2010 at 8:22 PM, Nicolas Pitre <nico@fluxnic.net> wrote:
> > On Fri, 29 Jan 2010, Mark Lodato wrote:
> >
> >> Still, I find it slightly confusing and unfriendly.  How about the following?
> >
> > It is slightly inaccurate.
> 
> Is the following the only inaccuracy?  Do you have any other feedback?
> 
> >> Checking out commit 'master^0'.
> >>
> >> Since this is not a local branch head, any commits you make will be lost
> >> when you check out another branch or commit.  (In git terminology, HEAD
> >> is detached.)  If you just wish to look at files without committing,
> >> this is fine.  If you wish to make commits and retain them, you may
> >> create a new branch by running:
> >>
> >>   git checkout -b <new_branch_name>
> >
> > This gives the impression that any commit you make on a detached HEAD
> > are going to be lost, unless you create a new branch first.
> 
> What about "...you may want to create..."?  This does not imply that
> creating a new branch now is the *only* way, just the most likely.  If
> a user knows another way, that user probably does not need this
> warning in the first place.

Still, you don't know what way the unsuspected user will take to get 
there.

Do you still have a problem with the latest version of the text from 
Junio?  Looks like you based your modification on an earlier version.


Nicolas

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Junio C Hamano @ 2010-01-30  3:06 UTC (permalink / raw)
  To: Michael Witten; +Cc: Ron Garret, git
In-Reply-To: <b4087cc51001291633l68760880i340d12e865641077@mail.gmail.com>

Michael Witten <mfwitten@gmail.com> writes:

> Isn't the difference between 'checkout' and 'reset' almost essentially
> a matter of whether the branch reference (HEAD), index, and tree are
> modified? Couldn't these commands be merged into one command or make
> use of one command?

I don't think that reduces any confusion.

By exposing orthogonal options like --index, --head, etc., you are opening
yourself to nonsensical combinations that were never possible with the
existing command set, and I suspect it would make it even more confusing,
not less.

What does "git update --detach $commit" _really_ mean, for example?

You can of course say "it detaches the HEAD at $commit, but otherwise does
not change anything else", but such a mechanical description does not give
an answer that helps end users.  "What would I do after doing that?" and
"What would I use this for?" are the questions they need an answer to.

What matters is "after doing this, next commit will record _this_, which
is often what users want in _that_ situation, and that is why this
combination of options makes sense."  Do all (or majority) of option
combinations to your "update" think have _meaning_ in that sense?  I don't
think so.

Flexibility and orthogonality is often good, but uncontrolled flexibility
is not.  And I suspect your "git update" is just an uncontrolled mess that
would not help users [*1*].

[Footnote]

*1* It is a different matter to have something like that as an ingredient
to build Porcelain scripts out of.  Porcelain writers may appreciate the
flexibility and they will choose to use only combinations that make sense
for the situation they are trying to deal with.

^ permalink raw reply

* Re: master^ is not a local branch -- huh?!?
From: Junio C Hamano @ 2010-01-30  2:59 UTC (permalink / raw)
  To: Ron Garret; +Cc: git
In-Reply-To: <ron1-F006CF.18381129012010@news.gmane.org>

Ron Garret <ron1@flownet.com> writes:

> 1.  The term "detached HEAD" is inherently misleading.  A detached HEAD 
> isn't detached from anything, it's just pointing to the middle of a 
> branch, which is to say, to a commit that happens to already have 
> descendants.  For that matter, the name HEAD is itself misleading, since 
> HEAD need not be the head of a branch (though normally it is).  A better 
> name for HEAD would have been CURRENT or ACTIVE.  I recognize it's 
> probably too late to change it now.

This description, especially the phrase "middle of a branch" shows that
you don't understand git yet.  A git branch is _not_ a line (nor multiple
lines) of development.  It is merely a _point_ in the history.

"A commit that is in the middle of an ancestry chain with existing
descendants" can be at the tip of a branch and does not have anything to
do with detached HEAD state.

When HEAD points at a branch, making a commit advances _that_ branch.  And
we say you are "on that branch".  When HEAD is detached, because it is not
attached to anything, it advances no branch.  "detached HEAD" is detached
in the very real sense.  It is not attached to _any_ branch.

> 2.  There are a lot of things in the documentation that turn out, now 
> that I understand what is going on, to be subtly misleading.  For 
> example, "A single git repository can track development on multiple 
> branches. It does this by keeping a list of heads which reference the 
> latest commit on each branch."  That last part is only true if the heads 
> are not "detached".

This is from old terminology.  We used to use "head" (lowercase) and
"branches" pretty much interchangeably and the quoted description is from
the era _before_ detached HEAD was invented, as a way to quickly get a
temporary state where you can browse around freely and without having to
worry about having to clean up afterwards even if you made commits in that
state by simply going back to an attached state.

So do a "s/a list of heads/a list of branch pointers/" replacement and you
will be fine.

> Another example: "The HEAD then refers to the SHA-1 of the commit 
> instead of to a branch, and git branch shows that you are no longer on a 
> branch:"  But you *are* on a branch, you just aren't at the head of the 
> branch.

No, you are _literally_ not on _any_ branch at that point.

Making a commit from that state does not advance _any_ branch and doing
"reset --hard $commit" from that state does not affect _any_ branch.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox