{"thread":{"id":"9964","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","startedAt":"2007-09-21T20:27:01Z","lastAt":"2007-09-26T19:23:53Z","messageCount":16,"participants":["Josh England","root","Junio C Hamano","Andreas Ericsson","Dmitry Potapov"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"53766","messageId":"1190406421-15620-1-git-send-email-jjengla@sandia.gov","threadId":"9964","inReplyTo":null,"subject":"[PATCH] post-checkout hook, and related docs and tests","fromName":"root","fromEmail":"root@sandia.gov","sentAt":"2007-09-21T20:27:01Z","receivedAt":"2007-09-21T20:27:01Z","isPatch":true,"sender":{"key":"root@sandia.gov","avatar":null},"body":"Signed-off-by: Josh England <jjengla@sandia.gov>\n---\n Documentation/hooks.txt       |   10 +++++++\n git-checkout.sh               |    5 +++\n t/t5403-post-checkout-hook.sh |   61 +++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 76 insertions(+), 0 deletions(-)\n create mode 100755 t/t5403-post-checkout-hook.sh\n\ndiff --git a/Documentation/hooks.txt b/Documentation/hooks.txt\nindex c39edc5..e78f91a 100644\n--- a/Documentation/hooks.txt\n+++ b/Documentation/hooks.txt\n@@ -87,6 +87,16 @@ parameter, and is invoked after a commit is made.\n This hook is meant primarily for notification, and cannot affect\n the outcome of `git-commit`.\n \n+post-checkout\n+-----------\n+\n+This hook is invoked when a `git-checkout` is run on a local repository.\n+The hook is given two parameters: the ref of the previous HEAD, and the ref of \n+the new HEAD.  This hook cannot affect the outcome of `git-checkout`.\n+\n+This hook can be used to perform repository validity checks, auto-display\n+differences from the previous HEAD, or set working dir metadata properties.\n+\n [[pre-receive]]\n pre-receive\n -----------\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 17f4392..0cff36c 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -284,3 +284,8 @@ if [ \"$?\" -eq 0 ]; then\n else\n \texit 1\n fi\n+\n+# Run a post-checkout hook\n+if test -x \"$GIT_DIR\"/hooks/post-checkout; then\n+        \"$GIT_DIR\"/hooks/post-checkout $old $new\n+fi\ndiff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh\nnew file mode 100755\nindex 0000000..aa0216a\n--- /dev/null\n+++ b/t/t5403-post-checkout-hook.sh\n@@ -0,0 +1,61 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2006 Josh England\n+#\n+\n+test_description='Test the post-checkout hook.'\n+. ./test-lib.sh\n+\n+test_expect_success setup '\n+\techo Data for commit0. >a &&\n+\tgit update-index --add a &&\n+\ttree0=$(git write-tree) &&\n+\tcommit0=$(echo setup | git commit-tree $tree0) &&\n+        git update-ref refs/heads/master $commit0 &&\n+\tgit-clone ./. clone1 &&\n+\tgit-clone ./. clone2 &&\n+        GIT_DIR=clone2/.git git branch -a new2 &&\n+       \techo Data for commit1. >clone2/b &&\n+\tGIT_DIR=clone2/.git git add clone2/b &&\n+\tGIT_DIR=clone2/.git git commit -m new2\n+'\n+\n+for clone in 1 2; do \n+    cat >clone${clone}/.git/hooks/post-checkout <<'EOF'\n+#!/bin/sh\n+echo $@ > $GIT_DIR/post-checkout.args\n+EOF\n+    chmod u+x clone${clone}/.git/hooks/post-checkout\n+done\n+\n+test_expect_success 'post-checkout runs as expected ' '\n+        GIT_DIR=clone1/.git git checkout master &&\n+ \ttest -e clone1/.git/post-checkout.args\n+'\n+\n+test_expect_success 'post-checkout receives the right arguments with HEAD unchanged ' '\n+         old=$(awk \"{print \\$1}\" clone1/.git/post-checkout.args) &&\n+         new=$(awk \"{print \\$2}\" clone1/.git/post-checkout.args) &&         \n+         test $old = $new\n+'\n+\n+test_expect_success 'post-checkout runs as expected ' '\n+        GIT_DIR=clone1/.git git checkout master &&\n+ \ttest -e clone1/.git/post-checkout.args\n+'\n+\n+test_expect_success 'post-checkout args are correct with git checkout -b ' '\n+        GIT_DIR=clone1/.git git checkout -b new1 &&\n+        old=$(awk \"{print \\$1}\" clone1/.git/post-checkout.args) &&\n+        new=$(awk \"{print \\$2}\" clone1/.git/post-checkout.args) &&         \n+        test $old = $new\n+'\n+\n+test_expect_success 'post-checkout receives the right arguments with HEAD changed ' '\n+        GIT_DIR=clone2/.git git checkout new2 &&\n+        old=$(awk \"{print \\$1}\" clone2/.git/post-checkout.args) &&\n+        new=$(awk \"{print \\$2}\" clone2/.git/post-checkout.args) &&         \n+        test $old != $new\n+'\n+\n+test_done\n-- \n1.5.3.1.143.gf417e3-dirty\n"},{"id":"53746","messageId":"1190406921.6541.16.camel@beauty","threadId":"9964","inReplyTo":"1190406421-15620-1-git-send-email-jjengla@sandia.gov","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-21T20:35:21Z","receivedAt":"2007-09-21T20:35:21Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"Junk.  Sorry about the address.  My mailer went retarded.\n\n-JE\n\nOn Fri, 2007-09-21 at 14:27 -0600, root wrote:\n> Signed-off-by: Josh England <jjengla@sandia.gov>\n> ---\n>  Documentation/hooks.txt       |   10 +++++++\n>  git-checkout.sh               |    5 +++\n>  t/t5403-post-checkout-hook.sh |   61 +++++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 76 insertions(+), 0 deletions(-)\n>  create mode 100755 t/t5403-post-checkout-hook.sh\n> \n> diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt\n> index c39edc5..e78f91a 100644\n> --- a/Documentation/hooks.txt\n> +++ b/Documentation/hooks.txt\n> @@ -87,6 +87,16 @@ parameter, and is invoked after a commit is made.\n>  This hook is meant primarily for notification, and cannot affect\n>  the outcome of `git-commit`.\n>  \n> +post-checkout\n> +-----------\n> +\n> +This hook is invoked when a `git-checkout` is run on a local repository.\n> +The hook is given two parameters: the ref of the previous HEAD, and the ref of \n> +the new HEAD.  This hook cannot affect the outcome of `git-checkout`.\n> +\n> +This hook can be used to perform repository validity checks, auto-display\n> +differences from the previous HEAD, or set working dir metadata properties.\n> +\n>  [[pre-receive]]\n>  pre-receive\n>  -----------\n> diff --git a/git-checkout.sh b/git-checkout.sh\n> index 17f4392..0cff36c 100755\n> --- a/git-checkout.sh\n> +++ b/git-checkout.sh\n> @@ -284,3 +284,8 @@ if [ \"$?\" -eq 0 ]; then\n>  else\n>  \texit 1\n>  fi\n> +\n> +# Run a post-checkout hook\n> +if test -x \"$GIT_DIR\"/hooks/post-checkout; then\n> +        \"$GIT_DIR\"/hooks/post-checkout $old $new\n> +fi\n> diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh\n> new file mode 100755\n> index 0000000..aa0216a\n> --- /dev/null\n> +++ b/t/t5403-post-checkout-hook.sh\n> @@ -0,0 +1,61 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2006 Josh England\n> +#\n> +\n> +test_description='Test the post-checkout hook.'\n> +. ./test-lib.sh\n> +\n> +test_expect_success setup '\n> +\techo Data for commit0. >a &&\n> +\tgit update-index --add a &&\n> +\ttree0=$(git write-tree) &&\n> +\tcommit0=$(echo setup | git commit-tree $tree0) &&\n> +        git update-ref refs/heads/master $commit0 &&\n> +\tgit-clone ./. clone1 &&\n> +\tgit-clone ./. clone2 &&\n> +        GIT_DIR=clone2/.git git branch -a new2 &&\n> +       \techo Data for commit1. >clone2/b &&\n> +\tGIT_DIR=clone2/.git git add clone2/b &&\n> +\tGIT_DIR=clone2/.git git commit -m new2\n> +'\n> +\n> +for clone in 1 2; do \n> +    cat >clone${clone}/.git/hooks/post-checkout <<'EOF'\n> +#!/bin/sh\n> +echo $@ > $GIT_DIR/post-checkout.args\n> +EOF\n> +    chmod u+x clone${clone}/.git/hooks/post-checkout\n> +done\n> +\n> +test_expect_success 'post-checkout runs as expected ' '\n> +        GIT_DIR=clone1/.git git checkout master &&\n> + \ttest -e clone1/.git/post-checkout.args\n> +'\n> +\n> +test_expect_success 'post-checkout receives the right arguments with HEAD unchanged ' '\n> +         old=$(awk \"{print \\$1}\" clone1/.git/post-checkout.args) &&\n> +         new=$(awk \"{print \\$2}\" clone1/.git/post-checkout.args) &&         \n> +         test $old = $new\n> +'\n> +\n> +test_expect_success 'post-checkout runs as expected ' '\n> +        GIT_DIR=clone1/.git git checkout master &&\n> + \ttest -e clone1/.git/post-checkout.args\n> +'\n> +\n> +test_expect_success 'post-checkout args are correct with git checkout -b ' '\n> +        GIT_DIR=clone1/.git git checkout -b new1 &&\n> +        old=$(awk \"{print \\$1}\" clone1/.git/post-checkout.args) &&\n> +        new=$(awk \"{print \\$2}\" clone1/.git/post-checkout.args) &&         \n> +        test $old = $new\n> +'\n> +\n> +test_expect_success 'post-checkout receives the right arguments with HEAD changed ' '\n> +        GIT_DIR=clone2/.git git checkout new2 &&\n> +        old=$(awk \"{print \\$1}\" clone2/.git/post-checkout.args) &&\n> +        new=$(awk \"{print \\$2}\" clone2/.git/post-checkout.args) &&         \n> +        test $old != $new\n> +'\n> +\n> +test_done\n"},{"id":"53769","messageId":"7vzlzfh7xd.fsf@gitster.siamese.dyndns.org","threadId":"9964","inReplyTo":"1190406421-15620-1-git-send-email-jjengla@sandia.gov","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-22T00:15:26Z","receivedAt":"2007-09-22T00:15:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"root\" <root@sandia.gov> writes:\n\n> +post-checkout\n> +-----------\n> +\n> +This hook is invoked when a `git-checkout` is run on a local repository.\n> +The hook is given two parameters: the ref of the previous HEAD, and the ref of \n> +the new HEAD.  This hook cannot affect the outcome of `git-checkout`.\n> +\n> +This hook can be used to perform repository validity checks, auto-display\n> +differences from the previous HEAD, or set working dir metadata properties.\n> +\n\nPeople may wonder why this is not run when they do \"git checkout\notherbranch path.c\"; the second sentence from the above\ndescription implies why it shouldn't, but the first sentence\nprobably should state it more clearly.\n\nWhat's the _semantics_ you are trying to achieve?\n\nWhy does the hook run every time git-bisect suggests the next\nrevision to try?\n\nWhy does the hook run when rebase starts its work?\n\nWhen \"git pull\" or \"git merge\" results in a fast forward, the\nsituation is no different from checking out a new revision.  Why\ndoesn't the hook run in these cases?\n"},{"id":"53935","messageId":"1190654052.6078.14.camel@beauty","threadId":"9964","inReplyTo":"7vzlzfh7xd.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-24T17:14:12Z","receivedAt":"2007-09-24T17:14:12Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"On Fri, 2007-09-21 at 17:15 -0700, Junio C Hamano wrote:\n> \"root\" <root@sandia.gov> writes:\n> \n> > +post-checkout\n> > +-----------\n> > +\n> > +This hook is invoked when a `git-checkout` is run on a local repository.\n> > +The hook is given two parameters: the ref of the previous HEAD, and the ref of \n> > +the new HEAD.  This hook cannot affect the outcome of `git-checkout`.\n> > +\n> > +This hook can be used to perform repository validity checks, auto-display\n> > +differences from the previous HEAD, or set working dir metadata properties.\n> > +\n> \n> People may wonder why this is not run when they do \"git checkout\n> otherbranch path.c\"; the second sentence from the above\n> description implies why it shouldn't, but the first sentence\n> probably should state it more clearly.\n> \n> What's the _semantics_ you are trying to achieve?\n\nI'd like to get a hook that runs whenever the working dir gets\nupdated.  The 'git-checkout otherbranch path.c' case should run it also, so I view that as a bug.\n\n> Why does the hook run every time git-bisect suggests the next\n> revision to try?\n> Why does the hook run when rebase starts its work?\n\nIt may be inserted in a ad place or maybe it needs some intelligence in\nthere to know when *not* to run.\n\n> When \"git pull\" or \"git merge\" results in a fast forward, the\n> situation is no different from checking out a new revision.  Why\n> doesn't the hook run in these cases?\n\nThis is actually what I'd like to do.  I submitted the post-merge patch\nsome time ago to serve that purpose.  Do you think they should both be\nrolled into a single post-checkout hook?  It would seem to make sense to\nme.\n"},{"id":"53937","messageId":"1190656680.6078.26.camel@beauty","threadId":"9964","inReplyTo":"7vzlzfh7xd.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-24T17:58:00Z","receivedAt":"2007-09-24T17:58:00Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"On Fri, 2007-09-21 at 17:15 -0700, Junio C Hamano wrote:\n> \"root\" <root@sandia.gov> writes:\n> \n> > +post-checkout\n> > +-----------\n> > +\n> > +This hook is invoked when a `git-checkout` is run on a local repository.\n> > +The hook is given two parameters: the ref of the previous HEAD, and the ref of \n> > +the new HEAD.  This hook cannot affect the outcome of `git-checkout`.\n> > +\n> > +This hook can be used to perform repository validity checks, auto-display\n> > +differences from the previous HEAD, or set working dir metadata properties.\n> > +\n> \n> People may wonder why this is not run when they do \"git checkout\n> otherbranch path.c\"; the second sentence from the above\n> description implies why it shouldn't, but the first sentence\n> probably should state it more clearly.\n> \n> What's the _semantics_ you are trying to achieve?\n> \n> Why does the hook run every time git-bisect suggests the next\n> revision to try?\n\nIts being run since git-bisect calls git-checkout internally, but since\nthe 'git-checkout $branch' could potentially update the working tree it\nmay be desirable to have the hook run.  Since one stated purpose of the\nhook is maintain repository validity or update metadata, running the\nhook at this time may be the right thing to do.\n\n> Why does the hook run when rebase starts its work?\n\nI think this case is actually desirable.  If the rebase changes some\naspects of the working dir that the hook cares about (eg: metadata),\nthen the hook will be able handle the situation correctly.  Not running\nthe hook for a rebase operation could result in the working dir being\nleft in an inconsistent state.\n\n-JE\n"},{"id":"53939","messageId":"7vsl53ap5x.fsf@gitster.siamese.dyndns.org","threadId":"9964","inReplyTo":"1190654052.6078.14.camel@beauty","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-24T18:34:02Z","receivedAt":"2007-09-24T18:34:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Josh England\" <jjengla@sandia.gov> writes:\n\n>> What's the _semantics_ you are trying to achieve?\n>\n> I'd like to get a hook that runs whenever the working dir gets\n> updated.  The 'git-checkout otherbranch path.c' case should\n> run it also, so I view that as a bug.\n\nI think that _is_ INSANE.  Do you run the hook for these then?\n\n\t$ edit path.c\n        $ git-cat-file otherbranch:path.c >path.c\n\nWhy \"git checkout otherbranch path.c\" should be any different?\n"},{"id":"53942","messageId":"1190662396.6078.63.camel@beauty","threadId":"9964","inReplyTo":"7vsl53ap5x.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-24T19:33:16Z","receivedAt":"2007-09-24T19:33:16Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"On Mon, 2007-09-24 at 11:34 -0700, Junio C Hamano wrote:\n> \"Josh England\" <jjengla@sandia.gov> writes:\n> \n> >> What's the _semantics_ you are trying to achieve?\n> >\n> > I'd like to get a hook that runs whenever the working dir gets\n> > updated.  The 'git-checkout otherbranch path.c' case should\n> > run it also, so I view that as a bug.\n> \n> I think that _is_ INSANE.  Do you run the hook for these then?\n> \n> \t$ edit path.c\n>         $ git-cat-file otherbranch:path.c >path.c\n> \n> Why \"git checkout otherbranch path.c\" should be any different?\n\nIt is different because the file is being updated through the 'git\ncheckout' interface.  The user is not copying the file over by hand,\nhe/she is asking git to do it for them via 'git checkout'.  Granted, the\nbranch (and HEAD) does not change for this operation, but that shouldn't\nmatter.  It is somewhat in line with the principle of 'least-surprise':\nif the hook runs for 'git checkout otherbranch', but not 'git checkout\notherbranch path.c', this could cause confusion and distress to the\nuser.  IMO, it is a 'checkout' so the post-checkout hook should run.\nWhy is that so insane?  \n\nLook at it from the perspective of the intended use of this hook.  I'm\ntrying to use this hook to keep working dir metadata (ownership/perms)\nin a consistent state.  When I do a 'git checkout otherbranch', the hook\nruns, updating perms as needed, and all is well.  As is, if I 'git\ncheckout otherbranch path.c', the file is created with the default\numask, the hook is not run, and path.c potentially (likely) has\nincorrect perms.  The working dir is now in an inconsistent state and\nthe worst part is that the next commit will propagate the faulty\nmetadata for that file.\n\n-JE\n"},{"id":"53946","messageId":"7vejgnai1z.fsf@gitster.siamese.dyndns.org","threadId":"9964","inReplyTo":"1190662396.6078.63.camel@beauty","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-24T21:07:36Z","receivedAt":"2007-09-24T21:07:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Josh England\" <jjengla@sandia.gov> writes:\n\n> ...  Granted, the\n> branch (and HEAD) does not change for this operation, but that shouldn't\n> matter.  It is somewhat in line with the principle of 'least-surprise':\n> if the hook runs for 'git checkout otherbranch', but not 'git checkout\n> otherbranch path.c', this could cause confusion and distress to the\n> user.  IMO, it is a 'checkout' so the post-checkout hook should run.\n> Why is that so insane?  \n\nBecause I find it would be surprising if the following commands\nbehave differently:\n\n\t$ git cat-file blob otherbranch:path.c >path.c\n        $ git show otherbranch:path.c >path.c\n        $ git diff -R otherbranch path.c | git apply\n        $ git checkout otherbranch path.c\n\nThese are all talking about various ways to _edit_ working tree\nfiles, and not about switching between revisions.\n\nThat's why I said I found that what the second sentence from\nyour original description implied (\"the hook gets old and new\ncommit object name\" which means we are talking about switching\nbetween revisions) was sensible, but it needs to be stressed a\nbit.\n\nIf you want to spacial case \n\n        $ git checkout otherbranch path.c\n\nit raises another issue.  Which commit should supply the\n\"extended attribute description\" for path.c?  Should it be taken\nfrom the current commit (aka HEAD), otherbranch, or the index?\n"},{"id":"53948","messageId":"1190671558.6078.87.camel@beauty","threadId":"9964","inReplyTo":"7vejgnai1z.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-24T22:05:58Z","receivedAt":"2007-09-24T22:05:58Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"On Mon, 2007-09-24 at 14:07 -0700, Junio C Hamano wrote:\n> \"Josh England\" <jjengla@sandia.gov> writes:\n> \n> > ...  Granted, the\n> > branch (and HEAD) does not change for this operation, but that shouldn't\n> > matter.  It is somewhat in line with the principle of 'least-surprise':\n> > if the hook runs for 'git checkout otherbranch', but not 'git checkout\n> > otherbranch path.c', this could cause confusion and distress to the\n> > user.  IMO, it is a 'checkout' so the post-checkout hook should run.\n> > Why is that so insane?  \n> \n> Because I find it would be surprising if the following commands\n> behave differently:\n> \n> \t$ git cat-file blob otherbranch:path.c >path.c\n>         $ git show otherbranch:path.c >path.c\n>         $ git diff -R otherbranch path.c | git apply\n>         $ git checkout otherbranch path.c\n\nFor all intents and purposes, these would still behave the same.  The\nexistence of a post-checkout hook does not at all affect the outcome of\nthe checkout.  Sure there is potential for someone to do something\nstupid inside the hook script, but that is true of any hook.\n\nMost git users would never even enable the hook, but for those that do I\nwould assume that they'd want the hook to run for all 'git-checkout'\nvariants -- as I do.\n\n> These are all talking about various ways to _edit_ working tree\n> files, and not about switching between revisions.\n> \n> That's why I said I found that what the second sentence from\n> your original description implied (\"the hook gets old and new\n> commit object name\" which means we are talking about switching\n> between revisions) was sensible, but it needs to be stressed a\n> bit.\n> \n> If you want to spacial case \n> \n>         $ git checkout otherbranch path.c\n> \n> it raises another issue.  Which commit should supply the\n> \"extended attribute description\" for path.c?  Should it be taken\n> from the current commit (aka HEAD), otherbranch, or the index?\n\nThis already is a special case and your question is valid but not one\nthat git should necessary care about.  Since extended attributes are not\nbuilt into git the only way to handle them is through hooks.  A such, it\nis up to the hook to worry about these kinds of issues.  The hook I have\nwritten handles this by updating path.c attributes to match whatever\nexists in the (tracked) attributes file of the current HEAD.\n\nThis 'git-checkout otherbranch path.c' is a corner case, but one that\ncan result in broken behavior when handling metadata unless the hook\nruns.  I just want to close all the holes.  I can change the description\nof the hook to try to dispel any confusion if that would help.\n\n-JE\n"},{"id":"53950","messageId":"7vfy138vql.fsf@gitster.siamese.dyndns.org","threadId":"9964","inReplyTo":"1190671558.6078.87.camel@beauty","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-24T23:54:58Z","receivedAt":"2007-09-24T23:54:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Josh England\" <jjengla@sandia.gov> writes:\n\n> On Mon, 2007-09-24 at 14:07 -0700, Junio C Hamano wrote:\n> ...\n>> If you want to spacial case \n>> \n>>         $ git checkout otherbranch path.c\n>> \n>> it raises another issue.  Which commit should supply the\n>> \"extended attribute description\" for path.c?  Should it be taken\n>> from the current commit (aka HEAD), otherbranch, or the index?\n>\n> This already is a special case and your question is valid but not one\n> that git should necessary care about.  Since extended attributes are not\n> built into git the only way to handle them is through hooks.  A such, it\n> is up to the hook to worry about these kinds of issues.\n\nThe fear I have is that that kind of thinking would necessitate\nyour hook to be called after the user edits paths.c in any other\nway not to confuse users.\n\nWhat I am questioning is where we should stop, in order to keep\nthings simpler to explain, and I happen to think that it is far\neasier if we can teach that \"git checkout other path.c\" is\nequivalent to \"git cat-file blob other:path.c >path.c\" followed\nby \"git add path.c\", than saying \"checkout is magical and if you\nhave external hook it can do far more than editing the file\nyourself to arrive at the same contents\".\n\nBut I am obviously not the one who is interested in tracking\nextended attributes attached to git contents, and I do not feel\ntoo strongly about one way or the other.  I am Ok with it if you\nthink \"checkout is magical\" is easier to teach [*1*].\n\nI just wanted to make sure we know what semantics this is\nbringing in, and get it clearly documented.  That's all.\n\n\n[Footnote]\n\n*1* I actually suspect this might be the case. I consider that\nper-path checkout from a commit is just a fancy and handy way to\nedit individual files but that probably comes from knowing how\ngit works too much and I lost my git virginity too long ago.  A\npure \"user\" who types \"git checkout commit path\" may actively\nexpect \"checkout\" command to do something more magical than\nsimply updating the index and the work tree files to a random\nstate that happens to match the state recorded in one commit.\n"},{"id":"53961","messageId":"46F891A4.9070407@op5.se","threadId":"9964","inReplyTo":"7vfy138vql.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2007-09-25T04:42:12Z","receivedAt":"2007-09-25T04:42:12Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Junio C Hamano wrote:\n> \"Josh England\" <jjengla@sandia.gov> writes:\n> \n> But I am obviously not the one who is interested in tracking\n> extended attributes attached to git contents, and I do not feel\n> too strongly about one way or the other.  I am Ok with it if you\n> think \"checkout is magical\" is easier to teach [*1*].\n> \n> [Footnote]\n> \n> *1* I actually suspect this might be the case.\n\nI think so too, if nothing else than for the simple reason than that\nthe hook is called 'post-checkout', so the explanation is likely to\ngo something like 'the checkout program activates it after having\nupdated the worktree'.\n\n\n> I consider that\n> per-path checkout from a commit is just a fancy and handy way to\n> edit individual files but that probably comes from knowing how\n> git works too much and I lost my git virginity too long ago.  A\n> pure \"user\" who types \"git checkout commit path\" may actively\n> expect \"checkout\" command to do something more magical than\n> simply updating the index and the work tree files to a random\n> state that happens to match the state recorded in one commit.\n\nLike, run the post-checkout hook? I should think it wouldn't be\ntoo hard to believe it will.\n\nI imagine the people using this feature will be either git-fanatics\nthat use it for everything and only in their own environment, or\nsysadmins that get a handy tool for managing config in a corporate\nenvironment. I wouldn't be surprised if those sysadmins weren't\nall too keen on learning the 1001 ways there is to create a file\nfrom a special revision in git (and personally I only knew about 2\nof the 4 you listed), so for them there'll most likely *only* be\ngit-checkout to edit the work-tree.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"54017","messageId":"1190738473.6078.102.camel@beauty","threadId":"9964","inReplyTo":"7vfy138vql.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-25T16:41:13Z","receivedAt":"2007-09-25T16:41:13Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"On Mon, 2007-09-24 at 16:54 -0700, Junio C Hamano wrote:\n> \"Josh England\" <jjengla@sandia.gov> writes:\n> \n> > On Mon, 2007-09-24 at 14:07 -0700, Junio C Hamano wrote:\n> > ...\n> >> If you want to spacial case \n> >> \n> >>         $ git checkout otherbranch path.c\n> >> \n> >> it raises another issue.  Which commit should supply the\n> >> \"extended attribute description\" for path.c?  Should it be taken\n> >> from the current commit (aka HEAD), otherbranch, or the index?\n> >\n> > This already is a special case and your question is valid but not one\n> > that git should necessary care about.  Since extended attributes are not\n> > built into git the only way to handle them is through hooks.  A such, it\n> > is up to the hook to worry about these kinds of issues.\n> \n> The fear I have is that that kind of thinking would necessitate\n> your hook to be called after the user edits paths.c in any other\n> way not to confuse users.\n> \n> What I am questioning is where we should stop, in order to keep\n> things simpler to explain, and I happen to think that it is far\n> easier if we can teach that \"git checkout other path.c\" is\n> equivalent to \"git cat-file blob other:path.c >path.c\" followed\n> by \"git add path.c\", than saying \"checkout is magical and if you\n> have external hook it can do far more than editing the file\n> yourself to arrive at the same contents\".\n> \n> But I am obviously not the one who is interested in tracking\n> extended attributes attached to git contents, and I do not feel\n> too strongly about one way or the other.  I am Ok with it if you\n> think \"checkout is magical\" is easier to teach [*1*].\n> \n> I just wanted to make sure we know what semantics this is\n> bringing in, and get it clearly documented.  That's all.\n\nOK.  I'll try to come up with some good wording for the documentation.\n\nSo this leads to my next question:  Should the post-merge patch be\nbrought in under this same umbrella to form a single post-checkout hook,\nor should it stay a separate hook?\n\n-JE\n"},{"id":"54046","messageId":"7v4phi5t98.fsf@gitster.siamese.dyndns.org","threadId":"9964","inReplyTo":"1190738473.6078.102.camel@beauty","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-09-25T21:29:07Z","receivedAt":"2007-09-25T21:29:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Josh England\" <jjengla@sandia.gov> writes:\n\n> So this leads to my next question:  Should the post-merge patch be\n> brought in under this same umbrella to form a single post-checkout hook,\n> or should it stay a separate hook?\n\nI think it is called would be inconvenient for the callee if you\ncall the same hook without telling the hook script why it is\ncalled, so if you go in the unification route the caller of the\nunified hook needs to supply an extra parameter and existing\nhooks if any need to be updated --- neither sounds like a very\nidea.  The writer of the hooks however can choose to call one\nfrom the other if he wants the same action for both hooks, so it\nlooks to me that separate hooks for separate purposes is the way\nto go.\n"},{"id":"54048","messageId":"1190756840.6078.109.camel@beauty","threadId":"9964","inReplyTo":"7v4phi5t98.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-25T21:47:20Z","receivedAt":"2007-09-25T21:47:20Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"On Tue, 2007-09-25 at 14:29 -0700, Junio C Hamano wrote:\n> \"Josh England\" <jjengla@sandia.gov> writes:\n> \n> > So this leads to my next question:  Should the post-merge patch be\n> > brought in under this same umbrella to form a single post-checkout hook,\n> > or should it stay a separate hook?\n> \n> I think it is called would be inconvenient for the callee if you\n> call the same hook without telling the hook script why it is\n> called, so if you go in the unification route the caller of the\n> unified hook needs to supply an extra parameter and existing\n> hooks if any need to be updated --- neither sounds like a very\n> idea.  The writer of the hooks however can choose to call one\n> from the other if he wants the same action for both hooks, so it\n> looks to me that separate hooks for separate purposes is the way\n> to go.\n\nYeah, I agree.  I'll rework post-checkout and send in both again.\n\n-JE\n"},{"id":"54104","messageId":"20070926145229.GA15300@potapov","threadId":"9964","inReplyTo":"7vejgnai1z.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Dmitry Potapov","fromEmail":"deaptor@mail.ru","sentAt":"2007-09-26T14:52:29Z","receivedAt":"2007-09-26T14:52:29Z","isPatch":true,"sender":{"key":"deaptor@mail.ru","avatar":null},"body":"On Mon, Sep 24, 2007 at 02:07:36PM -0700, Junio C Hamano wrote:\n> \"Josh England\" <jjengla@sandia.gov> writes:\n> \n> > ...  Granted, the\n> > branch (and HEAD) does not change for this operation, but that shouldn't\n> > matter.  It is somewhat in line with the principle of 'least-surprise':\n> > if the hook runs for 'git checkout otherbranch', but not 'git checkout\n> > otherbranch path.c', this could cause confusion and distress to the\n> > user.  IMO, it is a 'checkout' so the post-checkout hook should run.\n> > Why is that so insane?  \n> \n> Because I find it would be surprising if the following commands\n> behave differently:\n> \n> \t$ git cat-file blob otherbranch:path.c >path.c\n>         $ git show otherbranch:path.c >path.c\n>         $ git diff -R otherbranch path.c | git apply\n>         $ git checkout otherbranch path.c\n\nActually, they already act differently even without any hook.\nIf path.c is a symbol link then 1 and 2 will give a different\nresult than commands 3 and 4.\n\nOn the other hand, while the difference in above commands\nunderstandable (in case 1 and 2, the shell creates path.c; and\nin 3 and 4, git creates it), I really dislike the idea of \n\"checkout is magical.\" I believe that command 3 and 4 should\nalways give the same result or Git is broken.\n\nAnother reason, why I dislike the post-checkout hook is that it\nis prone to abuse like as not so smart user trying to put some\ncontent modification here. Moreover, it appears to be excessive\nto me, because if you want to run something after git-checkout,\nyou can write a simple shell script for that that first runs\ngit-checkout with the given arguments and then run whatever you\nwant. I don't see why we should modify Git for that.\n\nPerhaps, it would be better to have a hook on modification,\nwhich is invoked every time when Git wants to try to change\nanything in the working directory. The hook could receives on\nthe input something that looks like 'git-diff --name-status'\noutput and can do any work on creation files, etc. It is much\nmore flexible, because you can do additional stuff here like\ncreating one directory in the path as a symbol link somewhere\nelse or something like that. But what is much more important\nis that everything work _consistently_ and you get the same\nresults whether you type:\ngit diff -R otherbranch path.c | git apply\nor\ngit checkout otherbranch path.c\n\nIf you start with one \"magical interface\" then eventually you\nwill end up with everything being so magical that no one can\nmake sense of it. Please, stay consistent.\n\nDmitry Potapov\n"},{"id":"54110","messageId":"1190834633.6078.139.camel@beauty","threadId":"9964","inReplyTo":"20070926145229.GA15300@potapov","subject":"Re: [PATCH] post-checkout hook, and related docs and tests","fromName":"Josh England","fromEmail":"jjengla@sandia.gov","sentAt":"2007-09-26T19:23:53Z","receivedAt":"2007-09-26T19:23:53Z","isPatch":true,"sender":{"key":"jjengla@sandia.gov","avatar":null},"body":"On Wed, 2007-09-26 at 18:52 +0400, Dmitry Potapov wrote:\n> On Mon, Sep 24, 2007 at 02:07:36PM -0700, Junio C Hamano wrote:\n> > \"Josh England\" <jjengla@sandia.gov> writes:\n> > \n> > > ...  Granted, the\n> > > branch (and HEAD) does not change for this operation, but that shouldn't\n> > > matter.  It is somewhat in line with the principle of 'least-surprise':\n> > > if the hook runs for 'git checkout otherbranch', but not 'git checkout\n> > > otherbranch path.c', this could cause confusion and distress to the\n> > > user.  IMO, it is a 'checkout' so the post-checkout hook should run.\n> > > Why is that so insane?  \n> > \n> > Because I find it would be surprising if the following commands\n> > behave differently:\n> > \n> > \t$ git cat-file blob otherbranch:path.c >path.c\n> >         $ git show otherbranch:path.c >path.c\n> >         $ git diff -R otherbranch path.c | git apply\n> >         $ git checkout otherbranch path.c\n> \n> Actually, they already act differently even without any hook.\n> If path.c is a symbol link then 1 and 2 will give a different\n> result than commands 3 and 4.\n\nMoroever, with respect to permissions, the first 2 retain the\npermissions of the file if it already exists in the worktree, whereas\nthe other variations actually recreate the file with a default umask and\nwipe out existing permissions.\n\n> On the other hand, while the difference in above commands\n> understandable (in case 1 and 2, the shell creates path.c; and\n> in 3 and 4, git creates it), I really dislike the idea of \n> \"checkout is magical.\" I believe that command 3 and 4 should\n> always give the same result or Git is broken.\n> \n> Another reason, why I dislike the post-checkout hook is that it\n> is prone to abuse like as not so smart user trying to put some\n> content modification here.\n\nContent modification is not among the intended uses for this hook.  Any\nand all hooks can be abused/misused in this way.  I just want to give\nthe user a tool -- if he wants to hit himself in the face with it that's\nhis prerogative.\n\n>  Moreover, it appears to be excessive\n> to me, because if you want to run something after git-checkout,\n> you can write a simple shell script for that that first runs\n> git-checkout with the given arguments and then run whatever you\n> want. I don't see why we should modify Git for that.\n\nThe same could be said for pre-commit and other hooks.  The whole\nreason for the hook system is to provide a useful interface so that\nusers are *not* required to write their own wrapper scripts to get the\njob done.  In this case, providing the hook is by far the *more*\nconsistent way of doing things.\n\n> Perhaps, it would be better to have a hook on modification,\n> which is invoked every time when Git wants to try to change\n> anything in the working directory. The hook could receives on\n> the input something that looks like 'git-diff --name-status'\n> output and can do any work on creation files, etc. It is much\n> more flexible, because you can do additional stuff here like\n> creating one directory in the path as a symbol link somewhere\n> else or something like that. But what is much more important\n> is that everything work _consistently_ and you get the same\n> results whether you type:\n> git diff -R otherbranch path.c | git apply\n> or\n> git checkout otherbranch path.c\n> \n> If you start with one \"magical interface\" then eventually you\n> will end up with everything being so magical that no one can\n> make sense of it. Please, stay consistent.\n\nI don't know why you think this is so magical.  git-checkout can run a\npost-checkout hook, if enabled.  Plain and simple.  No magic here.  As\nfor the universal 'worktree-updated' hook, I look forward to seeing a\nsane implementation, but in the meantime post-merge and post-checkout\nsuit my needs just fine.\n\n-JE\n"}]}