threads / patch / 23039

v3git checkout -b: unparent the new branch with -o

Subject: [PATCH v3] git checkout -b: unparent the new branch with -o

## tl;dr

9 messages between Mar 16, 2010 and Mar 17, 2010. Diffs are folded; open one to read it.

replies: 8people: 3as markdown or json

Erick Mattos· Mar 16, 2010, 18:19 UTC · lore

Sometimes it is interesting to start a new unparented branch in an existing repository.

The new -o/--orphan is intended to solve this situation allowing the creation of a new branch unparented to any other.

After the 'checkout -o -b' the new branch is not saved until committed. Before committing you should 'git rm -rf' anything which is not going to take part in the new branch and change the work tree and index the way you want it to be since they remain untouched as before checkout command.

There are two potential work flows where this feature is most useful:

(1) "mostly common paths" work flow; (2) "no common paths" work flow;

Signed-off-by: Erick Mattos <erick.mattos@gmail.com>
---
Major rewrite to conform to Junio's demands.

Now after checkout to the new unparented branch, the index and the work tree remain unchanged.

 Documentation/git-checkout.txt |   13 ++++++++++
 builtin/checkout.c             |   10 ++++++-
 t/t2017-checkout-orphan.sh     |   49 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 2 deletions(-)
 create mode 100755 t/t2017-checkout-orphan.sh
Show changes to 3 files +70 −2

Documentation/git-checkout.txt, builtin/checkout.c, t/t2017-checkout-orphan.sh

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 37c1810..92562ce 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -9,6 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git checkout' [-q] [-f] [-m] [<branch>]
+'git checkout' [-q] [-f] [-m] [-b <new_branch> [-o]]
 'git checkout' [-q] [-f] [-m] [-b <new_branch>] [<start_point>]
 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
 'git checkout' --patch [<tree-ish>] [--] [<paths>...]
@@ -26,6 +27,13 @@ use the --track or --no-track options, which will be passed to `git
 branch`.  As a convenience, --track without `-b` implies branch
 creation; see the description of --track below.
 
+When using -b, it is possible to use the option -o to set the new branch
+as unparented thus unrelated to the previous branch.  The new branch is
+not saved until committed.  But before committing you should first do
+'git rm -rf' anything which is not going to take part in the new branch
+and change the work tree and index the way you want it to be since they
+remain untouched as before checkout command.
+
 When <paths> or --patch are given, this command does *not* switch
 branches.  It updates the named paths in the working tree from
 the index file, or from a named <tree-ish> (most often a commit).  In
@@ -86,6 +94,11 @@ explicitly give a name with '-b' in such a case.
 	Do not set up "upstream" configuration, even if the
 	branch.autosetupmerge configuration variable is true.
 
+-o::
+--orphan::
+	When creating a new branch, set it up as unparented thus
+	unrelated to the previous branch.
+
 -l::
 	Create the new branch's reflog; see linkgit:git-branch[1] for
 	details.
diff --git a/builtin/checkout.c b/builtin/checkout.c
index acefaaf..405de7e 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -34,6 +34,7 @@ struct checkout_opts {
 
 	const char *new_branch;
 	int new_branch_log;
+	int new_branch_orphan;
 	enum branch_track track;
 };
 
@@ -491,8 +492,9 @@ static void update_refs_for_switch(struct checkout_opts *opts,
 	struct strbuf msg = STRBUF_INIT;
 	const char *old_desc;
 	if (opts->new_branch) {
-		create_branch(old->name, opts->new_branch, new->name, 0,
-			      opts->new_branch_log, opts->track);
+		if (!opts->new_branch_orphan)
+			create_branch(old->name, opts->new_branch, new->name, 0,
+				      opts->new_branch_log, opts->track);
 		new->name = opts->new_branch;
 		setup_branch_path(new);
 	}
@@ -629,6 +631,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 	struct option options[] = {
 		OPT__QUIET(&opts.quiet),
 		OPT_STRING('b', NULL, &opts.new_branch, "new branch", "branch"),
+		OPT_BOOLEAN('o', "orphan", &opts.new_branch_orphan, "make the new branch unparented"),
 		OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "log for new branch"),
 		OPT_SET_INT('t', "track",  &opts.track, "track",
 			BRANCH_TRACK_EXPLICIT),
@@ -677,6 +680,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		opts.new_branch = argv0 + 1;
 	}
 
