{"thread":{"id":"22971","subject":"[PATCH v2] git checkout -b: unparent the new branch with -o","startedAt":"2010-03-09T22:28:33Z","lastAt":"2010-04-27T06:35:51Z","messageCount":17,"participants":["Erick Mattos","Junio C Hamano","Bert Wesarg","Jakub Narebski","David Kågedal"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"136472","messageId":"1268173713-5224-1-git-send-email-erick.mattos@gmail.com","threadId":"22971","inReplyTo":null,"subject":"[PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-09T22:28:33Z","receivedAt":"2010-03-09T22:28:33Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Sometimes it is necessary to start up a new development branch of code\nintended to be merged in the near future to existing branches but which\nactually does not relate to them.\n\nThe new -o/--orphan is intended to solve this situation allowing the\ncreation of a new branch unparented to any other.\n\nAfter the 'checkout -o -b' the new branch is not saved until some files are\nadded to the index and committed, exactly as if it was an initial commit.\nA 'git clean -df' would delete everything from the work tree making it\nempty for new files.\n\nSigned-off-by: Erick Mattos <erick.mattos@gmail.com>\n---\n\nChanged the text in SYNOPSIS to correct it as noticed by Jakub Narebski.\n\nRegards\n\n Documentation/git-checkout.txt |   10 ++++++++\n builtin-checkout.c             |   14 +++++++++-\n t/t2017-checkout-orphan.sh     |   50 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 72 insertions(+), 2 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..c13ab62 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -9,6 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git checkout' [-q] [-f] [-m] [<branch>]\n+'git checkout' [-q] [-f] [-m] [-b <new_branch> [-o]]\n 'git checkout' [-q] [-f] [-m] [-b <new_branch>] [<start_point>]\n 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...\n 'git checkout' --patch [<tree-ish>] [--] [<paths>...]\n@@ -25,6 +26,10 @@ 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 branch`.  As a convenience, --track without `-b` implies branch\n creation; see the description of --track below.\n+When using -b, it is possible to use the option -o to set the new branch\n+as unparented thus unrelated to the previous branch.  The new code will\n+be committed by using 'git add' and 'git commit' as if it was an initial\n+commit.\n \n When <paths> or --patch are given, this command does *not* switch\n branches.  It updates the named paths in the working tree from\n@@ -86,6 +91,11 @@ explicitly give a name with '-b' in such a case.\n \tDo not set up \"upstream\" configuration, even if the\n \tbranch.autosetupmerge configuration variable is true.\n \n+-o::\n+--orphan::\n+\tWhen creating a new branch, set it up as unparented thus\n+\tunrelated to the previous branch.\n+\n -l::\n \tCreate the new branch's reflog; see linkgit:git-branch[1] for\n \tdetails.\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex c5ab783..4882613 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -34,6 +34,7 @@ struct checkout_opts {\n \n \tconst char *new_branch;\n \tint new_branch_log;\n+\tint new_branch_orphan;\n \tenum branch_track track;\n };\n \n@@ -509,8 +510,13 @@ 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_branch_orphan) {\n+\t\t\tdiscard_cache();\n+\t\t\tremove_path(get_index_file());\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@@ -647,6 +653,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_BOOLEAN('o', \"orphan\", &opts.new_branch_orphan, \"make the new branch unparented\"),\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@@ -695,6 +702,9 @@ 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_branch_orphan && !opts.new_branch)\n+\t\tdie(\"-o is used only with -b\");\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..7170641\n--- /dev/null\n+++ b/t/t2017-checkout-orphan.sh\n@@ -0,0 +1,50 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2010 Erick Mattos\n+#\n+\n+test_description='git checkout -b\n+\n+Tests for -o 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+'\n+\n+test_expect_success '-b without -o checkout into a new clone branch' '\n+\ttest_tick &&\n+\techo \"Test 1\" >> \"$TEST_FILE\" &&\n+\tgit add \"$TEST_FILE\" &&\n+\tgit commit -m \"Second Commit\" &&\n+\tgit log --pretty=oneline > base &&\n+\tgit checkout -b alpha &&\n+\ttest \"alpha\" = \"$(git branch | sed -n \"/*/s/\\* //p\")\" &&\n+\tgit log --pretty=oneline > actual &&\n+\ttest_cmp base actual\n+'\n+\n+test_expect_success '-b with -o checkout into an orphan branch' '\n+\tgit checkout -ob beta &&\n+\ttest -z \"$(git branch | grep \\*)\" &&\n+\ttest \"beta\" = \"$(git symbolic-ref HEAD | sed \"s,.*/,,\")\" &&\n+\ttest -z \"$(git ls-files)\" &&\n+\ttest_tick &&\n+\techo \"Test 2\" >> \"$TEST_FILE\" &&\n+\tgit add \"$TEST_FILE\" &&\n+\tgit commit -m \"Third Commit\" &&\n+\tgit log --pretty=oneline > actual &&\n+\ttest 1 -eq $(wc -l actual | sed \"s/ .*//\") &&\n+\t! test_cmp base actual\n+'\n+\n+test_expect_success '-o must be rejected without -b' '\n+\ttest_must_fail git checkout -o alpha\n+'\n+\n+test_done\n-- \n1.7.0.99.ge963b.dirty\n"},{"id":"136646","messageId":"7vr5nqrpyg.fsf@alter.siamese.dyndns.org","threadId":"22971","inReplyTo":"1268173713-5224-1-git-send-email-erick.mattos@gmail.com","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-12T06:53:11Z","receivedAt":"2010-03-12T06:53:11Z","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> @@ -25,6 +26,10 @@ 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>  branch`.  As a convenience, --track without `-b` implies branch\n>  creation; see the description of --track below.\n> +When using -b, it is possible to use the option -o to set the new branch\n> +as unparented thus unrelated to the previous branch.  The new code will\n> +be committed by using 'git add' and 'git commit' as if it was an initial\n> +commit.\n\nThis says what the option does, but it is hard to guess why it would be a\ngood thing to do in the first place from the above description.\n\nThe use case in your commit log message wasn't convincing either.  If such\na new branch will be merged later, especially if the trees of the commits\nin newly rooted history resemble the trees in the original history (I am\nguessing that is the intended use case, as you do not seem to be removing\nanything from the working tree---how is the user expected to use them by\nthe way?), not having a common merge base will make the merge harder, not\neasier, and later examination of the history (think \"bisect\") also\nharder.\n\nThis looks like a \"because we can\" feeping creaturism, without any\n\"because it is beneficial if users can do this for this reason\"\njustification.\n\nAnd what it can do \"because we can\" doesn't look very useful, safe, nor\nsane either, with this particular implementation.\n\n> @@ -509,8 +510,13 @@ 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_branch_orphan) {\n> +\t\t\tdiscard_cache();\n> +\t\t\tremove_path(get_index_file());\n\nI don't think we want to see \"remove_path()\" here.  The function is about\nthe files in the work tree, and not about the files under .git/.\nCurrently the codepath to create and write out the index is abstracted\nlike this:\n\n    fd = hold_locked_index();\n    ... populate the_index structure ...\n    write_cache(fd);\n    commit_locked_index();\n\nand by only changing the implementation of these three functions, we could\nstore the index somewhere other than on the filesystem (say, database or\nmemcache).  By using remove_path() on the return value of get_index_file()\nin a random codepath like this one, you are pre-seeding a bug for other\npeople who may ant to make changes like that in the future.\n\nBut the above is just an advice on the coding, assuming that what is being\ncoded is sane, which unfortunately is not.  You are nuking the index but\nwithout doing anything to the working tree files.  Why?  The user manually\nhas to remove them?  Or re-add them?  I don't think you would want to call\ndiscard_cache() _nor_ remove the index file here.  This is probably even\nmore so if you think about a case where the user is using a sparse\ncheckout.  Some random set of files are still in the working tree but\nother files aren't, and the index used to keep track of which is what, but\nyou lost that information by discarding the cache.\n\nIf you are going to leave the files in the working tree intact, you should\nmake it the user's responsibility to run \"git rm -f\" after \"checkout -o\",\nif the user wants to start from an empty index.  That would also make it\nsafer; a mistaken \"checkout -o\" would be easier to recover from by running\nreset without --hard, if it does not touch the index.\n\nBy the way, the worst part of this patch is that I didn't see any safety\nchecks tested in the test script.  What prevents the users from typing an\nextra -o by mistake, while having some changes to the index and/or the\nfiles in the working tree?  Even if you change it not to touch the index,\nit would probably make sense to make sure this \"feature\" is a lot harder\nto invoke by mistake.  In a sane workflow you wouldn't be creating root\ncommits left and right.  Perhaps by not giving it a '-o' shorthand would\nbe a good start.\n\nIn the above I assumed (by guessing from the fact that you are not\ntouching files in the working tree) that the tree eventually committed by\nthe user on this newly rooted history would have some resemblance to the\ntrees in the original history.  But if -o is intended to be used for\nreally \"starting from void\" with an empty tree, then I think the option\nshould instead do this:\n\n - run an equivalent of \"git rm .\", which includes:\n\n  - make sure no change is in the index relative to HEAD; otherwise error\n    out.\n\n  - make sure no change is in the working tree relative to the index;\n    otherwise error out.\n\n - discard_cache() and write that empty index out;\n\n - make the HEAD dangling like you did.\n\nThat would be safe and halfway useful _if_ somebody wants to start a truly\nnew history from scratch, even though if you want to have an unrelated\nhistory in your repository it would be more natural do so by fetching such\nan unrelated history from an unrelated repository.\n\nThe way the patch implements is not suited for neither \"starting from\nvoid\" case, nor \"continuing the tree but with disjoint history\" case, I\nthink.\n\n> diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh\n> new file mode 100755\n> index 0000000..7170641\n> --- /dev/null\n> +++ b/t/t2017-checkout-orphan.sh\n> @@ -0,0 +1,50 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2010 Erick Mattos\n> +#\n> +\n> +test_description='git checkout -b\n> +\n> +Tests for -o functionality.'\n> +\n> +. ./test-lib.sh\n> +\n> +TEST_FILE=foo\n> +\n> +test_expect_success 'Setup' '\n> +\techo \"initial\" > \"$TEST_FILE\" &&\n\nThis is just style, but I find it easier to read if you have one SP before\nredirect and no SP between redirect and the filename, i.e.:\n\n\techo initial >\"$TEST_FILE\" &&\n\n> +\ttest \"alpha\" = \"$(git branch | sed -n \"/*/s/\\* //p\")\" &&\n\nDon't read from \"git branch\" in scripts; use symbolic-ref on HEAD.\n"},{"id":"136654","messageId":"36ca99e91003112340u6256ef4dwb40e308c9a5e3a46@mail.gmail.com","threadId":"22971","inReplyTo":"7vr5nqrpyg.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Bert Wesarg","fromEmail":"bert.wesarg@googlemail.com","sentAt":"2010-03-12T07:40:07Z","receivedAt":"2010-03-12T07:40:07Z","isPatch":true,"sender":{"key":"bert.wesarg@googlemail.com","avatar":"https://avatars.githubusercontent.com/u/111934?v=4"},"body":"On Fri, Mar 12, 2010 at 07:53, Junio C Hamano <gitster@pobox.com> wrote:\n> Erick Mattos <erick.mattos@gmail.com> writes:\n>> +     test \"alpha\" = \"$(git branch | sed -n \"/*/s/\\* //p\")\" &&\n>\n> Don't read from \"git branch\" in scripts; use symbolic-ref on HEAD.\n\nI think what he wants is:\n\n        git rev-parse --abbrev-ref HEAD\n\nBert\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n>\n"},{"id":"136663","messageId":"55bacdd31003120845kc980d16s1e6006d56d6f923a@mail.gmail.com","threadId":"22971","inReplyTo":"7vr5nqrpyg.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-12T16:45:17Z","receivedAt":"2010-03-12T16:45:17Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Hi,\n\nThanks for answering.\nI had to write a little in reply so I beg for you patience to read it.\n\nThis is a new option and before we start talking about the\nimplementation we should agree about its usefulness and the subjects\naddressed by it.\n\nThis is something that probably you haven't needed so I understand\nyour resistance.  In a intense merging software development work flow\nit would be quite rare to have a merge of an unrelated branch.\n\nBut not all of the software developments happen under this work flow.\nThere is a lot of very small projects.  Being developed by a few\npeople or even by one person.  And those softwares count too.  They\ncould become very important for everyone some day.\n\nFor those it is very common to:\n\n* Do some parallel development.\n* Working under unrelated parts before merging the start point of the\nnew software.\n* Recreate history.  It is not published yet so it is not being widely\ncloned and people just\n  want to have a good repository before publishing;\n* Adding files which is not meant to be part of anything in a temporary fashion;\n* Have different approaches starting different sources from those\nsoftware versions until you\n  find out the best one.\n\nGit is becoming much more used than it was planned to be.  It is even\nbeing used nowadays for other exotic jobs like regular file\nversioning.\n\nThose needs are nothing new.  If you query Google for \"new empty\nbranch git\" you will find that people have been querying it for.\n\nThere are a lot of ways to have the unrelated branch: you could start\na new repository and import from it; you could foresee that you will\nneed something like that and start all development with an empty\ncommit, ...\n\nBut the proposed solution is the best approach.  And it is the one I\nuse when needed.\n\nThis new option is not a new solution.  Just a direct implementation\nso people will not need to know this hack.  See it:\n\nGit SCM Wiki:\nhttp://git.wiki.kernel.org/index.php/GitTips#How_to_create_a_new_branch_that_has_no_ancestor\n\nGit Book:\nhttp://book.git-scm.com/5_creating_new_empty_branches.html\n\nAfter all said let's face the implementation.\n\n2010/3/12 Junio C Hamano <gitster@pobox.com>\n>\n> Erick Mattos <erick.mattos@gmail.com> writes:\n>\n> > @@ -25,6 +26,10 @@ 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> >  branch`.  As a convenience, --track without `-b` implies branch\n> >  creation; see the description of --track below.\n> > +When using -b, it is possible to use the option -o to set the new branch\n> > +as unparented thus unrelated to the previous branch.  The new code will\n> > +be committed by using 'git add' and 'git commit' as if it was an initial\n> > +commit.\n>\n> This says what the option does, but it is hard to guess why it would be a\n> good thing to do in the first place from the above description.\n\nSo you would like to have some examples on it?\nI was trying to let people know how to use it not why to use it.\n\n> The use case in your commit log message wasn't convincing either.  If such\n> a new branch will be merged later, especially if the trees of the commits\n> in newly rooted history resemble the trees in the original history (I am\n> guessing that is the intended use case, as you do not seem to be removing\n> anything from the working tree---how is the user expected to use them by\n> the way?), not having a common merge base will make the merge harder, not\n> easier, and later examination of the history (think \"bisect\") also\n> harder.\n\nAre you talking about the commit log message of the previous version\npatch?  If that is the case I replied to your message explaining it\nbetter (but not trying to convince you).\n\nI am not wiping the tree by default because I am not deciding for\npeople if they are going to use anything from it as a template (even\nthe directory structure only).\n\nI am not trying to make decisions for the user.  I think he would be\ncapable of deciding it himself.  That is my way of thinking so I\nnormally prefer to advice, alert, inform not to impose.\n\nWe should remember git users are normally programers not some wind... lamers.\n\nThe intended uses of this option was explained up there.\n\nAs it is a new fresh development branch it is not normally expected to\nhave anything in common with original branch so the future merge is\ngoing to be very easy.  Anything exotic is up to the user to solve.\n\n> This looks like a \"because we can\" feeping creaturism, without any\n> \"because it is beneficial if users can do this for this reason\"\n> justification.\n>\n> And what it can do \"because we can\" doesn't look very useful, safe, nor\n> sane either, with this particular implementation.\n\nBenefits explained up there already.\n\nIt is not creaturism.  People need this option at various levels.\n\n> > @@ -509,8 +510,13 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n> >       struct strbuf msg = STRBUF_INIT;\n> >       const char *old_desc;\n> >       if (opts->new_branch) {\n> > -             create_branch(old->name, opts->new_branch, new->name, 0,\n> > -                           opts->new_branch_log, opts->track);\n> > +             if (opts->new_branch_orphan) {\n> > +                     discard_cache();\n> > +                     remove_path(get_index_file());\n>\n> I don't think we want to see \"remove_path()\" here.  The function is about\n> the files in the work tree, and not about the files under .git/.\n> Currently the codepath to create and write out the index is abstracted\n> like this:\n>\n>    fd = hold_locked_index();\n>    ... populate the_index structure ...\n>    write_cache(fd);\n>    commit_locked_index();\n>\n> and by only changing the implementation of these three functions, we could\n> store the index somewhere other than on the filesystem (say, database or\n> memcache).  By using remove_path() on the return value of get_index_file()\n> in a random codepath like this one, you are pre-seeding a bug for other\n> people who may ant to make changes like that in the future.\n\nI see your point but what we will be doing is just wiping the index\nout.  So I did it in a direct fashion.\n\nPlease let me know after you read this whole reply if you still\nconsider this way as inadequate.\n\n> But the above is just an advice on the coding, assuming that what is being\n> coded is sane, which unfortunately is not.  You are nuking the index but\n> without doing anything to the working tree files.  Why?  The user manually\n> has to remove them?  Or re-add them?  I don't think you would want to call\n> discard_cache() _nor_ remove the index file here.  This is probably even\n> more so if you think about a case where the user is using a sparse\n> checkout.  Some random set of files are still in the working tree but\n> other files aren't, and the index used to keep track of which is what, but\n> you lost that information by discarding the cache.\n\nI have already replied that but let me state it: we will be leting\npeople start an unrelated branch, unrelated work, fresh new stuff.\nAnd leting them do anything they want with the files in the work tree.\n Deleting them as easy as 'git clean -df'.\n\n>\n> If you are going to leave the files in the working tree intact, you should\n> make it the user's responsibility to run \"git rm -f\" after \"checkout -o\",\n> if the user wants to start from an empty index.  That would also make it\n> safer; a mistaken \"checkout -o\" would be easier to recover from by running\n> reset without --hard, if it does not touch the index.\n\nIt is already very safe and easy to recover by just doing a 'git\ncheckout PREVIOUS_BRANCH'.\n\n>\n> By the way, the worst part of this patch is that I didn't see any safety\n> checks tested in the test script.  What prevents the users from typing an\n> extra -o by mistake, while having some changes to the index and/or the\n> files in the working tree?  Even if you change it not to touch the index,\n> it would probably make sense to make sure this \"feature\" is a lot harder\n> to invoke by mistake.  In a sane workflow you wouldn't be creating root\n> commits left and right.  Perhaps by not giving it a '-o' shorthand would\n> be a good start.\n\nI don't quite see your point here.  Not letting people use it when\nthey don't want to use it?!\n\nLike protecting him from typing a letter 'o' at keyboard when creating\na branch with -b and pressing enter after this mistake?!\n\nI really have not get it.  Could you please explain it from what we\nhave to protect him?\n\n>\n> In the above I assumed (by guessing from the fact that you are not\n> touching files in the working tree) that the tree eventually committed by\n> the user on this newly rooted history would have some resemblance to the\n> trees in the original history.  But if -o is intended to be used for\n> really \"starting from void\" with an empty tree, then I think the option\n> should instead do this:\n\nThe user could probably use something from the work tree as template\nso I am not making assuptions.  Just leting him know that with a 'git\nclean -df'  everything would be vanished.\n\n>\n> This is just style, but I find it easier to read if you have one SP before\n> redirect and no SP between redirect and the filename, i.e.:\n>\n>        echo initial >\"$TEST_FILE\" &&\n\nYou are the one that must demand the style so I am going to change it.\n\n>\n> > +     test \"alpha\" = \"$(git branch | sed -n \"/*/s/\\* //p\")\" &&\n>\n> Don't read from \"git branch\" in scripts; use symbolic-ref on HEAD.\n\nAll right then.\n\nThanks for you patience to read this email and I hope this effort will\nworth something.\n\nRegards\n"},{"id":"136712","messageId":"7v8w9whd3g.fsf@alter.siamese.dyndns.org","threadId":"22971","inReplyTo":"55bacdd31003120845kc980d16s1e6006d56d6f923a@mail.gmail.com","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-13T07:53:23Z","receivedAt":"2010-03-13T07:53:23Z","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>> The use case in your commit log message wasn't convincing either. If such\n>> a new branch will be merged later, especially if the trees of the commits\n>> in newly rooted history resemble the trees in the original history (I am\n>> guessing that is the intended use case, as you do not seem to be removing\n>> anything from the working tree---how is the user expected to use them by\n>> the way?), not having a common merge base will make the merge harder, not\n>> easier, and later examination of the history (think \"bisect\") also\n>> harder.\n>\n> Are you talking about the commit log message of the previous version\n> patch?\n\nI was referring to this from the latest version:\n\n    Sometimes it is necessary to start up a new development branch of code\n    intended to be merged in the near future to existing branches but which\n    actually does not relate to them.\n\nLet's give you an example of the depth of thought and clarity of\ndescription of the workflow I am expecting from anybody who claims \"this\nis a useful feature to help _some_ workflows\" by taking an example from\ngit.git, because it is one project that both of us are familiar with and\nthere is a readily available example in it.  It has disjoint merges from\ngitk, gitweb and git-gui.  The history up to such a merge 5569bf9 (Do a\ncross-project merge of Paul Mackerras' gitk visualizer, 2005-06-22) looks\nlike this:\n\n A---o---?---o---o---X---* linus\n          .             /\n           B---o---o---Y gitk\n\nNote that with this merge '*', two histories merged did not share any\npaths at commit X and Y.\n\nDid you have this kind of \"no common paths\" merge in mind when you wrote\nthe proposed commit log message?  IOW, if we pretend that Paul started his\ngitk work and he \"intended to be merged to Linus's branch but which does\nnot relate to it\", would that be a good example of what you are trying to\nachieve?\n\n    Side note: The other two \"disjoint\" merges we have are also this kind\n    of \"no common paths\" merge.  Nobody who was involved in the branches\n    that resulted in them prepared his branch with --orphan, by the way.\n    They started out in independent repositories, because they were by\n    definition independent projects and these were \"cross project merges\",\n    as Linus put it.\n\nI'd grant you that we could say that these histories did not start in the\nsame repository using \"checkout --orphan\" because it was not available.\nBut in that case, it would have been nicer if Paul didn't have to remove\nfiles came from Linus's branch, left by your \"checkout --orphan\", by hand.\n\"rm -rf\" would not have been very useful, especially if he had some\nuntracked files that he never intended to commit to git project but did\nnot want to lose (think of \"Notes\" \"memo\" \"todo\" files you would keep in\nthe source tree).  The most natural way to keep these untracked files\nwhile removing now-unneeded tracked files in the Linus's git when he\nswitched from using \"checkout --orphan\" would have been to use something\nlike \"ls-files -z | xargs -0 rm -f\".  But you are nuking the index without\nremoving the tracked files, so that becomes impossible.\n\nOn the other hand, Paul could have started his gitk branch from a copy of\ngit Linus had published.  Even though gitk was developed with an intention\nto run with any version of git available that was installed idependently\non the system, it did depend on git and it would have made equal amount of\nsense if he shipped with a matching version of git, saying \"this version\nof gitk was tested with this git\".  If that were the case, paths at commit\nX and Y would have been overlapping.  In fact, gitk has been a single-file\nproject for a long time, so most of the paths were the same and Y would\nhad one file more than X.\n\nDid you have this kind of \"mostly common paths\" merge in mind when you\nwrote the proposed commit log message?  IOW, if \"checkout --orphan\" were\navailable to Paul, would you have recommended him to use it, add his gitk\nscript to the tree, and start his history at commit B which he started\nfrom commit '?' from Linus's history?  But you are again nuking the index\nso Paul would have had to add the files back with \"git add\", while being\ncareful not to add untracked files, or run \"git read-tree ?\" to populate\nthe index back to the original state.\n\n> I am not wiping the tree by default because I am not deciding for\n> people if they are going to use anything from it as a template (even\n> the directory structure only).\n>\n> I am not trying to make decisions for the user.  I think he would be\n> capable of deciding it himself.  That is my way of thinking so I\n> normally prefer to advice, alert, inform not to impose.\n\nYou may think that you are supporting both, but in reality, you are\nsupporting neither by making both cases equally inconvenient.  The only\nthing you are gaining is a way to weasel out of issues experienced by the\nusers by saying \"I didn't remove anything from the working tree, so if you\nwant to add them, you can, it is up to you\", while ignoring the issue that\n(1) if the user wants \"no common paths\", cleaning working tree becomes\ncumbersome and error prone, and (2) if the user wants \"mostly common\npaths\", adding back to the index becomes cumbersome and error prone.\n\nAs I already said, I do not think \"mostly common paths\" case should be\nencouraged to begin with.  As far as I know (and you can guess by now that\nI know reasonably well about git), you do not gain anything by not having\nthe ancestry link between '?' and 'B', except that it would make conflict\nresolution at '*' extremely difficult.  There is only downside without any\nupside in \"mostly common paths\" disjoint merge.\n\nThat leaves only the \"almost no common paths\" case.  As we have already\nseen in git project, the end result is indeed very useful.  It used to be\nthat people had to download and use gitk independently before Linus's\ncross project merge, but after the merge, the project gives the core git\nand gitk comes with it.  So you could argue that \"checkout --orphan\" would\nbecome useful if you adjusted the code like I suggested in my review\ncomments (run an equivalent of \"git rm\" without \"-f\" from the top-level\nand make the HEAD dangling to the new branch, only if the \"git rm\" step\nsucceeds), and document clearly that is the intended workflow for the new\nfeature to support.\n\nBut stepping back a bit, you would realize that the usefulness of the end\nresult of these existing \"disjoint merges\" does not come from the fact\nthat the side branch was initially a disjoint history from the main\nbranch.  The usefulness of the end result comes solely from the fact that\nwe managed to merge such a side branch.  If Paul started gitk by forking\nLinus's git, adding gitk script, _without_ making the history disjoint,\nthe result of the merge would have been equally useful.\n\nThe only reason the early part of gitk's history is independent from git\nis because Paul nor Linus did _not_ have any plan to merge these two\nhistories.  Lack of foresight is not a crime, so it is perfectly fine if\nyou have to merge histories that started separately, but if you do plan to\nmerge the future, starting the branch as a disjoint history is a crime--it\ndoes not help anybody.\n\nUp to this point, I:\n\n - described possible two workflows (\"almost no common paths\" and \"mostly\n   common paths\") that \"checkout --orphan\" _could_ support;\n\n - explained why neither makes sene; and\n\n - explained why your implementation does not support either one well,\n   even if one or both of these workflows made sense.\n\nNow, do not take the above as a personal criticism.  The only thing the\nabove discussion may be showing could be that your description was not\nclear enough to tell me that the workflow you had in mind to support was a\nthird one, different from the above two, and that your implementation may\nsupport that untold workflow very well.  Take the above as an illustration\nof how you present the workflow your new feature intends to support, and\nhow you choose your design and implementation to support that workflow\nwell.\n\nSo let's hear it.  Until we clear the design issues, there is not much\npoint in talking about coding styles and implementation.\n"},{"id":"136715","messageId":"7v4okkegdy.fsf@alter.siamese.dyndns.org","threadId":"22971","inReplyTo":"7v8w9whd3g.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-13T09:10:33Z","receivedAt":"2010-03-13T09:10:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> As I already said, I do not think \"mostly common paths\" case should be\n> encouraged to begin with.  As far as I know (and you can guess by now that\n> I know reasonably well about git), you do not gain anything by not having\n> the ancestry link between '?' and 'B', except that it would make conflict\n> resolution at '*' extremely difficult.  There is only downside without any\n> upside in \"mostly common paths\" disjoint merge.\n\nThere is one case \"mostly common paths\" disjoint history can be useful.\n\nImagine you have a hitherto proprietary software project and want to go\nopen source.  Perhaps your intention is to have an open source version and\nan enhanced commercial version.  The project contains some third-party\nvendor software outside your control, and you have replaced them with open\nsource equivalents or disabled features that depend on them.\n\nYour history may look like this:\n\n      o---o---A oss-base\n     /\n ---o---o---o---o master\n\nwhere master is the primary version you will continue shipping to your\npaying customers, with proprietary third-party components and features\nthat depend on them.  Commits on oss-base were your work to prepare the\ntree into a releasable shape, removing these proprietary stuff along with\nsome features.\n\nBut you cannot publish oss-base (commit A) to the public.  \"git log\" will\nshow all the history that leads to it, with all the third-party stuff you\ndo not have license to distribute in the source form.  The older parts of\nthe history may even have site password at customer installation you have\ncommitted by mistake and eradicated long time ago.\n\nIf you run this three command sequence (in this message, I am assuming\nthat you keep the index and the working tree files intact in an updated\nimplementation of --orphan, which is different from the suggestion to\nsupport \"no common paths\" case I mentioned in the previous message):\n\n    $ git checkout --orphan oss oss-base\n    $ git checkout oss-base\n    $ git merge -s ours oss\n\nyou will get a history of this shape:\n\n                X oss\n                 \\\n      o---o---A---B oss-base\n     /\n ---o---o---o---o master\n\nwith commits X, A and B all recording an identical tree.  The oss branch\n(commit X) is now safe to publish.\n\nOnce you have done this, further you can:\n\n    $ git checkout master\n    $ git merge oss-base\n\nwhich gives you a history of this shape:\n\n                X oss\n                 \\\n      o---o---A---B oss-base\n     /             \\\n ---o---o---o---o---Y master\n\nThis merge Y has to be done carefully.  It inherently has to be an evil\nmerge because oss-base wants to replace some proprietary stuff with open\nsource counterparts while you may want to keep using the proprietary ones\nyou have support contract for in your paying customer release you will\nmake from the master branch.  So at Y, you will most likely be reverting\nsome work you did on oss-base branch since it forked from master.\n\nAfter setting it up, this arrangement allows you to:\n\n - accept changes from public, and/or build changes for public, to advance\n   \"community version\" on the oss branch on top of X;\n\n - from time to time, merge oss to oss-base;\n\n - from time to time, merge oss-base to master.\n\nand the histories will continue like this:\n\n                X---C---C---C---C oss\n                 \\           \\\n      o---o---A---B-----------* oss-base\n     /             \\           \\ \n ---o---o---o---o---Y---P---P---*---P---P master\n\nwith community commits C (either contributed from the public or you\ndeveloped yourself and gave to the community) on oss branch, with\nproprietary commits P that record your own proprietary work on master\nbranch.  Note that oss-base branch is not used to produce nor record any\ncommit on its own---it is merely to ease the merging from oss and master\nby providing X-B link to serve as a convenient common ancestor to make\nlater merges easier.\n\nNote also that it would be the most convenient if you kept both the index\nand the working tree intact, if \"checkout --orphan\" is to be used as an\ningredient for this workflow.  It _might_ actually make sense not to make\nthe \"git checkout --orphan\" an independent feature that can be randomly\nabused or misused, but package the three-command sequence to create the\nA-B-X open triangle above into a separate command, i.e.\n\n    $ git branch --orphan oss\n\nwould create a new branch \"oss\" with its own root commit X that records\nthe same tree as the current HEAD A, and immediately merge X back into A\nto produce B, again recording the same tree, and advance the current HEAD\nto point at B, like so:\n\n                                             X oss\n                                              \\\n    ---o---A HEAD       -->         ---o---A---B HEAD\n"},{"id":"136716","messageId":"m38w9wlg7i.fsf@localhost.localdomain","threadId":"22971","inReplyTo":"7v8w9whd3g.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-03-13T09:33:19Z","receivedAt":"2010-03-13T09:33:19Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>     Side note: The other two \"disjoint\" merges we have are also this kind\n>     of \"no common paths\" merge.  Nobody who was involved in the branches\n>     that resulted in them prepared his branch with --orphan, by the way.\n>     They started out in independent repositories, because they were by\n>     definition independent projects and these were \"cross project merges\",\n>     as Linus put it.\n\nNote that beside \"disjoint\" merges (\"cross project merges\"), of gitk,\ngit-gui, gitweb and (very early in git history) git mail tools, there\nare also three \"disjoint\"/\"unparented\" branches: 'html', 'man' and\n'todo'.\n\nWhile 'todo' is totally unrelated, and if instead of starting in\nseparate repository it would be created using proposed feature, it\nwould be created with \"no common paths\" case.\n\nBUT in the case of 'html' and 'man' branches I could see why current\nimplementation of _removing index and not removing files_ might be\nadvantageous.  Remove index, create HTML and manpage version of\ndocumentation, and add HTML (in 'html' branch) or manpages (in 'man'\nbranch)... probably shifting root, so it is not all in single\nDocumentation directory.\n\nJust my 2 eurocents.\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"136717","messageId":"7vaaucd0ch.fsf@alter.siamese.dyndns.org","threadId":"22971","inReplyTo":"m38w9wlg7i.fsf@localhost.localdomain","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-13T09:42:22Z","receivedAt":"2010-03-13T09:42:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> BUT in the case of 'html' and 'man' branches I could see why current\n> implementation of _removing index and not removing files_ might be\n> advantageous.  Remove index, create HTML and manpage version of\n> documentation, and add HTML (in 'html' branch) or manpages (in 'man'\n> branch)... probably shifting root, so it is not all in single\n> Documentation directory.\n\nWhen you have some spare time, I'd recommend you to read dodoc.sh script\nin the 'todo' branch.  These preformatted documentation branches are\ncoming from their own repositories, very much on purpose.\n\n> Just my 2 eurocents.\n\nAlready?\n"},{"id":"136776","messageId":"55bacdd31003141346t408c276ak507b7c289cf17679@mail.gmail.com","threadId":"22971","inReplyTo":"7v8w9whd3g.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-14T20:46:35Z","receivedAt":"2010-03-14T20:46:35Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Hi,\n\nSorry for writing much again in reply.\n\n2010/3/13 Junio C Hamano <gitster@pobox.com>:\n> I was referring to this from the latest version:\n>\n>    Sometimes it is necessary to start up a new development branch of code\n>    intended to be merged in the near future to existing branches but which\n>    actually does not relate to them.\n\nThat is one from some reasons to start a new empty, unparented,\nunrelated, without ancestry branch.  An example which is not\nconsidered good enough by your opinion.\n\nI am not trying because I don't feel myself good enough to convince\nyou of anything.  But I will try to give you more examples at the end\nof this reply.\n\nTo be more general the text could be:\n\nSometimes it is interesting to start an new unparented branch for new code.\n\n> Let's give you an example of the depth of thought and clarity of\n> description of the workflow I am expecting from anybody who claims \"this\n> is a useful feature to help _some_ workflows\" by taking an example from\n> git.git, because it is one project that both of us are familiar with and\n> there is a readily available example in it.  It has disjoint merges from\n> gitk, gitweb and git-gui.  The history up to such a merge 5569bf9 (Do a\n> cross-project merge of Paul Mackerras' gitk visualizer, 2005-06-22) looks\n> like this:\n>\n>  A---o---?---o---o---X---* linus\n>          .             /\n>           B---o---o---Y gitk\n>\n> Note that with this merge '*', two histories merged did not share any\n> paths at commit X and Y.\n>\n> Did you have this kind of \"no common paths\" merge in mind when you wrote\n> the proposed commit log message?  IOW, if we pretend that Paul started his\n> gitk work and he \"intended to be merged to Linus's branch but which does\n> not relate to it\", would that be a good example of what you are trying to\n> achieve?\n\nI am not trying to achieve anything.  I am already doing what I want\nmyself.  I am just trying to let people achieve what they want without\na hack.\n\nI think you haven't checked those, so PLEASE:\n\nGit SCM Wiki:\nhttp://git.wiki.kernel.org/index.php/GitTips#How_to_create_a_new_branch_that_has_no_ancestor\n\nGit Book:\nhttp://book.git-scm.com/5_creating_new_empty_branches.html\n\nAnyway your example is a good one if you are the one which controls\nthe branch flows and know you will be doing the merge eventually.  It\nfits then on my explained case.\n\n>    Side note: The other two \"disjoint\" merges we have are also this kind\n>    of \"no common paths\" merge.  Nobody who was involved in the branches\n>    that resulted in them prepared his branch with --orphan, by the way.\n>    They started out in independent repositories, because they were by\n>    definition independent projects and these were \"cross project merges\",\n>    as Linus put it.\n\nThey were not foreseeing the future but and if they were the only\ndeveloper and could project what they would need?\n\n> I'd grant you that we could say that these histories did not start in the\n> same repository using \"checkout --orphan\" because it was not available.\n\nThat's it!\n\n> Did you have this kind of \"mostly common paths\" merge in mind when you\n> wrote the proposed commit log message?  IOW, if \"checkout --orphan\" were\n> available to Paul, would you have recommended him to use it, add his gitk\n> script to the tree, and start his history at commit B which he started\n> from commit '?' from Linus's history?  But you are again nuking the index\n> so Paul would have had to add the files back with \"git add\", while being\n> careful not to add untracked files, or run \"git read-tree ?\" to populate\n> the index back to the original state.\n\nHe would use it easily.  No difficulty at all.\n\nI think the problem here is a matter of opinion: you think removal\nshould be automatically followed.  Like 'git checkout -ob NEW_BRANCH'\nfollowed by 'git clean -df'.\n\nI don't.  I think the user can do it or not by himself.\n\nI am not trying to convince you.  You rule.\n\n>> I am not wiping the tree by default because I am not deciding for\n>> people if they are going to use anything from it as a template (even\n>> the directory structure only).\n>>\n>> I am not trying to make decisions for the user.  I think he would be\n>> capable of deciding it himself.  That is my way of thinking so I\n>> normally prefer to advice, alert, inform not to impose.\n>\n> You may think that you are supporting both, but in reality, you are\n> supporting neither by making both cases equally inconvenient.  The only\n> thing you are gaining is a way to weasel out of issues experienced by the\n> users by saying \"I didn't remove anything from the working tree, so if you\n> want to add them, you can, it is up to you\", while ignoring the issue that\n> (1) if the user wants \"no common paths\", cleaning working tree becomes\n> cumbersome and error prone, and (2) if the user wants \"mostly common\n> paths\", adding back to the index becomes cumbersome and error prone.\n\nReally?\n(1) git clean -df\n(2) git add WHATEVER\n\nIt does not look cumbersome or error prone to me. :-1\n\n> As I already said, I do not think \"mostly common paths\" case should be\n> encouraged to begin with.  As far as I know (and you can guess by now that\n> I know reasonably well about git), you do not gain anything by not having\n> the ancestry link between '?' and 'B', except that it would make conflict\n> resolution at '*' extremely difficult.  There is only downside without any\n> upside in \"mostly common paths\" disjoint merge.\n\nI do not have to guess: you are the man.  I know you know everything about git.\n\nFirst of all, I do respect you a lot.  Not only by all your knowledge,\nor your commitment, or by Git's creator confidence upon you.\n\nBut more than all because of the hard work you have been giving to\nthis project.  Time and effort are very rare commodities to be wasted\nthese days.\n\nThe problem here is not what you know.  It is not about you.  It is\nabout what Git should become to ease user's life. It is to pay\nattention to common as well as to uncommon needs.\n\nThe first reason for Git was to be the Linux kernel SCM.  That was\nalready achieved perfectly.\nGit should freeze then?\n\nBeing good is not a reason for not becoming better.  I am trying to\nmake it better by filling a gap.  I have started my contributions by\nfilling needs I had which were not fulfilled.\n\nWe are not encouraging anything.  We are just letting people do what\nthey want to.  Having an empty new branch to start with is something\nsome people want to do.  Please do the google search I told you\nbefore: \"new empty branch git\".\n\nAnd finally, remember, merge will be easy because unparented branch is\nmainly for unrelated work.  User will solve problems if he wants any\nexotic stuff.\n\n> That leaves only the \"almost no common paths\" case.  As we have already\n> seen in git project, the end result is indeed very useful.  It used to be\n> that people had to download and use gitk independently before Linus's\n> cross project merge, but after the merge, the project gives the core git\n> and gitk comes with it.  So you could argue that \"checkout --orphan\" would\n> become useful if you adjusted the code like I suggested in my review\n> comments (run an equivalent of \"git rm\" without \"-f\" from the top-level\n> and make the HEAD dangling to the new branch, only if the \"git rm\" step\n> succeeds), and document clearly that is the intended workflow for the new\n> feature to support.\n\nThe end result will be very helpful indeed.\n\nYou are thinking as a maintainer of a huge project with a lot of\nmerging.  This new function is indeed not very useful to you.  But it\nis to people running different work flows.  Most of all when they are\nrunning small projects and when they have full control of the\nrepository without a lot of clones widespread.\n\n> Now, do not take the above as a personal criticism.  The only thing the\n> above discussion may be showing could be that your description was not\n> clear enough to tell me that the workflow you had in mind to support was a\n> third one, different from the above two, and that your implementation may\n> support that untold workflow very well.  Take the above as an illustration\n> of how you present the workflow your new feature intends to support, and\n> how you choose your design and implementation to support that workflow\n> well.\n\nI am not taking anything personally.  I already know your way of working.\n\nBut I have descripted what I wanted to.  When I showed the\ndebianization case to picture it, that was something I did.  Even\nthough you don't think is a good way to do it.\n\nThis new function satisfies a lot of needs because an empty new branch\nis needed some times and the way to get it nowadays is too unnatural.\n\nThat is why you could figure out some uses yourself even with exceptions.\n\n> So let's hear it.  Until we clear the design issues, there is not much\n> point in talking about coding styles and implementation.\n\nAs I see what you need is some examples of how useful this new option\nwill be.  I am going to show some but take in account that I am\ninventing those.  Trying to conceive uses which you would think is\nuseful.  And that I know I would probably fail.\n\nI know what for I had hacked to create orphan branches myself.  But\nthose personal experiences will not be good examples to you.\n\nBut I can foresee there will be a lot of uses even if I can not\nconceive them all right now.\n\nAll said, now let's exemplify, starting with the cases I told you in\nmy last email:\n\n* Do some parallel development:\nRecreating the wheel: unix shell softwares.\n  $ vim grep.c, ...\n  $ git add .\n  $ git commit -m grep\n  $ git checkout -ob sed\n  $ vim sed.c, ...\n  $ git add .\n  $ git commit -m sed\n...\n\n* Working under unrelated parts before merging the start point of the\nnew software.\n- You start with branch A with sources to draw math functions.\n- Then you start orphan B with sources to calculate math curves, their\nareas, ...\n- Later you organize them and merge the start point of the new software.\n- Now you are ready to publish and to call for community help.\n  $ vim draw.c, ...\n  $ git add .\n  $ git commit -m 'Drawing implementation'\n  $ git checkout -ob math\n  $ vim math.c, ...\n  $ git add .\n  $ git commit -m 'Complicated Math implementation'\n...\n\n* Recreate history.  It is not published yet so it is not being widely\ncloned and people just want to have a good repository before\npublishing;\nYou start A--B--C--D then you realize that A and B is not necessary\nand that you should have started directly by C.\n  $ git checkout C\n  $ git checkout -ob GOOD\n  $ git add .\n  $ git commit -C C --reset-author\n  $ git cherry-pick D\n  $ git branch -D OLD_BRANCH\n\n* Adding files which is not meant to be part of anything in a temporary fashion;\nAdding notes to yourself.\n  $ git checkout -ob notes\n  $ git clean -df\n  $ vim note\n  $ git add .\n  $ git commit -m Notes\n\n* Have different approaches starting different sources from those\nsoftware versions until you\n find out the best one.\nYou are going to start a software which you don't know if a good\nalgorithm would be to do some factorial by recursion or not.\n  $ vim recursive.c\n  $ git add .\n  $ git commit -m recursive\n  $ git checkout -ob normal\n  $ vim straight.c\n  $ git add .\n  $ git commit -m normal\n\nThis email is being made in chronological order.  I know you have\nalready sent another one but I have chosen to reply this one before\nseeing the new one.  I will reply that one after sending this so\nplease forgive me if I am talking about something you later\nreconsidered.\n\nTo finish this email I am going to make a 'cheat sheet' to show the\nnew functionality:\n\nBranch_A\n|\nYou realize that you need a new empty branch.\n|\nIs the work tree clean?\n|                          |\nYes                     No\n|                          |\ngit clean -ob Branch_B -------Undo?-------Was the work tree clean before?\n|\n|         |\n|                                                                     Yes    No\n|\n|         |\n|\n|         git add .\n|\n|         git commit -m temp\n|\n|         |\n|\n+--------+ git checkout Branch_A -f\n|\n         |\n|\n         git merge --squash Branch_B\nDo you want to use anything from the work tree?          |\n|                         |\n         git reset\nYes                    No\n    git branch -D Branch_B\n|                         |\n|                         git clean -df\n|                         |\nChange the work tree the way you want it to be.\n|\ngit add .\ngit commit\n|\nThat is it!\n\nThank you very much for the patience to get till here.  I know it is\nhard reading much but I realize that all this subject have to be well\nexplained otherwise I will be repeating the same in a series of\nemails.  I have already did repeat on this one.  ;-)\n\nI hope all this effort will be worth-full.  Thanks again for your time!\n\nRegards\n"},{"id":"136779","messageId":"55bacdd31003141457t7d2cebe3u9854d3c0a55b7da0@mail.gmail.com","threadId":"22971","inReplyTo":"7v4okkegdy.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-14T21:57:22Z","receivedAt":"2010-03-14T21:57:22Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Hi\n\nAs I see you have found a very good example under your common work\nflow.  Nice. :-)\n\nRegards\n\n2010/3/13 Junio C Hamano <gitster@pobox.com>:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> As I already said, I do not think \"mostly common paths\" case should be\n>> encouraged to begin with.  As far as I know (and you can guess by now that\n>> I know reasonably well about git), you do not gain anything by not having\n>> the ancestry link between '?' and 'B', except that it would make conflict\n>> resolution at '*' extremely difficult.  There is only downside without any\n>> upside in \"mostly common paths\" disjoint merge.\n>\n> There is one case \"mostly common paths\" disjoint history can be useful.\n>\n> Imagine you have a hitherto proprietary software project and want to go\n> open source.  Perhaps your intention is to have an open source version and\n> an enhanced commercial version.  The project contains some third-party\n> vendor software outside your control, and you have replaced them with open\n> source equivalents or disabled features that depend on them.\n>\n> Your history may look like this:\n>\n>      o---o---A oss-base\n>     /\n>  ---o---o---o---o master\n>\n> where master is the primary version you will continue shipping to your\n> paying customers, with proprietary third-party components and features\n> that depend on them.  Commits on oss-base were your work to prepare the\n> tree into a releasable shape, removing these proprietary stuff along with\n> some features.\n>\n> But you cannot publish oss-base (commit A) to the public.  \"git log\" will\n> show all the history that leads to it, with all the third-party stuff you\n> do not have license to distribute in the source form.  The older parts of\n> the history may even have site password at customer installation you have\n> committed by mistake and eradicated long time ago.\n>\n> If you run this three command sequence (in this message, I am assuming\n> that you keep the index and the working tree files intact in an updated\n> implementation of --orphan, which is different from the suggestion to\n> support \"no common paths\" case I mentioned in the previous message):\n>\n>    $ git checkout --orphan oss oss-base\n>    $ git checkout oss-base\n>    $ git merge -s ours oss\n>\n> you will get a history of this shape:\n>\n>                X oss\n>                 \\\n>      o---o---A---B oss-base\n>     /\n>  ---o---o---o---o master\n>\n> with commits X, A and B all recording an identical tree.  The oss branch\n> (commit X) is now safe to publish.\n>\n> Once you have done this, further you can:\n>\n>    $ git checkout master\n>    $ git merge oss-base\n>\n> which gives you a history of this shape:\n>\n>                X oss\n>                 \\\n>      o---o---A---B oss-base\n>     /             \\\n>  ---o---o---o---o---Y master\n>\n> This merge Y has to be done carefully.  It inherently has to be an evil\n> merge because oss-base wants to replace some proprietary stuff with open\n> source counterparts while you may want to keep using the proprietary ones\n> you have support contract for in your paying customer release you will\n> make from the master branch.  So at Y, you will most likely be reverting\n> some work you did on oss-base branch since it forked from master.\n>\n> After setting it up, this arrangement allows you to:\n>\n>  - accept changes from public, and/or build changes for public, to advance\n>   \"community version\" on the oss branch on top of X;\n>\n>  - from time to time, merge oss to oss-base;\n>\n>  - from time to time, merge oss-base to master.\n>\n> and the histories will continue like this:\n>\n>                X---C---C---C---C oss\n>                 \\           \\\n>      o---o---A---B-----------* oss-base\n>     /             \\           \\\n>  ---o---o---o---o---Y---P---P---*---P---P master\n>\n> with community commits C (either contributed from the public or you\n> developed yourself and gave to the community) on oss branch, with\n> proprietary commits P that record your own proprietary work on master\n> branch.  Note that oss-base branch is not used to produce nor record any\n> commit on its own---it is merely to ease the merging from oss and master\n> by providing X-B link to serve as a convenient common ancestor to make\n> later merges easier.\n>\n> Note also that it would be the most convenient if you kept both the index\n> and the working tree intact, if \"checkout --orphan\" is to be used as an\n> ingredient for this workflow.  It _might_ actually make sense not to make\n> the \"git checkout --orphan\" an independent feature that can be randomly\n> abused or misused, but package the three-command sequence to create the\n> A-B-X open triangle above into a separate command, i.e.\n>\n>    $ git branch --orphan oss\n>\n> would create a new branch \"oss\" with its own root commit X that records\n> the same tree as the current HEAD A, and immediately merge X back into A\n> to produce B, again recording the same tree, and advance the current HEAD\n> to point at B, like so:\n>\n>                                             X oss\n>                                              \\\n>    ---o---A HEAD       -->         ---o---A---B HEAD\n>\n"},{"id":"136780","messageId":"55bacdd31003141457x74222a79lc060112d20dbbe4c@mail.gmail.com","threadId":"22971","inReplyTo":"m38w9wlg7i.fsf@localhost.localdomain","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-14T21:57:44Z","receivedAt":"2010-03-14T21:57:44Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Hi,\n\nYou got it right.  HTML and man branches are really very good examples.\n\nRegards\n\n2010/3/13 Jakub Narebski <jnareb@gmail.com>:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>>     Side note: The other two \"disjoint\" merges we have are also this kind\n>>     of \"no common paths\" merge.  Nobody who was involved in the branches\n>>     that resulted in them prepared his branch with --orphan, by the way.\n>>     They started out in independent repositories, because they were by\n>>     definition independent projects and these were \"cross project merges\",\n>>     as Linus put it.\n>\n> Note that beside \"disjoint\" merges (\"cross project merges\"), of gitk,\n> git-gui, gitweb and (very early in git history) git mail tools, there\n> are also three \"disjoint\"/\"unparented\" branches: 'html', 'man' and\n> 'todo'.\n>\n> While 'todo' is totally unrelated, and if instead of starting in\n> separate repository it would be created using proposed feature, it\n> would be created with \"no common paths\" case.\n>\n> BUT in the case of 'html' and 'man' branches I could see why current\n> implementation of _removing index and not removing files_ might be\n> advantageous.  Remove index, create HTML and manpage version of\n> documentation, and add HTML (in 'html' branch) or manpages (in 'man'\n> branch)... probably shifting root, so it is not all in single\n> Documentation directory.\n>\n> Just my 2 eurocents.\n>\n> --\n> Jakub Narebski\n> Poland\n> ShadeHawk on #git\n>\n"},{"id":"136781","messageId":"55bacdd31003141458y3dfa3734i664b61e69dd50436@mail.gmail.com","threadId":"22971","inReplyTo":"55bacdd31003141346t408c276ak507b7c289cf17679@mail.gmail.com","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-14T21:58:07Z","receivedAt":"2010-03-14T21:58:07Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"Resending orphan branch 'cheat sheet' again.  Gmail screwed it in\nprevious email.  See this using a fixed font:\n\nBranch_A\n|\nYou realize that you need a new empty branch.\n|\nIs the work tree clean?\n|               |\nYes             No\n|               |\ngit clean -ob Branch_B -------Undo?-------Was the work tree clean before?\n|                                                 |      |\n|                                                 Yes    No\n|                                                 |      |\n|                                                 |      git add .\n|                                                 |      git commit -m temp\n|                                                 |      |\n|                                                 +------+ git\ncheckout Branch_A -f\n|                                                        |\n|                                                        git merge\n--squash Branch_B\nDo you want to use anything from the work tree?          |\n|               |                                        git reset\nYes             No                                       git branch -D Branch_B\n|               |\n|               git clean -df\n|               |\nChange the work tree the way you want it to be.\n|\ngit add .\ngit commit\n|\nThat is it!\n"},{"id":"136787","messageId":"7vhboil4ni.fsf@alter.siamese.dyndns.org","threadId":"22971","inReplyTo":"55bacdd31003141457x74222a79lc060112d20dbbe4c@mail.gmail.com","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-15T02:06:41Z","receivedAt":"2010-03-15T02:06:41Z","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> You got it right.  HTML and man branches are really very good examples.\n\nNot at all.  You fundamentally do not want to have checkout of these\nbranches in the same place as you checkout and work in the main branches.\n"},{"id":"136788","messageId":"7vmxyajns5.fsf@alter.siamese.dyndns.org","threadId":"22971","inReplyTo":"55bacdd31003141457t7d2cebe3u9854d3c0a55b7da0@mail.gmail.com","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-15T02:56:26Z","receivedAt":"2010-03-15T02:56:26Z","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> As I see you have found a very good example under your common work\n> flow.  Nice. :-)\n\nAnd realize that it does not help that you nuke the index while leaving\nthe working tree files.\n\nI do not think you got my point at all, so let's try a different phrasing.\nI've already spent too much time on this thread, so this will be the last\nmessage from me on this topic for now.  Hopefully you will understand this\ntime.\n\nI saw two potential workflows that could be useful:\n\n (1) \"mostly common paths\" workflow;\n (2) \"no common paths\" workflow;\n\nSuppose you are on master branch and creating an orphan branch.  The first\ncommand is this for either case:\n\n    $ git checkout -b orphan --orphan master\n\nThe next action the user needs to make before starting to work on\npreparing for the first commit on that unborn branch is different\ndepending on how \"checkout --orphan\" behaves.  Let's take two extreme:\n\n - If it kept both the index and the working tree, the user does not need\n   to do anything for \"mostly common paths\", while the user only needs\n   \"git rm -rf .\" for \"no common paths\".\n\n - If it nuked both the index and the working tree, the user does not need\n   to do anything else for \"no common paths\", while the user only needs\n   \"git checkout master .\" for \"mostly common paths\".\n\nNotice that in either of these two implementations, one camp does not need\nto do anything other than the checkout itself and can immediately start\nworking to prepare for the first commit.  The other camp needs to do an\nextra thing, but that is limited to one single, simple Porcelain command.\nThere is no \"did you have untracked files? then do this\" complications.\n\nIf you nuked the index but didn't touch the working tree, which is what\nyou did, everybody is forced to do extra things, and recovery is not as\nsimple as the above two extremes.\n\nFor people who wanted \"mostly common paths\", \"git add .\" would add paths\nthat were originally shown in the untracked list, so it cannot be used;\nthey need to either choose the necessary paths and run a series of random\n\"git add WHATEVER\", or \"git add .\" and untrack unwanted paths with a\nseries of random \"git rm --cached WHATEVER\" after that.\n\nFor people who wanted \"no common paths\", \"git rm\" wouldn't work (as the\nindex is nuked), and \"git clean\" will lose originally untracked files;\nagain they need to give a series of random \"git clean WHATEVER\".\n\nEither way, everbody suffers, and recovery won't be a single simple\ncommand anymore.\n\nThe conclusion to draw is that, among four possible implementations (\"keep\nboth\", \"remove both\", \"remove index but keep working tree\", \"keep index\nbut remove working tree\"), the last two are clearly inferior compared to\nthe first two.\n\nBetween the first two, there are a few pros-and-cons.\n\n - Obviously, if most people want \"mostly common paths\", then \"keep both\"\n   would be more helpful, and vice-versa.\n\n - \"keep both\" would not need much safety, but \"remove both\" needs a\n   safety-valve implementation (you don't want to lose added changes in\n   the index, nor changes in the working tree yet to be added).\n\nSo I am inclined to say, unless \"no common paths\" is the majority of the\nuse case, \"keep both\" would be the design to pick.\n\nI didn't see in your long mail any \"third\" workflow that would be helped\nby your \"remove index but keep working tree\".  All of them were either \"no\ncommon paths\" or \"mostly common paths\".  If you demonstrated that a\n\"third\" workflow is the majority of the case, and that \"remove index but\nkeep working tree\" would be the most helpful for that \"third\" workflow,\nthen you might have made a case that \"remove index but keep working tree\"\nis the right design to use.  But I didn't see any workflow that wants a\nworking tree full of files that are nothing but untracked cruft.\n"},{"id":"136966","messageId":"55bacdd31003161117l5c43631n80e2e4a023a78199@mail.gmail.com","threadId":"22971","inReplyTo":"7vhboil4ni.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-16T18:17:04Z","receivedAt":"2010-03-16T18:17:04Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"2010/3/14 Junio C Hamano <gitster@pobox.com>:\n> Erick Mattos <erick.mattos@gmail.com> writes:\n>\n>> You got it right.  HTML and man branches are really very good examples.\n>\n> Not at all.  You fundamentally do not want to have checkout of these\n> branches in the same place as you checkout and work in the main branches.\n\nIt is unimportant the folder you will have them within.\n\nIt is a good example because they could be started or even kept\n(merged only when needed) as an unrelated branch.\n"},{"id":"136967","messageId":"55bacdd31003161118m59bc6066id2aaf7b165a601a6@mail.gmail.com","threadId":"22971","inReplyTo":"7vmxyajns5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"Erick Mattos","fromEmail":"erick.mattos@gmail.com","sentAt":"2010-03-16T18:18:02Z","receivedAt":"2010-03-16T18:18:02Z","isPatch":true,"sender":{"key":"erick.mattos@gmail.com","avatar":"https://avatars.githubusercontent.com/u/134001?v=4"},"body":"2010/3/14 Junio C Hamano <gitster@pobox.com>:\n> Erick Mattos <erick.mattos@gmail.com> writes:\n>\n>> As I see you have found a very good example under your common work\n>> flow.  Nice. :-)\n>\n> And realize that it does not help that you nuke the index while leaving\n> the working tree files.\n>\n> I do not think you got my point at all, so let's try a different phrasing.\n> I've already spent too much time on this thread, so this will be the last\n> message from me on this topic for now.  Hopefully you will understand this\n> time.\n>\n> I saw two potential workflows that could be useful:\n\nIt is an evolution we are not talking about its usefulness anymore.\n\nHowever it is not a matter of understanding too. :-)  It is about opinion.\n\nIt is just that you do not like the actual behavior and I do.\n\nBut you rule and this is just a detail anyway so I will be sending a\nnew version in a few moments.\n\nRegards\n"},{"id":"140476","messageId":"874oixe720.fsf@krank.kagedal.org","threadId":"22971","inReplyTo":"36ca99e91003112340u6256ef4dwb40e308c9a5e3a46@mail.gmail.com","subject":"Re: [PATCH v2] git checkout -b: unparent the new branch with -o","fromName":"David Kågedal","fromEmail":"davidk@lysator.liu.se","sentAt":"2010-04-27T06:35:51Z","receivedAt":"2010-04-27T06:35:51Z","isPatch":true,"sender":{"key":"davidk@lysator.liu.se","avatar":"https://avatars.githubusercontent.com/u/60530?v=4"},"body":"Bert Wesarg <bert.wesarg@googlemail.com> writes:\n\n> On Fri, Mar 12, 2010 at 07:53, Junio C Hamano <gitster@pobox.com> wrote:\n>> Erick Mattos <erick.mattos@gmail.com> writes:\n>>> +     test \"alpha\" = \"$(git branch | sed -n \"/*/s/\\* //p\")\" &&\n>>\n>> Don't read from \"git branch\" in scripts; use symbolic-ref on HEAD.\n>\n> I think what he wants is:\n>\n>         git rev-parse --abbrev-ref HEAD\n\nAha! That's a command I've been looking for a number of times. Thanks a\nlot for the tip.\n\n-- \nDavid Kågedal\n"}]}