{"thread":{"id":"23065","subject":"[PATCH] git checkout: create unparented branch by --orphan","startedAt":"2010-03-18T16:09:39Z","lastAt":"2010-03-20T21:37:52Z","messageCount":7,"participants":["Erick Mattos","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"137102","messageId":"1268928579-11660-1-git-send-email-erick.mattos@gmail.com","threadId":"23065","inReplyTo":null,"subject":"[PATCH] git checkout: create unparented branch by --orphan","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-18T16:09:39Z","receivedAt":"2010-03-18T16:09:39Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Similar to -b, --orphan creates a new branch, but it starts without any\ncommit.  After running \"git checkout --orphan newbranch\", you are on a\nnew branch \"newbranch\", and the first commit you create from this state\nwill start a new history without any ancestry.\n\n\"git checkout --orphan\" keeps the index and the working tree files\nintact in order to make it convenient for creating a new history whose\ntrees resemble the ones from the original branch.\n\nWhen creating a branch whose trees have no resemblance to the ones from\nthe original branch, it may be easier to start work on the new branch by\nuntracking and removing all working tree files that came from the\noriginal branch, by running a 'git rm -rf .' immediately after running\n\"checkout --orphan\".\n\nSigned-off-by: Erick Mattos <erick.mattos@gmail.com>\n---\n\nComplete rewrite of --orphan functionality to fit it in the new design goals\nset by Junio.  Now --orphan is not anymore an option of -b.  It is an\nalternative to it.\n\nJunio:  I ask you to reconsider only the giving of the \"short-and-sweet\" -o\nfrom beginning because of the new design.\n\nAs it is now an alternative to -b, doing similar stuff, I think it will be nice\nif they look similar too.  So the it will be [[-b|-o] <new_branch>] not\n[[-b|--orphan] <new_branch>].\n\nPlease ignore it if you can preview future options to checkout that could take\nthe rest of the 21 remaining letters and 6 digits.\n\nRegards\n\n Documentation/git-checkout.txt |   21 +++++++++++++++-\n builtin/checkout.c             |   19 +++++++++++++-\n t/t2017-checkout-orphan.sh     |   53 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 90 insertions(+), 3 deletions(-)\n create mode 100755 t/t2017-checkout-orphan.sh\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 37c1810..18df834 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git checkout' [-q] [-f] [-m] [<branch>]\n-'git checkout' [-q] [-f] [-m] [-b <new_branch>] [<start_point>]\n+'git checkout' [-q] [-f] [-m] [[-b|--orphan] <new_branch>] [<start_point>]\n 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...\n 'git checkout' --patch [<tree-ish>] [--] [<paths>...]\n \n@@ -20,6 +20,19 @@ When <paths> are not given, this command switches branches by\n updating the index, working tree, and HEAD to reflect the specified\n branch.\n \n+When you use \"--orphan\", a new unparented branch is created having the\n+index and the working tree intact.  This allows you to start a new\n+history that records set of paths similar to that of the start-point\n+commit, which is useful when you want to keep different branches for\n+different audiences you are working to like when you have an open source\n+and commercial versions of a software, for example.\n+\n+If you want to start a disconnected history that records set of paths\n+totally different from the original branch, you may want to first clear\n+the index and the working tree, by running \"git rm -rf .\" from the\n+top-level of the working tree, before preparing your files (by copying\n+from elsewhere, extracting a tarball, etc.) in the working tree.\n+\n If `-b` is given, a new branch is created and checked out, as if\n linkgit:git-branch[1] were called; in this case you can\n use the --track or --no-track options, which will be passed to `git\n@@ -63,6 +76,12 @@ entries; instead, unmerged entries are ignored.\n \tWhen checking out paths from the index, check out stage #2\n \t('ours') or #3 ('theirs') for unmerged paths.\n \n+--orphan::\n+\tCreate a new branch named <new_branch>, unparented to any other\n+\tbranch.  The new branch you switch to does not have any commit\n+\tand after the first one it will become the root of a new history\n+\tcompletely unconnected from all the other branches.\n+\n -b::\n \tCreate a new branch named <new_branch> and start it at\n \t<start_point>; see linkgit:git-branch[1] for details.\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex acefaaf..9e0af6a 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -33,6 +33,7 @@ struct checkout_opts {\n \tint writeout_error;\n \n \tconst char *new_branch;\n+\tconst char *new_orphan_branch;\n \tint new_branch_log;\n \tenum branch_track track;\n };\n@@ -491,8 +492,15 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n \tstruct strbuf msg = STRBUF_INIT;\n \tconst char *old_desc;\n \tif (opts->new_branch) {\n-\t\tcreate_branch(old->name, opts->new_branch, new->name, 0,\n-\t\t\t      opts->new_branch_log, opts->track);\n+\t\tif (opts->new_orphan_branch) {\n+\t\t\tunsigned char rev[20];\n+\t\t\tint flag;\n+\t\t\tif (old->path != resolve_ref(\"HEAD\", rev, 0, &flag))\n+\t\t\t\tcmd_checkout(1, &old->name, NULL);\n+\t\t}\n+\t\telse\n+\t\t\tcreate_branch(old->name, opts->new_branch, new->name, 0,\n+\t\t\t\t      opts->new_branch_log, opts->track);\n \t\tnew->name = opts->new_branch;\n \t\tsetup_branch_path(new);\n \t}\n@@ -629,6 +637,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \tstruct option options[] = {\n \t\tOPT__QUIET(&opts.quiet),\n \t\tOPT_STRING('b', NULL, &opts.new_branch, \"new branch\", \"branch\"),\n+\t\tOPT_STRING(0, \"orphan\", &opts.new_orphan_branch, \"new branch\", \"new unparented branch\"),\n \t\tOPT_BOOLEAN('l', NULL, &opts.new_branch_log, \"log for new branch\"),\n \t\tOPT_SET_INT('t', \"track\",  &opts.track, \"track\",\n \t\t\tBRANCH_TRACK_EXPLICIT),\n@@ -677,6 +686,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\topts.new_branch = argv0 + 1;\n \t}\n \n+\tif (opts.new_orphan_branch) {\n+\t\tif (opts.new_branch)\n+\t\t\tdie(\"--orphan and -b are mutually exclusive\");\n+\t\topts.new_branch = opts.new_orphan_branch;\n+\t}\n+\n \tif (conflict_style) {\n \t\topts.merge = 1; /* implied */\n \t\tgit_xmerge_config(\"merge.conflictstyle\", conflict_style, NULL);\ndiff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh\nnew file mode 100755\nindex 0000000..e6d88b1\n--- /dev/null\n+++ b/t/t2017-checkout-orphan.sh\n@@ -0,0 +1,53 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2010 Erick Mattos\n+#\n+\n+test_description='git checkout --orphan\n+\n+Main Tests for --orphan functionality.'\n+\n+. ./test-lib.sh\n+\n+TEST_FILE=foo\n+\n+test_expect_success 'Setup' '\n+\techo \"Initial\" >\"$TEST_FILE\" &&\n+\tgit add \"$TEST_FILE\" &&\n+\tgit commit -m \"First Commit\"\n+\ttest_tick &&\n+\techo \"State 1\" >>\"$TEST_FILE\" &&\n+\tgit add \"$TEST_FILE\" &&\n+\tgit commit -m \"Second Commit\"\n+'\n+\n+test_expect_success '--orphan creates a new orphan branch from HEAD' '\n+\tgit checkout --orphan alpha &&\n+\ttest_must_fail PAGER= git log >/dev/null 2>/dev/null &&\n+\ttest \"alpha\" = \"$(git symbolic-ref HEAD | sed \"s,.*/,,\")\" &&\n+\ttest_tick &&\n+\tgit commit -m \"Third Commit\" &&\n+\ttest 0 -eq $(git cat-file -p HEAD | grep \"^parent\" | wc -l) &&\n+\tgit cat-file -p master | grep \"^tree\" >base &&\n+\tgit cat-file -p HEAD | grep \"^tree\" >actual &&\n+\ttest_cmp base actual\n+'\n+\n+test_expect_success '--orphan creates a new orphan branch from <start_point>' '\n+\tgit checkout master &&\n+\tgit checkout --orphan beta master^ &&\n+\ttest_must_fail PAGER= git log >/dev/null 2>/dev/null &&\n+\ttest \"beta\" = \"$(git symbolic-ref HEAD | sed \"s,.*/,,\")\" &&\n+\ttest_tick &&\n+\tgit commit -m \"Fourth Commit\" &&\n+\ttest 0 -eq $(git cat-file -p HEAD | grep \"^parent\" | wc -l) &&\n+\tgit cat-file -p master^ | grep \"^tree\" >base &&\n+\tgit cat-file -p HEAD | grep \"^tree\" >actual &&\n+\ttest_cmp base actual\n+'\n+\n+test_expect_success '--orphan must be rejected with -b' '\n+\ttest_must_fail git checkout --orphan new -b newer\n+'\n+\n+test_done\n-- \n1.7.0.2.280.g460a6\n"},{"id":"137336","messageId":"7vvdcrowlc.fsf@alter.siamese.dyndns.org","threadId":"23065","inReplyTo":"1268928579-11660-1-git-send-email-erick.mattos@gmail.com","subject":"Re: [PATCH] git checkout: create unparented branch by --orphan","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-20T15:13:03Z","receivedAt":"2010-03-20T15:13:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erick Mattos <erick.mattos@gmail.com> writes:\n\n> Complete rewrite of --orphan functionality to fit it in the new design goals\n> set by Junio.  Now --orphan is not anymore an option of -b.  It is an\n> alternative to it.\n\nYou are giving me too much credit.  I just made a suggestion, you had the\nchoice to agree to or disagree with it, and I am hoping that you made the\nfinal decision to rewrite the patch to match what I suggested not because\nyou wanted a \"commit count\" in the project with any form of a change, but\nbecause you thought the suggested approach made much more sense than the\nearlier iterations.  And in that case, the final decision to submit the\npatch in this form was due to _you_.  Don't give me undue credit---I was\njust helping from the sideline.\n\n> Junio:  I ask you to reconsider only the giving of the \"short-and-sweet\" -o\n> from beginning because of the new design.\n\nNo.  I don't want our hand to be tied with something that is clearly a\ncorner case feature from the beginning.  It wouldn't be too late to add\none later, after it proves something people do every day (or even every\nhour).\n\n>  Documentation/git-checkout.txt |   21 +++++++++++++++-\n>  builtin/checkout.c             |   19 +++++++++++++-\n>  t/t2017-checkout-orphan.sh     |   53 ++++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 90 insertions(+), 3 deletions(-)\n>  create mode 100755 t/t2017-checkout-orphan.sh\n>\n> diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\n> index 37c1810..18df834 100644\n> --- a/Documentation/git-checkout.txt\n> +++ b/Documentation/git-checkout.txt\n> @@ -20,6 +20,19 @@ When <paths> are not given, this command switches branches by\n>  updating the index, working tree, and HEAD to reflect the specified\n>  branch.\n>  \n> +When you use \"--orphan\", a new unparented branch is created having the\n> +index and the working tree intact.  This allows you to start a new\n> +history that records set of paths similar to that of the start-point\n> +commit, which is useful when you want to keep different branches for\n> +different audiences you are working to like when you have an open source\n> +and commercial versions of a software, for example.\n> +\n> +If you want to start a disconnected history that records set of paths\n> +totally different from the original branch, you may want to first clear\n> +the index and the working tree, by running \"git rm -rf .\" from the\n> +top-level of the working tree, before preparing your files (by copying\n> +from elsewhere, extracting a tarball, etc.) in the working tree.\n> +\n>  If `-b` is given, a new branch is created and checked out, as if\n>  linkgit:git-branch[1] were called; in this case you can\n>  use the --track or --no-track options, which will be passed to `git\n\nIt feels wrong to talk about --orphan before readers learned -b.  Does the\ntext flow nicely if we just swap the paragraphs?  Better yet, perhaps we\nshouldn't have any of this in the general description section.  Move this\nand consolidate it with the text in \"OPTIONS\" section under \"--orphan\"?\n\n> @@ -63,6 +76,12 @@ entries; instead, unmerged entries are ignored.\n>  \tWhen checking out paths from the index, check out stage #2\n>  \t('ours') or #3 ('theirs') for unmerged paths.\n>  \n> +--orphan::\n> +\tCreate a new branch named <new_branch>, unparented to any other\n> +\tbranch.  The new branch you switch to does not have any commit\n> +\tand after the first one it will become the root of a new history\n> +\tcompletely unconnected from all the other branches.\n> +\n>  -b::\n>  \tCreate a new branch named <new_branch> and start it at\n>  \t<start_point>; see linkgit:git-branch[1] for details.\n\nLikewise.  I think \"--orphan\" should come after -b/-t/-l (all about the\nnormal cases of switching to a different branch either new or existing).\n\nOh, by the way, how does this new option work with -t?  I think the\ncombination should be rejected, no?\n\n> @@ -491,8 +492,15 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n>  \tstruct strbuf msg = STRBUF_INIT;\n>  \tconst char *old_desc;\n>  \tif (opts->new_branch) {\n> -\t\tcreate_branch(old->name, opts->new_branch, new->name, 0,\n> -\t\t\t      opts->new_branch_log, opts->track);\n> +\t\tif (opts->new_orphan_branch) {\n> +\t\t\tunsigned char rev[20];\n> +\t\t\tint flag;\n> +\t\t\tif (old->path != resolve_ref(\"HEAD\", rev, 0, &flag))\n> +\t\t\t\tcmd_checkout(1, &old->name, NULL);\n\nCan you explain what this is doing?\n\n - the \"if\" compares the addresses of two strings; did you mean it?\n\n - It is like recursively calling main() which is rather unusual and error\n   prone;\n\n - what happens when cmd_checkout() fails, perhaps due to local changes?\n\nI have a suspicion that you are trying \"git co-o new old\" case where old\nis not the current branch (so that you would want to adjust the index and\nthe working tree files to that of \"old\" while carrying local changes\nforward), _but_ if that is the case that should have been already done\nwith the logic in switch_branches() where it calls merge_working_tree(),\nand not here in the call chain.\n\n> @@ -677,6 +686,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n>  \t\topts.new_branch = argv0 + 1;\n>  \t}\n>  \n> +\tif (opts.new_orphan_branch) {\n> +\t\tif (opts.new_branch)\n> +\t\t\tdie(\"--orphan and -b are mutually exclusive\");\n> +\t\topts.new_branch = opts.new_orphan_branch;\n> +\t}\n\nHow should this interact with opts.track?  I think (and please correct\nme if you disagree):\n\n - \"git checkout -t --orphan new [old]\" should fail; new is rootless and\n   does not track either the current branch or \"old\";\n\n - opts.track that came from git_branch_track (default read from config)\n   should not cause a failure, but be silently ignored.\n\n> diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh\n> new file mode 100755\n> index 0000000..e6d88b1\n> --- /dev/null\n> +++ b/t/t2017-checkout-orphan.sh\n> @@ -0,0 +1,53 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2010 Erick Mattos\n> +#\n> +\n> +test_description='git checkout --orphan\n> +\n> +Main Tests for --orphan functionality.'\n> +\n> +. ./test-lib.sh\n> +\n> +TEST_FILE=foo\n> +\n> +test_expect_success 'Setup' '\n> +\techo \"Initial\" >\"$TEST_FILE\" &&\n> +\tgit add \"$TEST_FILE\" &&\n> +\tgit commit -m \"First Commit\"\n> +\ttest_tick &&\n> +\techo \"State 1\" >>\"$TEST_FILE\" &&\n> +\tgit add \"$TEST_FILE\" &&\n> +\tgit commit -m \"Second Commit\"\n\nNo tick before this one?\n\n> +'\n> +\n> +test_expect_success '--orphan creates a new orphan branch from HEAD' '\n> +\tgit checkout --orphan alpha &&\n> +\ttest_must_fail PAGER= git log >/dev/null 2>/dev/null &&\n> +\ttest \"alpha\" = \"$(git symbolic-ref HEAD | sed \"s,.*/,,\")\" &&\n\nWhat is this PAGER= doing here?\n\nI think it is more direct to check that:\n\n - \"rev-parse --verify HEAD\" fails; and\n - \"symbolic-ref HEAD\" says refs/heads/alpha.\n\n> +\ttest_tick &&\n> +\tgit commit -m \"Third Commit\" &&\n\nTricky but correct ;-)\n\n> +\ttest 0 -eq $(git cat-file -p HEAD | grep \"^parent\" | wc -l) &&\n\n    test_must_fail git rev-parse --verify HEAD^\n\n> +\tgit cat-file -p master | grep \"^tree\" >base &&\n\n    git rev-parse master^{tree} >base\n\n> +\tgit cat-file -p HEAD | grep \"^tree\" >actual &&\n> +\ttest_cmp base actual\n> +'\n\nOr you can just replace the above three lines with:\n\n\tgit diff-tree --quiet master alpha\n\n> +test_expect_success '--orphan creates a new orphan branch from <start_point>' '\n> ...\n> +'\n\nSimilar.\n\n> +test_expect_success '--orphan must be rejected with -b' '\n> +\ttest_must_fail git checkout --orphan new -b newer\n> +'\n\nOk.  You have the basics covered well; there are a few more things to\ntest, I think.\n\nWith local changes in the index/working tree without \"start commit\" (which\nshould never fail) and with \"start commit\" (which should fail if HEAD and\nstart commit has differences to the same paths as you have local changes\nto).\n\nAlso you would want to check with -t, --no-t, branch.autosetupmrebe set to\nalways in the configuration with -t and without -t from the command line,\n\nThanks.\n"},{"id":"137363","messageId":"55bacdd31003201206w6215c6a4qec09797fbe060725@mail.gmail.com","threadId":"23065","inReplyTo":"7vvdcrowlc.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] git checkout: create unparented branch by --orphan","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-20T19:06:56Z","receivedAt":"2010-03-20T19:06:56Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Hi,\n\n2010/3/20 Junio C Hamano <gitster@pobox.com>:\n> Erick Mattos <erick.mattos@gmail.com> writes:\n>\n>> Complete rewrite of --orphan functionality to fit it in the new design goals\n>> set by Junio.  Now --orphan is not anymore an option of -b.  It is an\n>> alternative to it.\n>\n> You are giving me too much credit.  I just made a suggestion, you had the\n> choice to agree to or disagree with it, and I am hoping that you made the\n> final decision to rewrite the patch to match what I suggested not because\n> you wanted a \"commit count\" in the project with any form of a change, but\n> because you thought the suggested approach made much more sense than the\n> earlier iterations.  And in that case, the final decision to submit the\n> patch in this form was due to _you_.  Don't give me undue credit---I was\n> just helping from the sideline.\n\nIf I was going to look for a commit count I would do spelling/grammar\ncorrections. :-)\n\nThis is the second feature I am trying to add to git.  Both changes of\nmine are features I use my own.  On my compiled and customized version\nof git.  I thought they were good and tried to share following the\nbest free software spirit (I have been always feeling guilty of just\nusing free software).  I am not a new developer trying to be known.  I\nam not even \"new\"...  :-)\n\nAnyway I think you will not hear of me anymore after we finish this\nwork.  I think I did enough for this project and I really don't feel\nmyself fitted to the task.\n\nI realized your last critic was indeed good and that it worthed the changes.\n\nBut I have to confess that I am a little impatient to end this\ndevelopment cycle though.  So trying not to argue was a change of\nbehavior. ;-)\n\n>> Junio:  I ask you to reconsider only the giving of the \"short-and-sweet\" -o\n>> from beginning because of the new design.\n>\n> No.  I don't want our hand to be tied with something that is clearly a\n> corner case feature from the beginning.  It wouldn't be too late to add\n> one later, after it proves something people do every day (or even every\n> hour).\n\nIf it is because of its importance I think it will never deserve the upgrade.\n\nBut I was arguing because I imagine checkout will never need the 21\nremaining letters and that it was good for cosmetic and similarity (to\nhis brother -b) reasons.\n\nAlso because I am more used to one letter options from previous\noperational systems experience (let's forget that! :-) ).\n\n>>  Documentation/git-checkout.txt |   21 +++++++++++++++-\n>>  builtin/checkout.c             |   19 +++++++++++++-\n>>  t/t2017-checkout-orphan.sh     |   53 ++++++++++++++++++++++++++++++++++++++++\n>>  3 files changed, 90 insertions(+), 3 deletions(-)\n>>  create mode 100755 t/t2017-checkout-orphan.sh\n>>\n>> diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\n>> index 37c1810..18df834 100644\n>> --- a/Documentation/git-checkout.txt\n>> +++ b/Documentation/git-checkout.txt\n>> @@ -20,6 +20,19 @@ When <paths> are not given, this command switches branches by\n>>  updating the index, working tree, and HEAD to reflect the specified\n>>  branch.\n>>\n>> +When you use \"--orphan\", a new unparented branch is created having the\n>> +index and the working tree intact.  This allows you to start a new\n>> +history that records set of paths similar to that of the start-point\n>> +commit, which is useful when you want to keep different branches for\n>> +different audiences you are working to like when you have an open source\n>> +and commercial versions of a software, for example.\n>> +\n>> +If you want to start a disconnected history that records set of paths\n>> +totally different from the original branch, you may want to first clear\n>> +the index and the working tree, by running \"git rm -rf .\" from the\n>> +top-level of the working tree, before preparing your files (by copying\n>> +from elsewhere, extracting a tarball, etc.) in the working tree.\n>> +\n>>  If `-b` is given, a new branch is created and checked out, as if\n>>  linkgit:git-branch[1] were called; in this case you can\n>>  use the --track or --no-track options, which will be passed to `git\n>\n> It feels wrong to talk about --orphan before readers learned -b.  Does the\n> text flow nicely if we just swap the paragraphs?  Better yet, perhaps we\n> shouldn't have any of this in the general description section.  Move this\n> and consolidate it with the text in \"OPTIONS\" section under \"--orphan\"?\n\nAs you wish.\n\n>> @@ -63,6 +76,12 @@ entries; instead, unmerged entries are ignored.\n>>       When checking out paths from the index, check out stage #2\n>>       ('ours') or #3 ('theirs') for unmerged paths.\n>>\n>> +--orphan::\n>> +     Create a new branch named <new_branch>, unparented to any other\n>> +     branch.  The new branch you switch to does not have any commit\n>> +     and after the first one it will become the root of a new history\n>> +     completely unconnected from all the other branches.\n>> +\n>>  -b::\n>>       Create a new branch named <new_branch> and start it at\n>>       <start_point>; see linkgit:git-branch[1] for details.\n>\n> Likewise.  I think \"--orphan\" should come after -b/-t/-l (all about the\n> normal cases of switching to a different branch either new or existing).\n\nAll right.\n\n> Oh, by the way, how does this new option work with -t?  I think the\n> combination should be rejected, no?\n\nYes it should.  And it is.  By --track itself which is directly\nconnected to -b.  Test done just before --orphan test by someone else.\n\n> I have a suspicion that you are trying \"git co-o new old\" case where old\n> is not the current branch (so that you would want to adjust the index and\n> the working tree files to that of \"old\" while carrying local changes\n> forward), _but_ if that is the case that should have been already done\n> with the logic in switch_branches() where it calls merge_working_tree(),\n> and not here in the call chain.\n\nMy fault.  Forget that.  Fast unverified work in a hurry. :-\\\n\n>> @@ -677,6 +686,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n>>               opts.new_branch = argv0 + 1;\n>>       }\n>>\n>> +     if (opts.new_orphan_branch) {\n>> +             if (opts.new_branch)\n>> +                     die(\"--orphan and -b are mutually exclusive\");\n>> +             opts.new_branch = opts.new_orphan_branch;\n>> +     }\n>\n> How should this interact with opts.track?  I think (and please correct\n> me if you disagree):\n>\n>  - \"git checkout -t --orphan new [old]\" should fail; new is rootless and\n>   does not track either the current branch or \"old\";\n>\n>  - opts.track that came from git_branch_track (default read from config)\n>   should not cause a failure, but be silently ignored.\n\nIt is just working like you have pictured.\n\n>> diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh\n>> new file mode 100755\n>> index 0000000..e6d88b1\n>> --- /dev/null\n>> +++ b/t/t2017-checkout-orphan.sh\n>> @@ -0,0 +1,53 @@\n>> +#!/bin/sh\n>> +#\n>> +# Copyright (c) 2010 Erick Mattos\n>> +#\n>> +\n>> +test_description='git checkout --orphan\n>> +\n>> +Main Tests for --orphan functionality.'\n>> +\n>> +. ./test-lib.sh\n>> +\n>> +TEST_FILE=foo\n>> +\n>> +test_expect_success 'Setup' '\n>> +     echo \"Initial\" >\"$TEST_FILE\" &&\n>> +     git add \"$TEST_FILE\" &&\n>> +     git commit -m \"First Commit\"\n>> +     test_tick &&\n>> +     echo \"State 1\" >>\"$TEST_FILE\" &&\n>> +     git add \"$TEST_FILE\" &&\n>> +     git commit -m \"Second Commit\"\n>\n> No tick before this one?\n\nI will add another then.\n\n>> +'\n>> +\n>> +test_expect_success '--orphan creates a new orphan branch from HEAD' '\n>> +     git checkout --orphan alpha &&\n>> +     test_must_fail PAGER= git log >/dev/null 2>/dev/null &&\n>> +     test \"alpha\" = \"$(git symbolic-ref HEAD | sed \"s,.*/,,\")\" &&\n>\n> What is this PAGER= doing here?\n>\n> I think it is more direct to check that:\n>\n>  - \"rev-parse --verify HEAD\" fails; and\n>  - \"symbolic-ref HEAD\" says refs/heads/alpha.\n>> +     test_tick &&\n>> +     git commit -m \"Third Commit\" &&\n>\n> Tricky but correct ;-)\n\nIndeed.  Easier your way though.\n\n>> +     test 0 -eq $(git cat-file -p HEAD | grep \"^parent\" | wc -l) &&\n>\n>    test_must_fail git rev-parse --verify HEAD^\n>\n>> +     git cat-file -p master | grep \"^tree\" >base &&\n>\n>    git rev-parse master^{tree} >base\n>\n>> +     git cat-file -p HEAD | grep \"^tree\" >actual &&\n>> +     test_cmp base actual\n>> +'\n>\n> Or you can just replace the above three lines with:\n>\n>        git diff-tree --quiet master alpha\n>\n>> +test_expect_success '--orphan creates a new orphan branch from <start_point>' '\n>> ...\n>> +'\n>\n> Similar.\n>\n>> +test_expect_success '--orphan must be rejected with -b' '\n>> +     test_must_fail git checkout --orphan new -b newer\n>> +'\n\nAll your suggestions are going to be added.\n\n> Ok.  You have the basics covered well; there are a few more things to\n> test, I think.\n>\n> With local changes in the index/working tree without \"start commit\" (which\n> should never fail) and with \"start commit\" (which should fail if HEAD and\n> start commit has differences to the same paths as you have local changes\n> to).\n\nIt is behaving like that already and that is intrinsically a\nswitch_branches() logic, not a special --orphan need.  It is not part\nof this implementation and It is probably tested elsewhere (you\nprobably do know where).\n\n> Also you would want to check with -t, --no-t, branch.autosetupmrebe set to\n> always in the configuration with -t and without -t from the command line,\n\nThe actual implementation is just ignoring track and -t is not even\nallowed.  So it is pointless.\n\n> Thanks.\n>\n\nI will be sending a new patch version soon.\n\nRegards\n"},{"id":"137366","messageId":"7v4okad9by.fsf@alter.siamese.dyndns.org","threadId":"23065","inReplyTo":"55bacdd31003201206w6215c6a4qec09797fbe060725@mail.gmail.com","subject":"Re: [PATCH] git checkout: create unparented branch by --orphan","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-20T20:30:57Z","receivedAt":"2010-03-20T20:30:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erick Mattos <erick.mattos@gmail.com> writes:\n\n>> With local changes in the index/working tree without \"start commit\" (which\n>> should never fail) and with \"start commit\" (which should fail if HEAD and\n>> start commit has differences to the same paths as you have local changes\n>> to).\n>\n> It is behaving like that already and that is intrinsically a\n> switch_branches() logic, not a special --orphan need.  It is not part\n> of this implementation and It is probably tested elsewhere (you\n> probably do know where).\n>\n>> Also you would want to check with -t, --no-t, branch.autosetupmrebe set to\n>> always in the configuration with -t and without -t from the command line,\n>\n> The actual implementation is just ignoring track and -t is not even\n> allowed.  So it is pointless.\n\nI think you misunderstood the point of having tests.  It is not about\ndemonstrating that you did a good job implementing the new feature, or\nyour implementation works as advertised in the submitted form.  That is\nthe job of the review process before patch acceptance.\n\nTests are to pretect what you perfected during the patch acceptance review\nfrom getting broken by other people in the future, while you are not\nclosely monitoring the mailing list traffic.  Many people, me included,\ntend to concentrate on their own new addition, without being careful\nenough not to break the existing features.  If \"-t --orphan\" should result\nin an error, it should result in an error even after somebody restructures\nthe code, so it is not sufficient that it is obvious in the _current_ code\nstructure that breakage of that feature is unlikely.\n\nIf you can promise that you will be around on this list forever, and that\nevery time somebody posts patches to the related areas, you will make sure\nthat the changes do not inadvertently break this feature and respond to\nthe patches that do break it before they hit my tree, then theoretically\nwe do not need to have any test to make sure this feature keeps working as\nadvertised.  But we cannot ask that kind of time/attention commitment from\nanybody.\n"},{"id":"137369","messageId":"55bacdd31003201336u685f4b91u5206ca719609d153@mail.gmail.com","threadId":"23065","inReplyTo":"7v4okad9by.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] git checkout: create unparented branch by --orphan","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-20T20:36:06Z","receivedAt":"2010-03-20T20:36:06Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"2010/3/20 Junio C Hamano <gitster@pobox.com>:\n> Erick Mattos <erick.mattos@gmail.com> writes:\n>\n>>> With local changes in the index/working tree without \"start commit\" (which\n>>> should never fail) and with \"start commit\" (which should fail if HEAD and\n>>> start commit has differences to the same paths as you have local changes\n>>> to).\n>>\n>> It is behaving like that already and that is intrinsically a\n>> switch_branches() logic, not a special --orphan need.  It is not part\n>> of this implementation and It is probably tested elsewhere (you\n>> probably do know where).\n>>\n>>> Also you would want to check with -t, --no-t, branch.autosetupmrebe set to\n>>> always in the configuration with -t and without -t from the command line,\n>>\n>> The actual implementation is just ignoring track and -t is not even\n>> allowed.  So it is pointless.\n>\n> I think you misunderstood the point of having tests.  It is not about\n> demonstrating that you did a good job implementing the new feature, or\n> your implementation works as advertised in the submitted form.  That is\n> the job of the review process before patch acceptance.\n>\n> Tests are to pretect what you perfected during the patch acceptance review\n> from getting broken by other people in the future, while you are not\n> closely monitoring the mailing list traffic.  Many people, me included,\n> tend to concentrate on their own new addition, without being careful\n> enough not to break the existing features.  If \"-t --orphan\" should result\n> in an error, it should result in an error even after somebody restructures\n> the code, so it is not sufficient that it is obvious in the _current_ code\n> structure that breakage of that feature is unlikely.\n>\n> If you can promise that you will be around on this list forever, and that\n> every time somebody posts patches to the related areas, you will make sure\n> that the changes do not inadvertently break this feature and respond to\n> the patches that do break it before they hit my tree, then theoretically\n> we do not need to have any test to make sure this feature keeps working as\n> advertised.  But we cannot ask that kind of time/attention commitment from\n> anybody.\n>\n\nAll right then.  I am going to check it too.  But in this particular\ncase, the track is being ignored completely.  So to break this\nbehavior people will need to add code to --orphan.\n\nThat's not a break, it's a linkage!  :-)\n"},{"id":"137370","messageId":"7vfx3ubto9.fsf@alter.siamese.dyndns.org","threadId":"23065","inReplyTo":"55bacdd31003201336u685f4b91u5206ca719609d153@mail.gmail.com","subject":"Re: [PATCH] git checkout: create unparented branch by --orphan","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-20T20:54:30Z","receivedAt":"2010-03-20T20:54:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I hope I am not giving you undue burden, but here is what I would add.\nOne thing that I am not sure about is what to do with \"-l --orhpan\".\n\n---\n\n t/t2017-checkout-orphan.sh |   43 ++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 42 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh\nindex 5a9a3fa..e80e167 100755\n--- a/t/t2017-checkout-orphan.sh\n+++ b/t/t2017-checkout-orphan.sh\n@@ -44,7 +44,48 @@ test_expect_success '--orphan creates a new orphan branch from <start_point>' '\n '\n \n test_expect_success '--orphan must be rejected with -b' '\n-\ttest_must_fail git checkout --orphan new -b newer\n+\tgit checkout master &&\n+\ttest_must_fail git checkout --orphan new -b newer &&\n+\ttest refs/heads/master = \"$(git symbolic-ref HEAD)\"\n+'\n+\n+test_expect_success '--orphan is rejected with an existing name' '\n+\tgit checkout master &&\n+\ttest_must_fail git checkout --orphan master &&\n+\ttest refs/heads/master = \"$(git symbolic-ref HEAD)\"\n+'\n+\n+test_expect_success '--orhapn refuses to switch if a merge is needed' '\n+\tgit checkout master &&\n+\tgit reset --hard &&\n+\techo local >>\"$TEST_FILE\" &&\n+\tcat \"$TEST_FILE\" >\"$TEST_FILE.saved\" &&\n+\ttest_must_fail git checkout --orphan gamma master^ &&\n+\ttest refs/heads/master = \"$(git symbolic-ref HEAD)\" &&\n+\ttest_cmp \"$TEST_FILE\" \"$TEST_FILE.saved\" &&\n+\tgit diff-index --quiet --cached HEAD &&\n+\tgit reset --hard\n+'\n+\n+test_expect_success '--orphan does not mix well with -t' '\n+\tgit checkout master &&\n+\ttest_must_fail git checkout -t master --orphan gamma &&\n+\ttest refs/heads/master = \"$(git symbolic-ref HEAD)\"\n+'\n+\n+test_expect_success '--orphan ignores branch.autosetupmerge' '\n+\tgit checkout -f master &&\n+\tgit config branch.autosetupmerge always &&\n+\tgit checkout --orphan delta &&\n+\ttest -z \"$(git config branch.delta.merge)\" &&\n+\ttest refs/heads/delta = \"$(git symbolic-ref HEAD)\" &&\n+\ttest_must_fail git rev-parse --verify HEAD^\n+'\n+\n+# This is iffy.\n+test_expect_success '--orphan does not mix well with -l' '\n+\tgit checkout -f master &&\n+\ttest_must_fail git checkout -l --orphan gamma\n '\n \n test_done\n"},{"id":"137378","messageId":"55bacdd31003201437x2b3fcd58j4c631468be63b1e4@mail.gmail.com","threadId":"23065","inReplyTo":"7vfx3ubto9.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] git checkout: create unparented branch by --orphan","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-20T21:37:52Z","receivedAt":"2010-03-20T21:37:52Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"2010/3/20 Junio C Hamano <gitster@pobox.com>:\n> I hope I am not giving you undue burden, but here is what I would add.\n> One thing that I am not sure about is what to do with \"-l --orhpan\".\n\nNo problem.  I also like to do things right.  And you have made it\nlight with your attached tests.\n\nAbout -l well... you tell.\n"}]}