+	if (opts.new_branch_orphan && !opts.new_branch)
+		die("-o is used only with -b");
+
 	if (conflict_style) {
 		opts.merge = 1; /* implied */
 		git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh
new file mode 100755
index 0000000..c1b77ac
--- /dev/null
+++ b/t/t2017-checkout-orphan.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Erick Mattos
+#
+
+test_description='git checkout -b
+
+Tests for -o functionality.'
+
+. ./test-lib.sh
+
+TEST_FILE=foo
+
+test_expect_success 'Setup' '
+	echo "initial" >"$TEST_FILE" &&
+	git add "$TEST_FILE" &&
+	git commit -m "First Commit"
+'
+
+test_expect_success '-b without -o checkout into a new clone branch' '
+	test_tick &&
+	echo "Test 1" >>"$TEST_FILE" &&
+	git add "$TEST_FILE" &&
+	git commit -m "Second Commit" &&
+	git log --pretty=oneline >base &&
+	git checkout -b alpha &&
+	test "alpha" = "$(git symbolic-ref HEAD | sed "s,.*/,,")" &&
+	git log --pretty=oneline >actual &&
+	test_cmp base actual
+'
+
+test_expect_success '-b with -o checkout into an orphan branch' '
+	git checkout -ob beta &&
+	test_must_fail PAGER= git log >/dev/null 2>/dev/null &&
+	test "beta" = "$(git symbolic-ref HEAD | sed "s,.*/,,")" &&
+	test_tick &&
+	echo "Test 2" >>"$TEST_FILE" &&
+	git add "$TEST_FILE" &&
+	git commit -m "Third Commit" &&
+	git log --pretty=oneline >actual &&
+	test 1 -eq $(wc -l actual | sed "s/ .*//") &&
+	! test_cmp base actual
+'
+
+test_expect_success '-o must be rejected without -b' '
+	test_must_fail git checkout -o alpha
+'
+
+test_done
-- 
1.7.0.2.274.gc8f05
Junio C Hamano· Mar 16, 2010, 22:56 UTC · re: Erick Mattos · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

Erick Mattos <erick.mattos@gmail.com> writes:
Show 11 quoted lines
> Sometimes it is interesting to start a new unparented branch in an
> existing repository.
>
> The new -o/--orphan is intended to solve this situation allowing the
> creation of a new branch unparented to any other.
>
> After the 'checkout -o -b' the new branch is not saved until committed.
> Before committing you should 'git rm -rf' anything which is not going to
> take part in the new branch and change the work tree and index the way
> you want it to be since they remain untouched as before checkout
> command.

This paragraph makes the patch incoherent. It talks as if "no common paths" is the majority case, and everybody inconveniently has to perform an extra step that shouldn't be needed if the implementation were done right. If "no common paths" is indeed the assumed primary target, why doesn't the implementation empty both index and files in the working tree so that users don't have to do so themselves?

My _only_ complaint was that your version that _only_ emptied the index without touching the working tree made things difficult for everybody, both "no common paths" people and "mostly common paths" people.

You need to at least qualify the above paragraph with something like "if you want to create an unrelated branch whose contents do not resemble the original branch at all, then you should ...".

Better yet, try to advertise what you are giving your users in a positive way, instead of in a way that only scares users, perhaps like this:

    After 'checkout --orphan', your HEAD will point at an unborn branch,
    and the next commit will start a new history without any prior commit.
    To help create such a new history that has contents mostly the same as
    that of the original branch, the command does not touch the index nor
    the working tree, and "checkout --orphan" immediately followed by
    "commit -a" would record a tree very similar to what you had in the
    original branch.  This is useful when you want to ... [insert a
    summary of "going open source" example from my previous message if you
    want here].
    If on the other hand you want to start a new branch whose contents do
    not resemble the original branch at all, you may want to start from an
    empty index and the working tree, with "git rm -rf ." immediately
    after running this command.
The same comment applies to the documentation part.

By the way, I wouldn't mind if you believe "no common paths" is the majority case; if that is the case, then the code and behaviour would be different, and the presentation would say something like this:

    After 'checkout --orphan', your HEAD will point at an unborn branch,
    and the next commit will start a new history without any prior commit.
    To help create such a new history that has contents totally different
    from the original branch, the command empties the index and removes
    all tracked files from the working tree.  The command refuses to work
    if you have uncommitted changes, so that you won't lose them.
    Conclude the work in progress on your current branch first by first
    recording the changes in commits (or "git stash save") before
    re-running the command.
    After "checkout --orphan" you can immediately start preparing the
    files to be tracked in this new branch, without files unrelated to
    this branch getting in the way.  This is useful when you want to
    ... [I don't think any "no commmon paths" workflow makes sense to be
    done in the same repository, but you seem to do do so, so give readers
    such an example here].
    If on the other hand you want to start a new branch whose contents
    mostly match the original branch, you may need to start from an
    index and the working tree files from the original branch, by running
    "git checkout <original-branch-name> ."  after running this command.
Erick Mattos· Mar 17, 2010, 01:10 UTC · re: Junio C Hamano · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

Hi,

Junio, you are the leader. And I really don't want to bother you with my opinions.

I am just trying to make you satisfied so gitsters, I mean git users, will have this feature as soon as possible.

2010/3/16 Junio C Hamano <gitster@pobox.com>:
Show 12 quoted lines
>> After the 'checkout -o -b' the new branch is not saved until committed.
>> Before committing you should 'git rm -rf' anything which is not going to
>> take part in the new branch and change the work tree and index the way
>> you want it to be since they remain untouched as before checkout
>> command.
>
> This paragraph makes the patch incoherent.  It talks as if "no common
> paths" is the majority case, and everybody inconveniently has to perform
> an extra step that shouldn't be needed if the implementation were done
> right.  If "no common paths" is indeed the assumed primary target, why
> doesn't the implementation empty both index and files in the working tree
> so that users don't have to do so themselves?

I was NOT trying to scare with my message. That paragraph was meant to let people who would need to do something ("no common paths") know what they will need to do. I think it is good enough because "mostly common paths" people will be happy too by knowing that everything is unchanged as they want it to be. So I haven't thought about scaring at all. I thought it was good indeed! :-)

> My _only_ complaint was that your version that _only_ emptied the index
> without touching the working tree made things difficult for everybody,
> both "no common paths" people and "mostly common paths" people.
Just to clarify my point-of-view about the design:

I do prefer my first design mainly because it mimics the state of an initial commit. I think that is subjectively better.

You have been asking me to make one of the two possible work flow uses you pictured as favored so things will be already set to them. No further commands to them.

I did it! As a matter of fact the "mostly common paths" people were favored as you have noticed your inclination to it before.

As I told you, I just want to make you happy so people that needs the feature I am working on could have it as fast as possible.

And if one of the possible work flows have to be favored then I do agree with you about "mostly common paths" as the best choice.

But the point is that the other group will need to do further commands anyway so I would keep my previous design because of the resemblance to an initial commit: work tree full and nothing added to the index.

But I mean it! I really want to satisfy you. So this was the last time I talk about my preference.

Therefore let's find out what you want me to do so we can finish this production cycle. I don't want to bother you anymore.

Show 23 quoted lines
> You need to at least qualify the above paragraph with something like "if
> you want to create an unrelated branch whose contents do not resemble the
> original branch at all, then you should ...".
>
> Better yet, try to advertise what you are giving your users in a positive
> way, instead of in a way that only scares users, perhaps like this:
>
>    After 'checkout --orphan', your HEAD will point at an unborn branch,
>    and the next commit will start a new history without any prior commit.
>    To help create such a new history that has contents mostly the same as
>    that of the original branch, the command does not touch the index nor
>    the working tree, and "checkout --orphan" immediately followed by
>    "commit -a" would record a tree very similar to what you had in the
>    original branch.  This is useful when you want to ... [insert a
>    summary of "going open source" example from my previous message if you
>    want here].
>
>    If on the other hand you want to start a new branch whose contents do
>    not resemble the original branch at all, you may want to start from an
>    empty index and the working tree, with "git rm -rf ." immediately
>    after running this command.
>
> The same comment applies to the documentation part.
I was trying to be concise on my message.  I realize you want it more explained.
What about that:

After the 'checkout -o -b' you are in an new unborn branch ready to be committed. The next commit will start a new history without any ancestry. If this new branch was made to start from scratch, not resembling the previous one, then you should use 'git rm -rf' to get an empty work tree and index. Otherwise with a 'git commit -a' you will have a tree exactly as in the previous branch. So just set things as you want it to be and commit the new unparented branch.

> By the way, I wouldn't mind if you believe "no common paths" is the
> majority case; if that is the case, then the code and behaviour would be
> different, and the presentation would say something like this:

I agree with you in choosing "mostly common paths" as the target since you have decided to target one.

Before I send another patch version could you please tell me your position about my new explaining text up there. I will wait for your reply before sending a new patch version.

Best regards
Jonathan Nieder· Mar 17, 2010, 04:13 UTC · re: Erick Mattos · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

Hi,
Erick Mattos wrote:
> I am just trying to make you satisfied so gitsters, I mean git users,
> will have this feature as soon as possible.
Well, hopefully everyone wants it to make sense, too. :)
Show 9 quoted lines
> I do prefer my first design mainly because it mimics the state of an
> initial commit.  I think that is subjectively better.
> 
> You have been asking me to make one of the two possible work flow uses
> you pictured as favored so things will be already set to them.  No
> further commands to them.
> 
> I did it!  As a matter of fact the "mostly common paths" people were
> favored as you have noticed your inclination to it before.
I guess I am confused because I am not sure what you are trying to do:
 A. on one hand, you might want a command to use as a building block.
    In practice, people would use scripts or refer to known recipes to
    make use of this building block in one of a few known combinations
    with other commands.
 B. on the other hand, you might be trying to make it easier to get
    some particular task done.

