git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] git checkout: create unparented branch by --orphan
@ 2010-03-18 16:09 Erick Mattos
  2010-03-20 15:13 ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: Erick Mattos @ 2010-03-18 16:09 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Erick Mattos

Similar to -b, --orphan creates a new branch, but it starts without any
commit.  After running "git checkout --orphan newbranch", you are on a
new branch "newbranch", and the first commit you create from this state
will start a new history without any ancestry.

"git checkout --orphan" keeps the index and the working tree files
intact in order to make it convenient for creating a new history whose
trees resemble the ones from the original branch.

When creating a branch whose trees have no resemblance to the ones from
the original branch, it may be easier to start work on the new branch by
untracking and removing all working tree files that came from the
original branch, by running a 'git rm -rf .' immediately after running
"checkout --orphan".

Signed-off-by: Erick Mattos <erick.mattos@gmail.com>
---

Complete rewrite of --orphan functionality to fit it in the new design goals
set by Junio.  Now --orphan is not anymore an option of -b.  It is an
alternative to it.

Junio:  I ask you to reconsider only the giving of the "short-and-sweet" -o
from beginning because of the new design.

As it is now an alternative to -b, doing similar stuff, I think it will be nice
if they look similar too.  So the it will be [[-b|-o] <new_branch>] not
[[-b|--orphan] <new_branch>].

Please ignore it if you can preview future options to checkout that could take
the rest of the 21 remaining letters and 6 digits.

Regards

 Documentation/git-checkout.txt |   21 +++++++++++++++-
 builtin/checkout.c             |   19 +++++++++++++-
 t/t2017-checkout-orphan.sh     |   53 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+), 3 deletions(-)
 create mode 100755 t/t2017-checkout-orphan.sh

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 37c1810..18df834 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git checkout' [-q] [-f] [-m] [<branch>]
-'git checkout' [-q] [-f] [-m] [-b <new_branch>] [<start_point>]
+'git checkout' [-q] [-f] [-m] [[-b|--orphan] <new_branch>] [<start_point>]
 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
 'git checkout' --patch [<tree-ish>] [--] [<paths>...]
 
@@ -20,6 +20,19 @@ When <paths> are not given, this command switches branches by
 updating the index, working tree, and HEAD to reflect the specified
 branch.
 
+When you use "--orphan", a new unparented branch is created having the
+index and the working tree intact.  This allows you to start a new
+history that records set of paths similar to that of the start-point
+commit, which is useful when you want to keep different branches for
+different audiences you are working to like when you have an open source
+and commercial versions of a software, for example.
+
+If you want to start a disconnected history that records set of paths
+totally different from the original branch, you may want to first clear
+the index and the working tree, by running "git rm -rf ." from the
+top-level of the working tree, before preparing your files (by copying
+from elsewhere, extracting a tarball, etc.) in the working tree.
+
 If `-b` is given, a new branch is created and checked out, as if
 linkgit:git-branch[1] were called; in this case you can
 use the --track or --no-track options, which will be passed to `git
@@ -63,6 +76,12 @@ entries; instead, unmerged entries are ignored.
 	When checking out paths from the index, check out stage #2
 	('ours') or #3 ('theirs') for unmerged paths.
 
+--orphan::
+	Create a new branch named <new_branch>, unparented to any other
+	branch.  The new branch you switch to does not have any commit
+	and after the first one it will become the root of a new history
+	completely unconnected from all the other branches.
+
 -b::
 	Create a new branch named <new_branch> and start it at
 	<start_point>; see linkgit:git-branch[1] for details.
diff --git a/builtin/checkout.c b/builtin/checkout.c
index acefaaf..9e0af6a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -33,6 +33,7 @@ struct checkout_opts {
 	int writeout_error;
 
 	const char *new_branch;
+	const char *new_orphan_branch;
 	int new_branch_log;
 	enum branch_track track;
 };
@@ -491,8 +492,15 @@ 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_orphan_branch) {
+			unsigned char rev[20];
+			int flag;
+			if (old->path != resolve_ref("HEAD", rev, 0, &flag))
+				cmd_checkout(1, &old->name, NULL);
+		}
+		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);
 	}
@@ -629,6 +637,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_STRING(0, "orphan", &opts.new_orphan_branch, "new branch", "new unparented branch"),
 		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 +686,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		opts.new_branch = argv0 + 1;
 	}
 
+	if (opts.new_orphan_branch) {
+		if (opts.new_branch)
+			die("--orphan and -b are mutually exclusive");
+		opts.new_branch = opts.new_orphan_branch;
+	}
+
 	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..e6d88b1
--- /dev/null
+++ b/t/t2017-checkout-orphan.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Erick Mattos
+#
+
+test_description='git checkout --orphan
+
+Main Tests for --orphan 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_tick &&
+	echo "State 1" >>"$TEST_FILE" &&
+	git add "$TEST_FILE" &&
+	git commit -m "Second Commit"
+'
+
+test_expect_success '--orphan creates a new orphan branch from HEAD' '
+	git checkout --orphan alpha &&
+	test_must_fail PAGER= git log >/dev/null 2>/dev/null &&
+	test "alpha" = "$(git symbolic-ref HEAD | sed "s,.*/,,")" &&
+	test_tick &&
+	git commit -m "Third Commit" &&
+	test 0 -eq $(git cat-file -p HEAD | grep "^parent" | wc -l) &&
+	git cat-file -p master | grep "^tree" >base &&
+	git cat-file -p HEAD | grep "^tree" >actual &&
+	test_cmp base actual
+'
+
+test_expect_success '--orphan creates a new orphan branch from <start_point>' '
+	git checkout master &&
+	git checkout --orphan beta master^ &&
+	test_must_fail PAGER= git log >/dev/null 2>/dev/null &&
+	test "beta" = "$(git symbolic-ref HEAD | sed "s,.*/,,")" &&
+	test_tick &&
+	git commit -m "Fourth Commit" &&
+	test 0 -eq $(git cat-file -p HEAD | grep "^parent" | wc -l) &&
+	git cat-file -p master^ | grep "^tree" >base &&
+	git cat-file -p HEAD | grep "^tree" >actual &&
+	test_cmp base actual
+'
+
+test_expect_success '--orphan must be rejected with -b' '
+	test_must_fail git checkout --orphan new -b newer
+'
+
+test_done
-- 
1.7.0.2.280.g460a6

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-03-20 21:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-18 16:09 [PATCH] git checkout: create unparented branch by --orphan Erick Mattos
2010-03-20 15:13 ` Junio C Hamano
2010-03-20 19:06   ` Erick Mattos
2010-03-20 20:30     ` Junio C Hamano
2010-03-20 20:36       ` Erick Mattos
2010-03-20 20:54         ` Junio C Hamano
2010-03-20 21:37           ` 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).