* [PATCH v2] git checkout -b: unparent the new branch with -o
@ 2010-03-09 22:28 Erick Mattos
2010-03-12 6:53 ` Junio C Hamano
0 siblings, 1 reply; 17+ messages in thread
From: Erick Mattos @ 2010-03-09 22:28 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Erick Mattos
Sometimes it is necessary to start up a new development branch of code
intended to be merged in the near future to existing branches but which
actually does not relate to them.
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 some files are
added to the index and committed, exactly as if it was an initial commit.
A 'git clean -df' would delete everything from the work tree making it
empty for new files.
Signed-off-by: Erick Mattos <erick.mattos@gmail.com>
---
Changed the text in SYNOPSIS to correct it as noticed by Jakub Narebski.
Regards
Documentation/git-checkout.txt | 10 ++++++++
builtin-checkout.c | 14 +++++++++-
t/t2017-checkout-orphan.sh | 50 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 2 deletions(-)
create mode 100755 t/t2017-checkout-orphan.sh
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 37c1810..c13ab62 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>...]
@@ -25,6 +26,10 @@ linkgit:git-branch[1] were called; in this case you can
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 code will
+be committed by using 'git add' and 'git commit' as if it was an initial
+commit.
When <paths> or --patch are given, this command does *not* switch
branches. It updates the named paths in the working tree from
@@ -86,6 +91,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 c5ab783..4882613 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;
};
@@ -509,8 +510,13 @@ 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) {
+ discard_cache();
+ remove_path(get_index_file());
+ }
+ else
+ 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);
}
@@ -647,6 +653,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),
@@ -695,6 +702,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..7170641
--- /dev/null
+++ b/t/t2017-checkout-orphan.sh
@@ -0,0 +1,50 @@
+#!/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 branch | sed -n "/*/s/\* //p")" &&
+ 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 -z "$(git branch | grep \*)" &&
+ test "beta" = "$(git symbolic-ref HEAD | sed "s,.*/,,")" &&
+ test -z "$(git ls-files)" &&
+ 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.99.ge963b.dirty
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-09 22:28 [PATCH v2] git checkout -b: unparent the new branch with -o Erick Mattos
@ 2010-03-12 6:53 ` Junio C Hamano
2010-03-12 7:40 ` Bert Wesarg
2010-03-12 16:45 ` Erick Mattos
0 siblings, 2 replies; 17+ messages in thread
From: Junio C Hamano @ 2010-03-12 6:53 UTC (permalink / raw)
To: Erick Mattos; +Cc: git
Erick Mattos <erick.mattos@gmail.com> writes:
> @@ -25,6 +26,10 @@ linkgit:git-branch[1] were called; in this case you can
> 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 code will
> +be committed by using 'git add' and 'git commit' as if it was an initial
> +commit.
This says what the option does, but it is hard to guess why it would be a
good thing to do in the first place from the above description.
The use case in your commit log message wasn't convincing either. If such
a new branch will be merged later, especially if the trees of the commits
in newly rooted history resemble the trees in the original history (I am
guessing that is the intended use case, as you do not seem to be removing
anything from the working tree---how is the user expected to use them by
the way?), not having a common merge base will make the merge harder, not
easier, and later examination of the history (think "bisect") also
harder.
This looks like a "because we can" feeping creaturism, without any
"because it is beneficial if users can do this for this reason"
justification.
And what it can do "because we can" doesn't look very useful, safe, nor
sane either, with this particular implementation.
> @@ -509,8 +510,13 @@ 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) {
> + discard_cache();
> + remove_path(get_index_file());
I don't think we want to see "remove_path()" here. The function is about
the files in the work tree, and not about the files under .git/.
Currently the codepath to create and write out the index is abstracted
like this:
fd = hold_locked_index();
... populate the_index structure ...
write_cache(fd);
commit_locked_index();
and by only changing the implementation of these three functions, we could
store the index somewhere other than on the filesystem (say, database or
memcache). By using remove_path() on the return value of get_index_file()
in a random codepath like this one, you are pre-seeding a bug for other
people who may ant to make changes like that in the future.
But the above is just an advice on the coding, assuming that what is being
coded is sane, which unfortunately is not. You are nuking the index but
without doing anything to the working tree files. Why? The user manually
has to remove them? Or re-add them? I don't think you would want to call
discard_cache() _nor_ remove the index file here. This is probably even
more so if you think about a case where the user is using a sparse
checkout. Some random set of files are still in the working tree but
other files aren't, and the index used to keep track of which is what, but
you lost that information by discarding the cache.
If you are going to leave the files in the working tree intact, you should
make it the user's responsibility to run "git rm -f" after "checkout -o",
if the user wants to start from an empty index. That would also make it
safer; a mistaken "checkout -o" would be easier to recover from by running
reset without --hard, if it does not touch the index.
By the way, the worst part of this patch is that I didn't see any safety
checks tested in the test script. What prevents the users from typing an
extra -o by mistake, while having some changes to the index and/or the
files in the working tree? Even if you change it not to touch the index,
it would probably make sense to make sure this "feature" is a lot harder
to invoke by mistake. In a sane workflow you wouldn't be creating root
commits left and right. Perhaps by not giving it a '-o' shorthand would
be a good start.
In the above I assumed (by guessing from the fact that you are not
touching files in the working tree) that the tree eventually committed by
the user on this newly rooted history would have some resemblance to the
trees in the original history. But if -o is intended to be used for
really "starting from void" with an empty tree, then I think the option
should instead do this:
- run an equivalent of "git rm .", which includes:
- make sure no change is in the index relative to HEAD; otherwise error
out.
- make sure no change is in the working tree relative to the index;
otherwise error out.
- discard_cache() and write that empty index out;
- make the HEAD dangling like you did.
That would be safe and halfway useful _if_ somebody wants to start a truly
new history from scratch, even though if you want to have an unrelated
history in your repository it would be more natural do so by fetching such
an unrelated history from an unrelated repository.
The way the patch implements is not suited for neither "starting from
void" case, nor "continuing the tree but with disjoint history" case, I
think.
> diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh
> new file mode 100755
> index 0000000..7170641
> --- /dev/null
> +++ b/t/t2017-checkout-orphan.sh
> @@ -0,0 +1,50 @@
> +#!/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" &&
This is just style, but I find it easier to read if you have one SP before
redirect and no SP between redirect and the filename, i.e.:
echo initial >"$TEST_FILE" &&
> + test "alpha" = "$(git branch | sed -n "/*/s/\* //p")" &&
Don't read from "git branch" in scripts; use symbolic-ref on HEAD.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-12 6:53 ` Junio C Hamano
@ 2010-03-12 7:40 ` Bert Wesarg
2010-04-27 6:35 ` David Kågedal
2010-03-12 16:45 ` Erick Mattos
1 sibling, 1 reply; 17+ messages in thread
From: Bert Wesarg @ 2010-03-12 7:40 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Erick Mattos, git
On Fri, Mar 12, 2010 at 07:53, Junio C Hamano <gitster@pobox.com> wrote:
> Erick Mattos <erick.mattos@gmail.com> writes:
>> + test "alpha" = "$(git branch | sed -n "/*/s/\* //p")" &&
>
> Don't read from "git branch" in scripts; use symbolic-ref on HEAD.
I think what he wants is:
git rev-parse --abbrev-ref HEAD
Bert
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-12 6:53 ` Junio C Hamano
2010-03-12 7:40 ` Bert Wesarg
@ 2010-03-12 16:45 ` Erick Mattos
2010-03-13 7:53 ` Junio C Hamano
1 sibling, 1 reply; 17+ messages in thread
From: Erick Mattos @ 2010-03-12 16:45 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
Thanks for answering.
I had to write a little in reply so I beg for you patience to read it.
This is a new option and before we start talking about the
implementation we should agree about its usefulness and the subjects
addressed by it.
This is something that probably you haven't needed so I understand
your resistance. In a intense merging software development work flow
it would be quite rare to have a merge of an unrelated branch.
But not all of the software developments happen under this work flow.
There is a lot of very small projects. Being developed by a few
people or even by one person. And those softwares count too. They
could become very important for everyone some day.
For those it is very common to:
* Do some parallel development.
* Working under unrelated parts before merging the start point of the
new software.
* Recreate history. It is not published yet so it is not being widely
cloned and people just
want to have a good repository before publishing;
* Adding files which is not meant to be part of anything in a temporary fashion;
* Have different approaches starting different sources from those
software versions until you
find out the best one.
Git is becoming much more used than it was planned to be. It is even
being used nowadays for other exotic jobs like regular file
versioning.
Those needs are nothing new. If you query Google for "new empty
branch git" you will find that people have been querying it for.
There are a lot of ways to have the unrelated branch: you could start
a new repository and import from it; you could foresee that you will
need something like that and start all development with an empty
commit, ...
But the proposed solution is the best approach. And it is the one I
use when needed.
This new option is not a new solution. Just a direct implementation
so people will not need to know this hack. See it:
Git SCM Wiki:
http://git.wiki.kernel.org/index.php/GitTips#How_to_create_a_new_branch_that_has_no_ancestor
Git Book:
http://book.git-scm.com/5_creating_new_empty_branches.html
After all said let's face the implementation.
2010/3/12 Junio C Hamano <gitster@pobox.com>
>
> Erick Mattos <erick.mattos@gmail.com> writes:
>
> > @@ -25,6 +26,10 @@ linkgit:git-branch[1] were called; in this case you can
> > 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 code will
> > +be committed by using 'git add' and 'git commit' as if it was an initial
> > +commit.
>
> This says what the option does, but it is hard to guess why it would be a
> good thing to do in the first place from the above description.
So you would like to have some examples on it?
I was trying to let people know how to use it not why to use it.
> The use case in your commit log message wasn't convincing either. If such
> a new branch will be merged later, especially if the trees of the commits
> in newly rooted history resemble the trees in the original history (I am
> guessing that is the intended use case, as you do not seem to be removing
> anything from the working tree---how is the user expected to use them by
> the way?), not having a common merge base will make the merge harder, not
> easier, and later examination of the history (think "bisect") also
> harder.
Are you talking about the commit log message of the previous version
patch? If that is the case I replied to your message explaining it
better (but not trying to convince you).
I am not wiping the tree by default because I am not deciding for
people if they are going to use anything from it as a template (even
the directory structure only).
I am not trying to make decisions for the user. I think he would be
capable of deciding it himself. That is my way of thinking so I
normally prefer to advice, alert, inform not to impose.
We should remember git users are normally programers not some wind... lamers.
The intended uses of this option was explained up there.
As it is a new fresh development branch it is not normally expected to
have anything in common with original branch so the future merge is
going to be very easy. Anything exotic is up to the user to solve.
> This looks like a "because we can" feeping creaturism, without any
> "because it is beneficial if users can do this for this reason"
> justification.
>
> And what it can do "because we can" doesn't look very useful, safe, nor
> sane either, with this particular implementation.
Benefits explained up there already.
It is not creaturism. People need this option at various levels.
> > @@ -509,8 +510,13 @@ 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) {
> > + discard_cache();
> > + remove_path(get_index_file());
>
> I don't think we want to see "remove_path()" here. The function is about
> the files in the work tree, and not about the files under .git/.
> Currently the codepath to create and write out the index is abstracted
> like this:
>
> fd = hold_locked_index();
> ... populate the_index structure ...
> write_cache(fd);
> commit_locked_index();
>
> and by only changing the implementation of these three functions, we could
> store the index somewhere other than on the filesystem (say, database or
> memcache). By using remove_path() on the return value of get_index_file()
> in a random codepath like this one, you are pre-seeding a bug for other
> people who may ant to make changes like that in the future.
I see your point but what we will be doing is just wiping the index
out. So I did it in a direct fashion.
Please let me know after you read this whole reply if you still
consider this way as inadequate.
> But the above is just an advice on the coding, assuming that what is being
> coded is sane, which unfortunately is not. You are nuking the index but
> without doing anything to the working tree files. Why? The user manually
> has to remove them? Or re-add them? I don't think you would want to call
> discard_cache() _nor_ remove the index file here. This is probably even
> more so if you think about a case where the user is using a sparse
> checkout. Some random set of files are still in the working tree but
> other files aren't, and the index used to keep track of which is what, but
> you lost that information by discarding the cache.
I have already replied that but let me state it: we will be leting
people start an unrelated branch, unrelated work, fresh new stuff.
And leting them do anything they want with the files in the work tree.
Deleting them as easy as 'git clean -df'.
>
> If you are going to leave the files in the working tree intact, you should
> make it the user's responsibility to run "git rm -f" after "checkout -o",
> if the user wants to start from an empty index. That would also make it
> safer; a mistaken "checkout -o" would be easier to recover from by running
> reset without --hard, if it does not touch the index.
It is already very safe and easy to recover by just doing a 'git
checkout PREVIOUS_BRANCH'.
>
> By the way, the worst part of this patch is that I didn't see any safety
> checks tested in the test script. What prevents the users from typing an
> extra -o by mistake, while having some changes to the index and/or the
> files in the working tree? Even if you change it not to touch the index,
> it would probably make sense to make sure this "feature" is a lot harder
> to invoke by mistake. In a sane workflow you wouldn't be creating root
> commits left and right. Perhaps by not giving it a '-o' shorthand would
> be a good start.
I don't quite see your point here. Not letting people use it when
they don't want to use it?!
Like protecting him from typing a letter 'o' at keyboard when creating
a branch with -b and pressing enter after this mistake?!
I really have not get it. Could you please explain it from what we
have to protect him?
>
> In the above I assumed (by guessing from the fact that you are not
> touching files in the working tree) that the tree eventually committed by
> the user on this newly rooted history would have some resemblance to the
> trees in the original history. But if -o is intended to be used for
> really "starting from void" with an empty tree, then I think the option
> should instead do this:
The user could probably use something from the work tree as template
so I am not making assuptions. Just leting him know that with a 'git
clean -df' everything would be vanished.
>
> This is just style, but I find it easier to read if you have one SP before
> redirect and no SP between redirect and the filename, i.e.:
>
> echo initial >"$TEST_FILE" &&
You are the one that must demand the style so I am going to change it.
>
> > + test "alpha" = "$(git branch | sed -n "/*/s/\* //p")" &&
>
> Don't read from "git branch" in scripts; use symbolic-ref on HEAD.
All right then.
Thanks for you patience to read this email and I hope this effort will
worth something.
Regards
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-12 16:45 ` Erick Mattos
@ 2010-03-13 7:53 ` Junio C Hamano
2010-03-13 9:10 ` Junio C Hamano
` (2 more replies)
0 siblings, 3 replies; 17+ messages in thread
From: Junio C Hamano @ 2010-03-13 7:53 UTC (permalink / raw)
To: Erick Mattos; +Cc: git
Erick Mattos <erick.mattos@gmail.com> writes:
>> The use case in your commit log message wasn't convincing either. If such
>> a new branch will be merged later, especially if the trees of the commits
>> in newly rooted history resemble the trees in the original history (I am
>> guessing that is the intended use case, as you do not seem to be removing
>> anything from the working tree---how is the user expected to use them by
>> the way?), not having a common merge base will make the merge harder, not
>> easier, and later examination of the history (think "bisect") also
>> harder.
>
> Are you talking about the commit log message of the previous version
> patch?
I was referring to this from the latest version:
Sometimes it is necessary to start up a new development branch of code
intended to be merged in the near future to existing branches but which
actually does not relate to them.
Let's give you an example of the depth of thought and clarity of
description of the workflow I am expecting from anybody who claims "this
is a useful feature to help _some_ workflows" by taking an example from
git.git, because it is one project that both of us are familiar with and
there is a readily available example in it. It has disjoint merges from
gitk, gitweb and git-gui. The history up to such a merge 5569bf9 (Do a
cross-project merge of Paul Mackerras' gitk visualizer, 2005-06-22) looks
like this:
A---o---?---o---o---X---* linus
. /
B---o---o---Y gitk
Note that with this merge '*', two histories merged did not share any
paths at commit X and Y.
Did you have this kind of "no common paths" merge in mind when you wrote
the proposed commit log message? IOW, if we pretend that Paul started his
gitk work and he "intended to be merged to Linus's branch but which does
not relate to it", would that be a good example of what you are trying to
achieve?
Side note: The other two "disjoint" merges we have are also this kind
of "no common paths" merge. Nobody who was involved in the branches
that resulted in them prepared his branch with --orphan, by the way.
They started out in independent repositories, because they were by
definition independent projects and these were "cross project merges",
as Linus put it.
I'd grant you that we could say that these histories did not start in the
same repository using "checkout --orphan" because it was not available.
But in that case, it would have been nicer if Paul didn't have to remove
files came from Linus's branch, left by your "checkout --orphan", by hand.
"rm -rf" would not have been very useful, especially if he had some
untracked files that he never intended to commit to git project but did
not want to lose (think of "Notes" "memo" "todo" files you would keep in
the source tree). The most natural way to keep these untracked files
while removing now-unneeded tracked files in the Linus's git when he
switched from using "checkout --orphan" would have been to use something
like "ls-files -z | xargs -0 rm -f". But you are nuking the index without
removing the tracked files, so that becomes impossible.
On the other hand, Paul could have started his gitk branch from a copy of
git Linus had published. Even though gitk was developed with an intention
to run with any version of git available that was installed idependently
on the system, it did depend on git and it would have made equal amount of
sense if he shipped with a matching version of git, saying "this version
of gitk was tested with this git". If that were the case, paths at commit
X and Y would have been overlapping. In fact, gitk has been a single-file
project for a long time, so most of the paths were the same and Y would
had one file more than X.
Did you have this kind of "mostly common paths" merge in mind when you
wrote the proposed commit log message? IOW, if "checkout --orphan" were
available to Paul, would you have recommended him to use it, add his gitk
script to the tree, and start his history at commit B which he started
from commit '?' from Linus's history? But you are again nuking the index
so Paul would have had to add the files back with "git add", while being
careful not to add untracked files, or run "git read-tree ?" to populate
the index back to the original state.
> I am not wiping the tree by default because I am not deciding for
> people if they are going to use anything from it as a template (even
> the directory structure only).
>
> I am not trying to make decisions for the user. I think he would be
> capable of deciding it himself. That is my way of thinking so I
> normally prefer to advice, alert, inform not to impose.
You may think that you are supporting both, but in reality, you are
supporting neither by making both cases equally inconvenient. The only
thing you are gaining is a way to weasel out of issues experienced by the
users by saying "I didn't remove anything from the working tree, so if you
want to add them, you can, it is up to you", while ignoring the issue that
(1) if the user wants "no common paths", cleaning working tree becomes
cumbersome and error prone, and (2) if the user wants "mostly common
paths", adding back to the index becomes cumbersome and error prone.
As I already said, I do not think "mostly common paths" case should be
encouraged to begin with. As far as I know (and you can guess by now that
I know reasonably well about git), you do not gain anything by not having
the ancestry link between '?' and 'B', except that it would make conflict
resolution at '*' extremely difficult. There is only downside without any
upside in "mostly common paths" disjoint merge.
That leaves only the "almost no common paths" case. As we have already
seen in git project, the end result is indeed very useful. It used to be
that people had to download and use gitk independently before Linus's
cross project merge, but after the merge, the project gives the core git
and gitk comes with it. So you could argue that "checkout --orphan" would
become useful if you adjusted the code like I suggested in my review
comments (run an equivalent of "git rm" without "-f" from the top-level
and make the HEAD dangling to the new branch, only if the "git rm" step
succeeds), and document clearly that is the intended workflow for the new
feature to support.
But stepping back a bit, you would realize that the usefulness of the end
result of these existing "disjoint merges" does not come from the fact
that the side branch was initially a disjoint history from the main
branch. The usefulness of the end result comes solely from the fact that
we managed to merge such a side branch. If Paul started gitk by forking
Linus's git, adding gitk script, _without_ making the history disjoint,
the result of the merge would have been equally useful.
The only reason the early part of gitk's history is independent from git
is because Paul nor Linus did _not_ have any plan to merge these two
histories. Lack of foresight is not a crime, so it is perfectly fine if
you have to merge histories that started separately, but if you do plan to
merge the future, starting the branch as a disjoint history is a crime--it
does not help anybody.
Up to this point, I:
- described possible two workflows ("almost no common paths" and "mostly
common paths") that "checkout --orphan" _could_ support;
- explained why neither makes sene; and
- explained why your implementation does not support either one well,
even if one or both of these workflows made sense.
Now, do not take the above as a personal criticism. The only thing the
above discussion may be showing could be that your description was not
clear enough to tell me that the workflow you had in mind to support was a
third one, different from the above two, and that your implementation may
support that untold workflow very well. Take the above as an illustration
of how you present the workflow your new feature intends to support, and
how you choose your design and implementation to support that workflow
well.
So let's hear it. Until we clear the design issues, there is not much
point in talking about coding styles and implementation.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-13 7:53 ` Junio C Hamano
@ 2010-03-13 9:10 ` Junio C Hamano
2010-03-14 21:57 ` Erick Mattos
2010-03-13 9:33 ` Jakub Narebski
2010-03-14 20:46 ` Erick Mattos
2 siblings, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2010-03-13 9:10 UTC (permalink / raw)
To: Erick Mattos; +Cc: git
Junio C Hamano <gitster@pobox.com> writes:
> As I already said, I do not think "mostly common paths" case should be
> encouraged to begin with. As far as I know (and you can guess by now that
> I know reasonably well about git), you do not gain anything by not having
> the ancestry link between '?' and 'B', except that it would make conflict
> resolution at '*' extremely difficult. There is only downside without any
> upside in "mostly common paths" disjoint merge.
There is one case "mostly common paths" disjoint history can be useful.
Imagine you have a hitherto proprietary software project and want to go
open source. Perhaps your intention is to have an open source version and
an enhanced commercial version. The project contains some third-party
vendor software outside your control, and you have replaced them with open
source equivalents or disabled features that depend on them.
Your history may look like this:
o---o---A oss-base
/
---o---o---o---o master
where master is the primary version you will continue shipping to your
paying customers, with proprietary third-party components and features
that depend on them. Commits on oss-base were your work to prepare the
tree into a releasable shape, removing these proprietary stuff along with
some features.
But you cannot publish oss-base (commit A) to the public. "git log" will
show all the history that leads to it, with all the third-party stuff you
do not have license to distribute in the source form. The older parts of
the history may even have site password at customer installation you have
committed by mistake and eradicated long time ago.
If you run this three command sequence (in this message, I am assuming
that you keep the index and the working tree files intact in an updated
implementation of --orphan, which is different from the suggestion to
support "no common paths" case I mentioned in the previous message):
$ git checkout --orphan oss oss-base
$ git checkout oss-base
$ git merge -s ours oss
you will get a history of this shape:
X oss
\
o---o---A---B oss-base
/
---o---o---o---o master
with commits X, A and B all recording an identical tree. The oss branch
(commit X) is now safe to publish.
Once you have done this, further you can:
$ git checkout master
$ git merge oss-base
which gives you a history of this shape:
X oss
\
o---o---A---B oss-base
/ \
---o---o---o---o---Y master
This merge Y has to be done carefully. It inherently has to be an evil
merge because oss-base wants to replace some proprietary stuff with open
source counterparts while you may want to keep using the proprietary ones
you have support contract for in your paying customer release you will
make from the master branch. So at Y, you will most likely be reverting
some work you did on oss-base branch since it forked from master.
After setting it up, this arrangement allows you to:
- accept changes from public, and/or build changes for public, to advance
"community version" on the oss branch on top of X;
- from time to time, merge oss to oss-base;
- from time to time, merge oss-base to master.
and the histories will continue like this:
X---C---C---C---C oss
\ \
o---o---A---B-----------* oss-base
/ \ \
---o---o---o---o---Y---P---P---*---P---P master
with community commits C (either contributed from the public or you
developed yourself and gave to the community) on oss branch, with
proprietary commits P that record your own proprietary work on master
branch. Note that oss-base branch is not used to produce nor record any
commit on its own---it is merely to ease the merging from oss and master
by providing X-B link to serve as a convenient common ancestor to make
later merges easier.
Note also that it would be the most convenient if you kept both the index
and the working tree intact, if "checkout --orphan" is to be used as an
ingredient for this workflow. It _might_ actually make sense not to make
the "git checkout --orphan" an independent feature that can be randomly
abused or misused, but package the three-command sequence to create the
A-B-X open triangle above into a separate command, i.e.
$ git branch --orphan oss
would create a new branch "oss" with its own root commit X that records
the same tree as the current HEAD A, and immediately merge X back into A
to produce B, again recording the same tree, and advance the current HEAD
to point at B, like so:
X oss
\
---o---A HEAD --> ---o---A---B HEAD
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-13 7:53 ` Junio C Hamano
2010-03-13 9:10 ` Junio C Hamano
@ 2010-03-13 9:33 ` Jakub Narebski
2010-03-13 9:42 ` Junio C Hamano
2010-03-14 21:57 ` Erick Mattos
2010-03-14 20:46 ` Erick Mattos
2 siblings, 2 replies; 17+ messages in thread
From: Jakub Narebski @ 2010-03-13 9:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Erick Mattos, git
Junio C Hamano <gitster@pobox.com> writes:
> Side note: The other two "disjoint" merges we have are also this kind
> of "no common paths" merge. Nobody who was involved in the branches
> that resulted in them prepared his branch with --orphan, by the way.
> They started out in independent repositories, because they were by
> definition independent projects and these were "cross project merges",
> as Linus put it.
Note that beside "disjoint" merges ("cross project merges"), of gitk,
git-gui, gitweb and (very early in git history) git mail tools, there
are also three "disjoint"/"unparented" branches: 'html', 'man' and
'todo'.
While 'todo' is totally unrelated, and if instead of starting in
separate repository it would be created using proposed feature, it
would be created with "no common paths" case.
BUT in the case of 'html' and 'man' branches I could see why current
implementation of _removing index and not removing files_ might be
advantageous. Remove index, create HTML and manpage version of
documentation, and add HTML (in 'html' branch) or manpages (in 'man'
branch)... probably shifting root, so it is not all in single
Documentation directory.
Just my 2 eurocents.
--
Jakub Narebski
Poland
ShadeHawk on #git
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-13 9:33 ` Jakub Narebski
@ 2010-03-13 9:42 ` Junio C Hamano
2010-03-14 21:57 ` Erick Mattos
1 sibling, 0 replies; 17+ messages in thread
From: Junio C Hamano @ 2010-03-13 9:42 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Junio C Hamano, Erick Mattos, git
Jakub Narebski <jnareb@gmail.com> writes:
> BUT in the case of 'html' and 'man' branches I could see why current
> implementation of _removing index and not removing files_ might be
> advantageous. Remove index, create HTML and manpage version of
> documentation, and add HTML (in 'html' branch) or manpages (in 'man'
> branch)... probably shifting root, so it is not all in single
> Documentation directory.
When you have some spare time, I'd recommend you to read dodoc.sh script
in the 'todo' branch. These preformatted documentation branches are
coming from their own repositories, very much on purpose.
> Just my 2 eurocents.
Already?
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-13 7:53 ` Junio C Hamano
2010-03-13 9:10 ` Junio C Hamano
2010-03-13 9:33 ` Jakub Narebski
@ 2010-03-14 20:46 ` Erick Mattos
2010-03-14 21:58 ` Erick Mattos
2 siblings, 1 reply; 17+ messages in thread
From: Erick Mattos @ 2010-03-14 20:46 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
Sorry for writing much again in reply.
2010/3/13 Junio C Hamano <gitster@pobox.com>:
> I was referring to this from the latest version:
>
> Sometimes it is necessary to start up a new development branch of code
> intended to be merged in the near future to existing branches but which
> actually does not relate to them.
That is one from some reasons to start a new empty, unparented,
unrelated, without ancestry branch. An example which is not
considered good enough by your opinion.
I am not trying because I don't feel myself good enough to convince
you of anything. But I will try to give you more examples at the end
of this reply.
To be more general the text could be:
Sometimes it is interesting to start an new unparented branch for new code.
> Let's give you an example of the depth of thought and clarity of
> description of the workflow I am expecting from anybody who claims "this
> is a useful feature to help _some_ workflows" by taking an example from
> git.git, because it is one project that both of us are familiar with and
> there is a readily available example in it. It has disjoint merges from
> gitk, gitweb and git-gui. The history up to such a merge 5569bf9 (Do a
> cross-project merge of Paul Mackerras' gitk visualizer, 2005-06-22) looks
> like this:
>
> A---o---?---o---o---X---* linus
> . /
> B---o---o---Y gitk
>
> Note that with this merge '*', two histories merged did not share any
> paths at commit X and Y.
>
> Did you have this kind of "no common paths" merge in mind when you wrote
> the proposed commit log message? IOW, if we pretend that Paul started his
> gitk work and he "intended to be merged to Linus's branch but which does
> not relate to it", would that be a good example of what you are trying to
> achieve?
I am not trying to achieve anything. I am already doing what I want
myself. I am just trying to let people achieve what they want without
a hack.
I think you haven't checked those, so PLEASE:
Git SCM Wiki:
http://git.wiki.kernel.org/index.php/GitTips#How_to_create_a_new_branch_that_has_no_ancestor
Git Book:
http://book.git-scm.com/5_creating_new_empty_branches.html
Anyway your example is a good one if you are the one which controls
the branch flows and know you will be doing the merge eventually. It
fits then on my explained case.
> Side note: The other two "disjoint" merges we have are also this kind
> of "no common paths" merge. Nobody who was involved in the branches
> that resulted in them prepared his branch with --orphan, by the way.
> They started out in independent repositories, because they were by
> definition independent projects and these were "cross project merges",
> as Linus put it.
They were not foreseeing the future but and if they were the only
developer and could project what they would need?
> I'd grant you that we could say that these histories did not start in the
> same repository using "checkout --orphan" because it was not available.
That's it!
> Did you have this kind of "mostly common paths" merge in mind when you
> wrote the proposed commit log message? IOW, if "checkout --orphan" were
> available to Paul, would you have recommended him to use it, add his gitk
> script to the tree, and start his history at commit B which he started
> from commit '?' from Linus's history? But you are again nuking the index
> so Paul would have had to add the files back with "git add", while being
> careful not to add untracked files, or run "git read-tree ?" to populate
> the index back to the original state.
He would use it easily. No difficulty at all.
I think the problem here is a matter of opinion: you think removal
should be automatically followed. Like 'git checkout -ob NEW_BRANCH'
followed by 'git clean -df'.
I don't. I think the user can do it or not by himself.
I am not trying to convince you. You rule.
>> I am not wiping the tree by default because I am not deciding for
>> people if they are going to use anything from it as a template (even
>> the directory structure only).
>>
>> I am not trying to make decisions for the user. I think he would be
>> capable of deciding it himself. That is my way of thinking so I
>> normally prefer to advice, alert, inform not to impose.
>
> You may think that you are supporting both, but in reality, you are
> supporting neither by making both cases equally inconvenient. The only
> thing you are gaining is a way to weasel out of issues experienced by the
> users by saying "I didn't remove anything from the working tree, so if you
> want to add them, you can, it is up to you", while ignoring the issue that
> (1) if the user wants "no common paths", cleaning working tree becomes
> cumbersome and error prone, and (2) if the user wants "mostly common
> paths", adding back to the index becomes cumbersome and error prone.
Really?
(1) git clean -df
(2) git add WHATEVER
It does not look cumbersome or error prone to me. :-1
> As I already said, I do not think "mostly common paths" case should be
> encouraged to begin with. As far as I know (and you can guess by now that
> I know reasonably well about git), you do not gain anything by not having
> the ancestry link between '?' and 'B', except that it would make conflict
> resolution at '*' extremely difficult. There is only downside without any
> upside in "mostly common paths" disjoint merge.
I do not have to guess: you are the man. I know you know everything about git.
First of all, I do respect you a lot. Not only by all your knowledge,
or your commitment, or by Git's creator confidence upon you.
But more than all because of the hard work you have been giving to
this project. Time and effort are very rare commodities to be wasted
these days.
The problem here is not what you know. It is not about you. It is
about what Git should become to ease user's life. It is to pay
attention to common as well as to uncommon needs.
The first reason for Git was to be the Linux kernel SCM. That was
already achieved perfectly.
Git should freeze then?
Being good is not a reason for not becoming better. I am trying to
make it better by filling a gap. I have started my contributions by
filling needs I had which were not fulfilled.
We are not encouraging anything. We are just letting people do what
they want to. Having an empty new branch to start with is something
some people want to do. Please do the google search I told you
before: "new empty branch git".
And finally, remember, merge will be easy because unparented branch is
mainly for unrelated work. User will solve problems if he wants any
exotic stuff.
> That leaves only the "almost no common paths" case. As we have already
> seen in git project, the end result is indeed very useful. It used to be
> that people had to download and use gitk independently before Linus's
> cross project merge, but after the merge, the project gives the core git
> and gitk comes with it. So you could argue that "checkout --orphan" would
> become useful if you adjusted the code like I suggested in my review
> comments (run an equivalent of "git rm" without "-f" from the top-level
> and make the HEAD dangling to the new branch, only if the "git rm" step
> succeeds), and document clearly that is the intended workflow for the new
> feature to support.
The end result will be very helpful indeed.
You are thinking as a maintainer of a huge project with a lot of
merging. This new function is indeed not very useful to you. But it
is to people running different work flows. Most of all when they are
running small projects and when they have full control of the
repository without a lot of clones widespread.
> Now, do not take the above as a personal criticism. The only thing the
> above discussion may be showing could be that your description was not
> clear enough to tell me that the workflow you had in mind to support was a
> third one, different from the above two, and that your implementation may
> support that untold workflow very well. Take the above as an illustration
> of how you present the workflow your new feature intends to support, and
> how you choose your design and implementation to support that workflow
> well.
I am not taking anything personally. I already know your way of working.
But I have descripted what I wanted to. When I showed the
debianization case to picture it, that was something I did. Even
though you don't think is a good way to do it.
This new function satisfies a lot of needs because an empty new branch
is needed some times and the way to get it nowadays is too unnatural.
That is why you could figure out some uses yourself even with exceptions.
> So let's hear it. Until we clear the design issues, there is not much
> point in talking about coding styles and implementation.
As I see what you need is some examples of how useful this new option
will be. I am going to show some but take in account that I am
inventing those. Trying to conceive uses which you would think is
useful. And that I know I would probably fail.
I know what for I had hacked to create orphan branches myself. But
those personal experiences will not be good examples to you.
But I can foresee there will be a lot of uses even if I can not
conceive them all right now.
All said, now let's exemplify, starting with the cases I told you in
my last email:
* Do some parallel development:
Recreating the wheel: unix shell softwares.
$ vim grep.c, ...
$ git add .
$ git commit -m grep
$ git checkout -ob sed
$ vim sed.c, ...
$ git add .
$ git commit -m sed
...
* Working under unrelated parts before merging the start point of the
new software.
- You start with branch A with sources to draw math functions.
- Then you start orphan B with sources to calculate math curves, their
areas, ...
- Later you organize them and merge the start point of the new software.
- Now you are ready to publish and to call for community help.
$ vim draw.c, ...
$ git add .
$ git commit -m 'Drawing implementation'
$ git checkout -ob math
$ vim math.c, ...
$ git add .
$ git commit -m 'Complicated Math implementation'
...
* Recreate history. It is not published yet so it is not being widely
cloned and people just want to have a good repository before
publishing;
You start A--B--C--D then you realize that A and B is not necessary
and that you should have started directly by C.
$ git checkout C
$ git checkout -ob GOOD
$ git add .
$ git commit -C C --reset-author
$ git cherry-pick D
$ git branch -D OLD_BRANCH
* Adding files which is not meant to be part of anything in a temporary fashion;
Adding notes to yourself.
$ git checkout -ob notes
$ git clean -df
$ vim note
$ git add .
$ git commit -m Notes
* Have different approaches starting different sources from those
software versions until you
find out the best one.
You are going to start a software which you don't know if a good
algorithm would be to do some factorial by recursion or not.
$ vim recursive.c
$ git add .
$ git commit -m recursive
$ git checkout -ob normal
$ vim straight.c
$ git add .
$ git commit -m normal
This email is being made in chronological order. I know you have
already sent another one but I have chosen to reply this one before
seeing the new one. I will reply that one after sending this so
please forgive me if I am talking about something you later
reconsidered.
To finish this email I am going to make a 'cheat sheet' to show the
new functionality:
Branch_A
|
You realize that you need a new empty branch.
|
Is the work tree clean?
| |
Yes No
| |
git clean -ob Branch_B -------Undo?-------Was the work tree clean before?
|
| |
| Yes No
|
| |
|
| git add .
|
| git commit -m temp
|
| |
|
+--------+ git checkout Branch_A -f
|
|
|
git merge --squash Branch_B
Do you want to use anything from the work tree? |
| |
git reset
Yes No
git branch -D Branch_B
| |
| git clean -df
| |
Change the work tree the way you want it to be.
|
git add .
git commit
|
That is it!
Thank you very much for the patience to get till here. I know it is
hard reading much but I realize that all this subject have to be well
explained otherwise I will be repeating the same in a series of
emails. I have already did repeat on this one. ;-)
I hope all this effort will be worth-full. Thanks again for your time!
Regards
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-13 9:10 ` Junio C Hamano
@ 2010-03-14 21:57 ` Erick Mattos
2010-03-15 2:56 ` Junio C Hamano
0 siblings, 1 reply; 17+ messages in thread
From: Erick Mattos @ 2010-03-14 21:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi
As I see you have found a very good example under your common work
flow. Nice. :-)
Regards
2010/3/13 Junio C Hamano <gitster@pobox.com>:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> As I already said, I do not think "mostly common paths" case should be
>> encouraged to begin with. As far as I know (and you can guess by now that
>> I know reasonably well about git), you do not gain anything by not having
>> the ancestry link between '?' and 'B', except that it would make conflict
>> resolution at '*' extremely difficult. There is only downside without any
>> upside in "mostly common paths" disjoint merge.
>
> There is one case "mostly common paths" disjoint history can be useful.
>
> Imagine you have a hitherto proprietary software project and want to go
> open source. Perhaps your intention is to have an open source version and
> an enhanced commercial version. The project contains some third-party
> vendor software outside your control, and you have replaced them with open
> source equivalents or disabled features that depend on them.
>
> Your history may look like this:
>
> o---o---A oss-base
> /
> ---o---o---o---o master
>
> where master is the primary version you will continue shipping to your
> paying customers, with proprietary third-party components and features
> that depend on them. Commits on oss-base were your work to prepare the
> tree into a releasable shape, removing these proprietary stuff along with
> some features.
>
> But you cannot publish oss-base (commit A) to the public. "git log" will
> show all the history that leads to it, with all the third-party stuff you
> do not have license to distribute in the source form. The older parts of
> the history may even have site password at customer installation you have
> committed by mistake and eradicated long time ago.
>
> If you run this three command sequence (in this message, I am assuming
> that you keep the index and the working tree files intact in an updated
> implementation of --orphan, which is different from the suggestion to
> support "no common paths" case I mentioned in the previous message):
>
> $ git checkout --orphan oss oss-base
> $ git checkout oss-base
> $ git merge -s ours oss
>
> you will get a history of this shape:
>
> X oss
> \
> o---o---A---B oss-base
> /
> ---o---o---o---o master
>
> with commits X, A and B all recording an identical tree. The oss branch
> (commit X) is now safe to publish.
>
> Once you have done this, further you can:
>
> $ git checkout master
> $ git merge oss-base
>
> which gives you a history of this shape:
>
> X oss
> \
> o---o---A---B oss-base
> / \
> ---o---o---o---o---Y master
>
> This merge Y has to be done carefully. It inherently has to be an evil
> merge because oss-base wants to replace some proprietary stuff with open
> source counterparts while you may want to keep using the proprietary ones
> you have support contract for in your paying customer release you will
> make from the master branch. So at Y, you will most likely be reverting
> some work you did on oss-base branch since it forked from master.
>
> After setting it up, this arrangement allows you to:
>
> - accept changes from public, and/or build changes for public, to advance
> "community version" on the oss branch on top of X;
>
> - from time to time, merge oss to oss-base;
>
> - from time to time, merge oss-base to master.
>
> and the histories will continue like this:
>
> X---C---C---C---C oss
> \ \
> o---o---A---B-----------* oss-base
> / \ \
> ---o---o---o---o---Y---P---P---*---P---P master
>
> with community commits C (either contributed from the public or you
> developed yourself and gave to the community) on oss branch, with
> proprietary commits P that record your own proprietary work on master
> branch. Note that oss-base branch is not used to produce nor record any
> commit on its own---it is merely to ease the merging from oss and master
> by providing X-B link to serve as a convenient common ancestor to make
> later merges easier.
>
> Note also that it would be the most convenient if you kept both the index
> and the working tree intact, if "checkout --orphan" is to be used as an
> ingredient for this workflow. It _might_ actually make sense not to make
> the "git checkout --orphan" an independent feature that can be randomly
> abused or misused, but package the three-command sequence to create the
> A-B-X open triangle above into a separate command, i.e.
>
> $ git branch --orphan oss
>
> would create a new branch "oss" with its own root commit X that records
> the same tree as the current HEAD A, and immediately merge X back into A
> to produce B, again recording the same tree, and advance the current HEAD
> to point at B, like so:
>
> X oss
> \
> ---o---A HEAD --> ---o---A---B HEAD
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-13 9:33 ` Jakub Narebski
2010-03-13 9:42 ` Junio C Hamano
@ 2010-03-14 21:57 ` Erick Mattos
2010-03-15 2:06 ` Junio C Hamano
1 sibling, 1 reply; 17+ messages in thread
From: Erick Mattos @ 2010-03-14 21:57 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Junio C Hamano, git
Hi,
You got it right. HTML and man branches are really very good examples.
Regards
2010/3/13 Jakub Narebski <jnareb@gmail.com>:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> Side note: The other two "disjoint" merges we have are also this kind
>> of "no common paths" merge. Nobody who was involved in the branches
>> that resulted in them prepared his branch with --orphan, by the way.
>> They started out in independent repositories, because they were by
>> definition independent projects and these were "cross project merges",
>> as Linus put it.
>
> Note that beside "disjoint" merges ("cross project merges"), of gitk,
> git-gui, gitweb and (very early in git history) git mail tools, there
> are also three "disjoint"/"unparented" branches: 'html', 'man' and
> 'todo'.
>
> While 'todo' is totally unrelated, and if instead of starting in
> separate repository it would be created using proposed feature, it
> would be created with "no common paths" case.
>
> BUT in the case of 'html' and 'man' branches I could see why current
> implementation of _removing index and not removing files_ might be
> advantageous. Remove index, create HTML and manpage version of
> documentation, and add HTML (in 'html' branch) or manpages (in 'man'
> branch)... probably shifting root, so it is not all in single
> Documentation directory.
>
> Just my 2 eurocents.
>
> --
> Jakub Narebski
> Poland
> ShadeHawk on #git
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-14 20:46 ` Erick Mattos
@ 2010-03-14 21:58 ` Erick Mattos
0 siblings, 0 replies; 17+ messages in thread
From: Erick Mattos @ 2010-03-14 21:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Resending orphan branch 'cheat sheet' again. Gmail screwed it in
previous email. See this using a fixed font:
Branch_A
|
You realize that you need a new empty branch.
|
Is the work tree clean?
| |
Yes No
| |
git clean -ob Branch_B -------Undo?-------Was the work tree clean before?
| | |
| Yes No
| | |
| | git add .
| | git commit -m temp
| | |
| +------+ git
checkout Branch_A -f
| |
| git merge
--squash Branch_B
Do you want to use anything from the work tree? |
| | git reset
Yes No git branch -D Branch_B
| |
| git clean -df
| |
Change the work tree the way you want it to be.
|
git add .
git commit
|
That is it!
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-14 21:57 ` Erick Mattos
@ 2010-03-15 2:06 ` Junio C Hamano
2010-03-16 18:17 ` Erick Mattos
0 siblings, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2010-03-15 2:06 UTC (permalink / raw)
To: Erick Mattos; +Cc: Jakub Narebski, Junio C Hamano, git
Erick Mattos <erick.mattos@gmail.com> writes:
> You got it right. HTML and man branches are really very good examples.
Not at all. You fundamentally do not want to have checkout of these
branches in the same place as you checkout and work in the main branches.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-14 21:57 ` Erick Mattos
@ 2010-03-15 2:56 ` Junio C Hamano
2010-03-16 18:18 ` Erick Mattos
0 siblings, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2010-03-15 2:56 UTC (permalink / raw)
To: Erick Mattos; +Cc: git
Erick Mattos <erick.mattos@gmail.com> writes:
> As I see you have found a very good example under your common work
> flow. Nice. :-)
And realize that it does not help that you nuke the index while leaving
the working tree files.
I do not think you got my point at all, so let's try a different phrasing.
I've already spent too much time on this thread, so this will be the last
message from me on this topic for now. Hopefully you will understand this
time.
I saw two potential workflows that could be useful:
(1) "mostly common paths" workflow;
(2) "no common paths" workflow;
Suppose you are on master branch and creating an orphan branch. The first
command is this for either case:
$ git checkout -b orphan --orphan master
The next action the user needs to make before starting to work on
preparing for the first commit on that unborn branch is different
depending on how "checkout --orphan" behaves. Let's take two extreme:
- If it kept both the index and the working tree, the user does not need
to do anything for "mostly common paths", while the user only needs
"git rm -rf ." for "no common paths".
- If it nuked both the index and the working tree, the user does not need
to do anything else for "no common paths", while the user only needs
"git checkout master ." for "mostly common paths".
Notice that in either of these two implementations, one camp does not need
to do anything other than the checkout itself and can immediately start
working to prepare for the first commit. The other camp needs to do an
extra thing, but that is limited to one single, simple Porcelain command.
There is no "did you have untracked files? then do this" complications.
If you nuked the index but didn't touch the working tree, which is what
you did, everybody is forced to do extra things, and recovery is not as
simple as the above two extremes.
For people who wanted "mostly common paths", "git add ." would add paths
that were originally shown in the untracked list, so it cannot be used;
they need to either choose the necessary paths and run a series of random
"git add WHATEVER", or "git add ." and untrack unwanted paths with a
series of random "git rm --cached WHATEVER" after that.
For people who wanted "no common paths", "git rm" wouldn't work (as the
index is nuked), and "git clean" will lose originally untracked files;
again they need to give a series of random "git clean WHATEVER".
Either way, everbody suffers, and recovery won't be a single simple
command anymore.
The conclusion to draw is that, among four possible implementations ("keep
both", "remove both", "remove index but keep working tree", "keep index
but remove working tree"), the last two are clearly inferior compared to
the first two.
Between the first two, there are a few pros-and-cons.
- Obviously, if most people want "mostly common paths", then "keep both"
would be more helpful, and vice-versa.
- "keep both" would not need much safety, but "remove both" needs a
safety-valve implementation (you don't want to lose added changes in
the index, nor changes in the working tree yet to be added).
So I am inclined to say, unless "no common paths" is the majority of the
use case, "keep both" would be the design to pick.
I didn't see in your long mail any "third" workflow that would be helped
by your "remove index but keep working tree". All of them were either "no
common paths" or "mostly common paths". If you demonstrated that a
"third" workflow is the majority of the case, and that "remove index but
keep working tree" would be the most helpful for that "third" workflow,
then you might have made a case that "remove index but keep working tree"
is the right design to use. But I didn't see any workflow that wants a
working tree full of files that are nothing but untracked cruft.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-15 2:06 ` Junio C Hamano
@ 2010-03-16 18:17 ` Erick Mattos
0 siblings, 0 replies; 17+ messages in thread
From: Erick Mattos @ 2010-03-16 18:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jakub Narebski, git
2010/3/14 Junio C Hamano <gitster@pobox.com>:
> Erick Mattos <erick.mattos@gmail.com> writes:
>
>> You got it right. HTML and man branches are really very good examples.
>
> Not at all. You fundamentally do not want to have checkout of these
> branches in the same place as you checkout and work in the main branches.
It is unimportant the folder you will have them within.
It is a good example because they could be started or even kept
(merged only when needed) as an unrelated branch.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-15 2:56 ` Junio C Hamano
@ 2010-03-16 18:18 ` Erick Mattos
0 siblings, 0 replies; 17+ messages in thread
From: Erick Mattos @ 2010-03-16 18:18 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
2010/3/14 Junio C Hamano <gitster@pobox.com>:
> Erick Mattos <erick.mattos@gmail.com> writes:
>
>> As I see you have found a very good example under your common work
>> flow. Nice. :-)
>
> And realize that it does not help that you nuke the index while leaving
> the working tree files.
>
> I do not think you got my point at all, so let's try a different phrasing.
> I've already spent too much time on this thread, so this will be the last
> message from me on this topic for now. Hopefully you will understand this
> time.
>
> I saw two potential workflows that could be useful:
It is an evolution we are not talking about its usefulness anymore.
However it is not a matter of understanding too. :-) It is about opinion.
It is just that you do not like the actual behavior and I do.
But you rule and this is just a detail anyway so I will be sending a
new version in a few moments.
Regards
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] git checkout -b: unparent the new branch with -o
2010-03-12 7:40 ` Bert Wesarg
@ 2010-04-27 6:35 ` David Kågedal
0 siblings, 0 replies; 17+ messages in thread
From: David Kågedal @ 2010-04-27 6:35 UTC (permalink / raw)
To: git
Bert Wesarg <bert.wesarg@googlemail.com> writes:
> On Fri, Mar 12, 2010 at 07:53, Junio C Hamano <gitster@pobox.com> wrote:
>> Erick Mattos <erick.mattos@gmail.com> writes:
>>> + test "alpha" = "$(git branch | sed -n "/*/s/\* //p")" &&
>>
>> Don't read from "git branch" in scripts; use symbolic-ref on HEAD.
>
> I think what he wants is:
>
> git rev-parse --abbrev-ref HEAD
Aha! That's a command I've been looking for a number of times. Thanks a
lot for the tip.
--
David Kågedal
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2010-04-27 6:36 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-09 22:28 [PATCH v2] git checkout -b: unparent the new branch with -o Erick Mattos
2010-03-12 6:53 ` Junio C Hamano
2010-03-12 7:40 ` Bert Wesarg
2010-04-27 6:35 ` David Kågedal
2010-03-12 16:45 ` Erick Mattos
2010-03-13 7:53 ` Junio C Hamano
2010-03-13 9:10 ` Junio C Hamano
2010-03-14 21:57 ` Erick Mattos
2010-03-15 2:56 ` Junio C Hamano
2010-03-16 18:18 ` Erick Mattos
2010-03-13 9:33 ` Jakub Narebski
2010-03-13 9:42 ` Junio C Hamano
2010-03-14 21:57 ` Erick Mattos
2010-03-15 2:06 ` Junio C Hamano
2010-03-16 18:17 ` Erick Mattos
2010-03-14 20:46 ` Erick Mattos
2010-03-14 21:58 ` Erick Mattos
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).