Junio was discussing the case B. Whoever has the itch is in a good position to say what interface would be convenient. Usually one command invocation can be enough to accomplish most of what is needed on its own. There were two examples of such commands he gave:

 1.                                                    * [public]
                                                        \
     * --- * --- * [private]   ===>    * --- * --- * --- * [private]
   for the “we cannot publish the whole history” use,
and
 2.                                                 * [doc]
    * --- * --- * [master]  ===>  * --- * --- * --- * [master]
   for the “starting unrelated development but restrictive disk quotas
   mean I have to use the same working directory” use.

In these examples (which are just examples for illustration of what a well supported use case looks like), the content in the index and work tree after the command is run is tailored to what is expected to be needed.

I suspect you are aiming for case A instead. For scripts and special case recipes, it might be a good idea to have a command to use as an ingredient in tasks like (1) and (2) above. The recipe people currently use is usually something like the following:

  git symbolic-ref HEAD refs/heads/newbranch
  rm .git/index

but that indeed is not perfect: it does not check for a dirty index in case 1, it does not keep track of what files were not registered in the index so as not to delete them in case 2, and so on.

Also one might object to the knowledge of repository layout required; gitrepository-layout(5) is probably not the first place a person would look in trying to figure out how to carry out this task. That misses the point, though, in my opinion, since

 git symbolic-ref HEAD refs/heads/newbranch
 git rm --cached '*'

accomplishes the same thing. Anyway, if your goal is to create plumbing, I would suggest modifying a plumbing command instead of ‘git checkout’.

Thank you for your efforts. As hinted above, I would not mind seeing improvement in this area at all. Anyway, I hope this has provided some food for thought (if not, don’t mind me; please carry on).

Kind regards, Jonathan

Junio C Hamano· Mar 17, 2010, 05:23 UTC · re: Jonathan Nieder · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

Jonathan Nieder <jrnieder@gmail.com> writes:
> Junio was discussing the case B.

Well, not really. Even as an ingredient, "nuke index, leaving files in the work tree around" is the most difficult-to-use mode of operation. Either "try to run 'git rm -f .' from the toplevel and only if it succeeds point HEAD to an unborn branch" (aka "remove both"), or "point HEAD to an unborn branch without doing anything else" (aka "keep both") would be an ingredient that is far easier to use.

Jonathan Nieder· Mar 17, 2010, 06:40 UTC · re: Junio C Hamano · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

Junio C Hamano wrote:
Show 10 quoted lines
> Jonathan Nieder <jrnieder@gmail.com> writes:
> 
> > Junio was discussing the case B.
> 
> Well, not really.  Even as an ingredient, "nuke index, leaving files in
> the work tree around" is the most difficult-to-use mode of operation.
> Either "try to run 'git rm -f .' from the toplevel and only if it succeeds
> point HEAD to an unborn branch" (aka "remove both"), or "point HEAD to an
> unborn branch without doing anything else" (aka "keep both") would be an
> ingredient that is far easier to use.

Okay, fair enough. From the point of view of plumbing, what is there left to do that

	git rm -f . &&
	git symbolic-ref HEAD refs/heads/new
or
	git symbolic-ref HEAD refs/heads/new
or
	git rm --cached . &&
	git symbolic-ref HEAD refs/heads/new
does not take care of?

I guess I should have said that I would be happier to see something tailored to a use case or a class of use cases.

I haven’t needed it for a while, but once upon a time I was making isolated branches like crazy for some abuse of git as a compression tool.

Jonathan
Junio C Hamano· Mar 17, 2010, 17:17 UTC · re: Jonathan Nieder · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

Jonathan Nieder <jrnieder@gmail.com> writes:
Show 16 quoted lines
> Okay, fair enough.  From the point of view of plumbing, what is there
> left to do that
>
> 	git rm -f . &&
> 	git symbolic-ref HEAD refs/heads/new
>
> or
>
> 	git symbolic-ref HEAD refs/heads/new
>
> or
>
> 	git rm --cached . &&
> 	git symbolic-ref HEAD refs/heads/new
>
> does not take care of?

If we have the "just detach, don't touch index nor working tree", which happens to be the cheapest one in the middle (except that it probably wants to verify that "new" does not exist yet), the calling script of the Porcelain suite can use it in conjunction with various forms of "git rm" without incurring any additional overhead (other than a fork-and-exec), and I think that would be sufficient.

You could add
	git ls-files |
        while read path
        do
        	case $(choose-keep-drop-nuke "$path") in
                keep) ;;
                drop) git rm --cached -f "$path" ;;
                nuke) git rm -f "$path" ;;
        	esac
	done
	git symbolic-ref HEAD refs/heads/new

and have the caller supply a callback that intelligently choose what to keep and what to drop, if you want to be really fancy, but at that level of complexity, I think it is something the Porcelain writer using the plumbing would want to write himself as part of the Porcelain program.

We might want to add "git branch --switch <branchname>" that is roughly like this:

    ref="refs/heads/$branch"
    git check-ref-format "$ref" || die "malformed"
    if git rev-parse -q --verify "$ref" >/dev/null
    then
    	# exists
        exec git checkout "$branch"
    else
	# create
	exec git symbolic-ref HEAD "$ref"
    fi
Erick Mattos· Mar 17, 2010, 18:55 UTC · re: Jonathan Nieder · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

2010/3/17 Jonathan Nieder <jrnieder@gmail.com>:
Show 8 quoted lines
> ...
>
> Thank you for your efforts.  As hinted above, I would not mind seeing
> improvement in this area at all.  Anyway, I hope this has provided some
> food for thought (if not, don’t mind me; please carry on).
>
> Kind regards,
> Jonathan
Thanks for your kindness.

We are almost at the end of this new option creation cycle. We are now building the appropriated explaining messages.

This improvement is indeed targeted to let end users create orphan branches. I don't see a reason for changing focus because I see this need as eventual really.

Kind regards
Junio C Hamano· Mar 17, 2010, 05:21 UTC · re: Erick Mattos · lore

Re: [PATCH v3] git checkout -b: unparent the new branch with -o

Erick Mattos <erick.mattos@gmail.com> writes:
> I am just trying to make you satisfied so gitsters, I mean git users,
> will have this feature as soon as possible.

Don't try to satisfy _me_ personally. It is not likely that I am going to use "checkout --orphan" myself. But I would not reject a new feature that does make sense to some people, even if it is not something I would use. I am here to help people like you help others (and to prevent people from harming others).

I however am going to have to answer when people complain "why was this senseless new feature added to the system? what it does makes no sense and does not help me."

"Nuke index but not working tree" is not something I think I can defend and explain as sensible to these people, as I do not think it makes sense myself. So when Ispot a design that logically does not make sense to me, I would say so and ask clarifications. A major part of the maintainer's job is to ask questions and say "no".

> I do prefer my first design mainly because it mimics the state of an
> initial commit.  I think that is subjectively better.

You keep saying that, but I think it is misguided. And I do not think there is anything subjective there.

If you are starting from scratch, you would:
    $ git init newrepo
    $ cd newrepo

and that is how the state before the initial commit begins with. You might then do this to prepare for the commit:

    $ tar xf ~/junk/frotz-2.43.tar.gz
    $ git add .
Or perhaps you would work the other way around:
    $ tar xf ~/junk/frotz-2.43.tar.gz
    $ cd frotz-2.43
    $ git init
    $ git add .

Whichever way you work, notice that you wouldn't have any rubbish in the working tree unrelated to the "frotz" project, when the tool (in this case, "git init") prepares the repository with a dangling HEAD and the working tree "before the initial commit". You either have emptiness (to which you can untar into), or you already have files that you would want to have in the branch and no other cruft.

If you did "nuke index, leaving files in the work tree around", the result does not resemble "state before the initial commit" at all. The leftover files will get in the way.

The leftover worktree files will not get in the way ONLY if the user wants to record a tree that is similar to the original branch, but even in that case they have to do "git add ."; keeping the index intact would help them even better.

After realizing all that, do you still think "nuke only the index" is subjectively better?

> I did it!

Sure, I am saying that then you should advertise the result as such, without being negative.

Show 21 quoted lines
>> Better yet, try to advertise what you are giving your users in a positive
>> way, instead of in a way that only scares users, perhaps like this:
>>
>>    After 'checkout --orphan', your HEAD will point at an unborn branch,
>>    and the next commit will start a new history without any prior commit.
>>    To help create such a new history that has contents mostly the same as
>>    that of the original branch, the command does not touch the index nor
>>    the working tree, and "checkout --orphan" immediately followed by
>>    "commit -a" would record a tree very similar to what you had in the
>>    original branch.  This is useful when you want to ... [insert a
>>    summary of "going open source" example from my previous message if you
>>    want here].
>>
>>    If on the other hand you want to start a new branch whose contents do
>>    not resemble the original branch at all, you may want to start from an
>>    empty index and the working tree, with "git rm -rf ." immediately
>>    after running this command.
>>
>> The same comment applies to the documentation part.
>
> I was trying to be concise on my message.  I realize you want it more explained.
Concise is good.  Negative is not.
Show 7 quoted lines
> After the 'checkout -o -b' you are in an new unborn branch ready to be
> committed.  The next commit will start a new history without any
> ancestry.  If this new branch was made to start from scratch, not
> resembling the previous one, then you should use 'git rm -rf' to get
> an empty work tree and index.  Otherwise with a 'git commit -a' you
> will have a tree exactly as in the previous branch.  So just set
> things as you want it to be and commit the new unparented branch.
I wouldn't start the description with
    if you want 'no common paths', then it would be more cumbersome than
    just this single command

if the primary workflow your chose to support with your implementation is 'mostly common paths'.

Look at the example I gave you more carefully. The primary use case we intend to support is described first. Also it is written in much more inviting tone, in order to help readers understand the motivation behind the feature. IOW, "Ah, that is something I may want to do in some cases, and the new feature indeed sounds useful." is what we want to hear from the readers (the log message for reviewers, and the documentation for the end users) after they read the explanation. The second paragraph then mentions the less common use case for completeness. To the readers who understand why the behaviour of the command makes sense for its primary use case (which is described first), it would be easier to accept that they have to run an extra command (by the way, it is "'git rm -rf .' from the top-level of the working tree; do not forget the dot at the end) to clean up the working tree to a prestine state, because they would understand the reason why the clearing is not done by default.

The same comment applies to the documentation part of the patch. Don't be negative. Positively explain why what you added is useful, and help the users understand why they might want to use it and in what situation.

← back to recent threads