All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jacob Abel <jacobabel@nullpo.dev>
To: git@vger.kernel.org
Cc: Jacob Abel <jacobabel@nullpo.dev>
Subject: [PATCH 3/4] worktree add: add --orphan flag
Date: Fri, 04 Nov 2022 01:03:20 +0000	[thread overview]
Message-ID: <20221104010242.11555-4-jacobabel@nullpo.dev> (raw)
In-Reply-To: <20221104010242.11555-1-jacobabel@nullpo.dev>

Adds support for creating an orphan branch when adding a new worktree.
This functionality is equivalent to git checkout's --orphan flag.

The original reason this feature was implemented was to allow a user
to initialise a new repository using solely the worktree oriented
workflow. Example usage included below.

$ GIT_DIR=".git" git init --bare
$ git worktree add --orphan master master/

Signed-off-by: Jacob Abel <jacobabel@nullpo.dev>
---
 Documentation/git-worktree.txt | 18 ++++++++-
 builtin/worktree.c             | 68 +++++++++++++++++++++++++---------
 2 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 4dd658012b..92bd75564f 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git worktree add' [-f] [--detach] [--checkout] [--lock [--reason <string>]]
-		   [[-b | -B] <new-branch>] <path> [<commit-ish>]
+		   [[-b | -B | --orphan] <new-branch>] <path> [<commit-ish>]
 'git worktree list' [-v | --porcelain [-z]]
 'git worktree lock' [--reason <string>] <worktree>
 'git worktree move' <worktree> <new-path>
@@ -95,6 +95,17 @@ exist, a new branch based on `HEAD` is automatically created as if
 `-b <branch>` was given.  If `<branch>` does exist, it will be checked out
 in the new worktree, if it's not checked out anywhere else, otherwise the
 command will refuse to create the worktree (unless `--force` is used).
++
+------------
+$ git worktree add --orphan <branch> <path> [<commit-ish>]
+------------
++
+Create a worktree containing an orphan branch named `<branch>` based
+on `<commit-ish>`. If `<commit-ish>` is not specified, the new orphan branch
+will be created based on `HEAD`.
++
+Note that unlike with `-b` or `-B`, this operation will succeed even if
+`<commit-ish>` is a branch that is currently checked out somewhere else.

 list::

@@ -222,6 +233,11 @@ This can also be set up as the default behaviour by using the
 	With `prune`, do not remove anything; just report what it would
 	remove.

+--orphan <new-branch>::
+	With `add`, create a new orphan branch named `<new-branch>` in the new
+	worktree based on `<commit-ish>`. If `<commit-ish>` is omitted, it
+	defaults to `HEAD`.
+
 --porcelain::
 	With `list`, output in an easy-to-parse format for scripts.
 	This format will remain stable across Git versions and regardless of user
diff --git a/builtin/worktree.c b/builtin/worktree.c
index d40f771848..70f319a6b5 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -17,7 +17,7 @@

 #define BUILTIN_WORKTREE_ADD_USAGE                                                        \
 	N_("git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n" \
-	   "                 [[-b | -B] <new-branch>] <path> [<commit-ish>]")
+	   "                 [[-b | -B | --orphan] <new-branch>] <path> [<commit-ish>]")
 #define BUILTIN_WORKTREE_LIST_USAGE \
 	N_("git worktree list [-v | --porcelain [-z]]")
 #define BUILTIN_WORKTREE_LOCK_USAGE \
@@ -90,6 +90,8 @@ struct add_opts {
 	int detach;
 	int quiet;
 	int checkout;
+	int implicit;
+	const char *orphan_branch;
 	const char *keep_locked;
 };

@@ -360,6 +362,8 @@ static int checkout_worktree(const struct add_opts *opts,
 	strvec_pushl(&cp.args, "checkout", "--no-recurse-submodules", NULL);
 	if (opts->quiet)
 		strvec_push(&cp.args, "--quiet");
+	if (opts->orphan_branch)
+		strvec_pushl(&cp.args, "--orphan", opts->orphan_branch, NULL);
 	strvec_pushv(&cp.env, child_env->v);
 	return run_command(&cp);
 }
@@ -393,7 +397,8 @@ static int add_worktree(const char *path, const char *refname,
 			die_if_checked_out(symref.buf, 0);
 	}
 	commit = lookup_commit_reference_by_name(refname);
-	if (!commit)
+
+	if (!commit && !opts->implicit)
 		die(_("invalid reference: %s"), refname);

 	name = worktree_basename(path, &len);
@@ -482,10 +487,10 @@ static int add_worktree(const char *path, const char *refname,
 	strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
 	cp.git_cmd = 1;

-	if (!is_branch)
+	if (!is_branch && commit) {
 		strvec_pushl(&cp.args, "update-ref", "HEAD",
 			     oid_to_hex(&commit->object.oid), NULL);
-	else {
+	} else {
 		strvec_pushl(&cp.args, "symbolic-ref", "HEAD",
 			     symref.buf, NULL);
 		if (opts->quiet)
@@ -516,7 +521,7 @@ static int add_worktree(const char *path, const char *refname,
 	 * Hook failure does not warrant worktree deletion, so run hook after
 	 * is_junk is cleared, but do return appropriate code when hook fails.
 	 */
-	if (!ret && opts->checkout) {
+	if (!ret && opts->checkout && !opts->orphan_branch) {
 		struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;

 		strvec_pushl(&opt.env, "GIT_DIR", "GIT_WORK_TREE", NULL);
@@ -608,33 +613,52 @@ static int add(int ac, const char **av, const char *prefix)
 	const char *opt_track = NULL;
 	const char *lock_reason = NULL;
 	int keep_locked = 0;
+
 	struct option options[] = {
-		OPT__FORCE(&opts.force,
-			   N_("checkout <branch> even if already checked out in other worktree"),
-			   PARSE_OPT_NOCOMPLETE),
+		OPT__FORCE(
+			&opts.force,
+			N_("checkout <branch> even if already checked out in other worktree"),
+			PARSE_OPT_NOCOMPLETE),
 		OPT_STRING('b', NULL, &new_branch, N_("branch"),
 			   N_("create a new branch")),
 		OPT_STRING('B', NULL, &new_branch_force, N_("branch"),
 			   N_("create or reset a branch")),
-		OPT_BOOL('d', "detach", &opts.detach, N_("detach HEAD at named commit")),
-		OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")),
-		OPT_BOOL(0, "lock", &keep_locked, N_("keep the new working tree locked")),
+		OPT_STRING(0, "orphan", &opts.orphan_branch, N_("branch"),
+			   N_("create a new unparented branch")),
+		OPT_BOOL('d', "detach", &opts.detach,
+			 N_("detach HEAD at named commit")),
+		OPT_BOOL(0, "checkout", &opts.checkout,
+			 N_("populate the new working tree")),
+		OPT_BOOL(0, "lock", &keep_locked,
+			 N_("keep the new working tree locked")),
 		OPT_STRING(0, "reason", &lock_reason, N_("string"),
 			   N_("reason for locking")),
 		OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
 		OPT_PASSTHRU(0, "track", &opt_track, NULL,
 			     N_("set up tracking mode (see git-branch(1))"),
 			     PARSE_OPT_NOARG | PARSE_OPT_OPTARG),
-		OPT_BOOL(0, "guess-remote", &guess_remote,
-			 N_("try to match the new branch name with a remote-tracking branch")),
+		OPT_BOOL(
+			0, "guess-remote", &guess_remote,
+			N_("try to match the new branch name with a remote-tracking branch")),
 		OPT_END()
 	};

 	memset(&opts, 0, sizeof(opts));
 	opts.checkout = 1;
 	ac = parse_options(ac, av, prefix, options, git_worktree_add_usage, 0);
-	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach");
+
+	opts.implicit = ac < 2;
+
+	if (!!opts.detach + !!new_branch + !!new_branch_force +
+		    !!opts.orphan_branch >
+	    1)
+		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
+		    "-b", "-B", "--orphan", "--detach");
+	if (opts.orphan_branch && opt_track)
+		die(_("'%s' cannot be used with '%s'"), "--orphan", "--track");
+	if (opts.orphan_branch && !opts.checkout)
+		die(_("'%s' cannot be used with '%s'"), "--orphan",
+		    "--no-checkout");
 	if (lock_reason && !keep_locked)
 		die(_("the option '%s' requires '%s'"), "--reason", "--lock");
 	if (lock_reason)
@@ -646,11 +670,16 @@ static int add(int ac, const char **av, const char *prefix)
 		usage_with_options(git_worktree_add_usage, options);

 	path = prefix_filename(prefix, av[0]);
-	branch = ac < 2 ? "HEAD" : av[1];
+	branch = opts.implicit ? "HEAD" : av[1];

 	if (!strcmp(branch, "-"))
 		branch = "@{-1}";

+	/*
+	 * From here on, new_branch will contain the branch to be checked out,
+	 * and new_branch_force and opts.orphan_branch will tell us which one of
+	 * -b/-B/--orphan is being used.
+	 */
 	if (new_branch_force) {
 		struct strbuf symref = STRBUF_INIT;

@@ -663,6 +692,11 @@ static int add(int ac, const char **av, const char *prefix)
 		strbuf_release(&symref);
 	}

+	if (opts.orphan_branch) {
+		new_branch = opts.orphan_branch;
+		opts.force = 1;
+	}
+
 	if (ac < 2 && !new_branch && !opts.detach) {
 		const char *s = dwim_branch(path, &new_branch);
 		if (s)
@@ -686,7 +720,7 @@ static int add(int ac, const char **av, const char *prefix)
 	if (!opts.quiet)
 		print_preparing_worktree_line(opts.detach, branch, new_branch, !!new_branch_force);

-	if (new_branch) {
+	if (new_branch && !opts.orphan_branch) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		cp.git_cmd = 1;
 		strvec_push(&cp.args, "branch");
--
2.37.4



  parent reply	other threads:[~2022-11-04  1:03 UTC|newest]

Thread overview: 129+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-04  1:02 [PATCH 0/4] worktree: Support `--orphan` when creating new worktrees Jacob Abel
2022-11-04  1:03 ` [PATCH 1/4] worktree add: Include -B in usage docs Jacob Abel
2022-11-04  3:05   ` Eric Sunshine
2022-11-04  4:24     ` Jacob Abel
2022-11-04  1:03 ` [PATCH 2/4] builtin/worktree.c: Update checkout_worktree() to use git-worktree Jacob Abel
2022-11-04  1:32   ` Ævar Arnfjörð Bjarmason
2022-11-04  3:58     ` Jacob Abel
2022-11-04 20:45     ` Taylor Blau
2022-11-04  1:03 ` Jacob Abel [this message]
2022-11-04  1:33   ` [PATCH 3/4] worktree add: add --orphan flag Ævar Arnfjörð Bjarmason
2022-11-04  4:11     ` Jacob Abel
2022-11-04  5:03   ` Eric Sunshine
2022-11-04 16:41     ` Jacob Abel
2022-11-10  4:13       ` Eric Sunshine
2022-11-10 21:21         ` Jacob Abel
2022-11-04  1:03 ` [PATCH 4/4] worktree add: Add unit tests for --orphan Jacob Abel
2022-11-04  1:37   ` Ævar Arnfjörð Bjarmason
2022-11-04  4:17     ` Jacob Abel
2022-11-04  4:33 ` [PATCH 0/4] worktree: Support `--orphan` when creating new worktrees Eric Sunshine
2022-11-04  4:47   ` Jacob Abel
2022-11-04  4:50   ` Jacob Abel
2022-11-04 21:34 ` [PATCH v2 0/2] " Jacob Abel
2022-11-04 21:34   ` [PATCH v2 1/2] worktree add: Include -B in usage docs Jacob Abel
2022-11-04 21:34   ` [PATCH v2 2/2] worktree add: add --orphan flag Jacob Abel
2022-11-10 23:32   ` [PATCH v3 0/2] worktree: Support `--orphan` when creating new worktrees Jacob Abel
2022-11-10 23:32     ` [PATCH v3 1/2] worktree add: Include -B in usage docs Jacob Abel
2022-11-10 23:32     ` [PATCH v3 2/2] worktree add: add --orphan flag Jacob Abel
2022-11-15 21:08       ` Ævar Arnfjörð Bjarmason
2022-11-15 21:29         ` Eric Sunshine
2022-11-15 22:35           ` Ævar Arnfjörð Bjarmason
2022-11-16  0:19             ` Eric Sunshine
2022-11-19  3:13               ` Jacob Abel
2022-11-19  3:09             ` Jacob Abel
2022-11-19 11:50               ` Ævar Arnfjörð Bjarmason
2022-11-19  1:44         ` Jacob Abel
2022-11-22  6:00           ` Eric Sunshine
2022-11-22 23:09             ` Jacob Abel
2022-11-15 22:09       ` Ævar Arnfjörð Bjarmason
2022-11-19  2:57         ` Jacob Abel
2022-11-19 11:50           ` Ævar Arnfjörð Bjarmason
2022-11-16  0:39     ` [PATCH v3 0/2] worktree: Support `--orphan` when creating new worktrees Eric Sunshine
2022-11-17 10:00       ` Ævar Arnfjörð Bjarmason
2022-11-19  3:47         ` Jacob Abel
2022-11-19 11:48           ` Ævar Arnfjörð Bjarmason
2022-11-22  5:16             ` Eric Sunshine
2022-11-22 23:26               ` Jacob Abel
2022-11-22 23:55                 ` Ævar Arnfjörð Bjarmason
2022-11-23  2:47                   ` Jacob Abel
2022-11-23  2:43                 ` Rubén Justo
2022-11-23  5:37                   ` Jacob Abel
2022-11-23  7:35                     ` Rubén Justo
2022-11-22 14:45           ` Phillip Wood
2022-11-23  4:21             ` Jacob Abel
2022-12-12  1:42     ` [PATCH v4 0/3] " Jacob Abel
2022-12-12  1:42       ` [PATCH v4 1/3] worktree add: Include -B in usage docs Jacob Abel
2022-12-12  1:42       ` [PATCH v4 2/3] worktree add: add --orphan flag Jacob Abel
2022-12-12  8:11         ` Ævar Arnfjörð Bjarmason
2022-12-12 14:55           ` Jacob Abel
2022-12-12 18:14             ` Ævar Arnfjörð Bjarmason
2022-12-12 22:39               ` Jacob Abel
2022-12-12  1:43       ` [PATCH v4 3/3] worktree add: Add hint to use --orphan when bad ref Jacob Abel
2022-12-12  8:35         ` Ævar Arnfjörð Bjarmason
2022-12-12 14:59           ` Jacob Abel
2022-12-12 18:16             ` Ævar Arnfjörð Bjarmason
2022-12-12 18:35               ` Eric Sunshine
2022-12-12 22:36                 ` Jacob Abel
2022-12-12 22:38               ` Jacob Abel
2022-12-20  2:37       ` [PATCH v5 0/4] worktree: Support `--orphan` when creating new worktrees Jacob Abel
2022-12-20  2:37         ` [PATCH v5 1/4] worktree add: Include -B in usage docs Jacob Abel
2022-12-20  3:42           ` Junio C Hamano
2022-12-20 23:24             ` Jacob Abel
2022-12-20  2:37         ` [PATCH v5 2/4] worktree add: refactor opt exclusion tests Jacob Abel
2022-12-20  4:00           ` Junio C Hamano
2022-12-20 23:29             ` Jacob Abel
2022-12-20  2:38         ` [PATCH v5 3/4] worktree add: add --orphan flag Jacob Abel
2022-12-20  4:19           ` Junio C Hamano
2022-12-21  0:17             ` Jacob Abel
2022-12-20  2:38         ` [PATCH v5 4/4] worktree add: Add hint to use --orphan when bad ref Jacob Abel
2022-12-20  6:18           ` Junio C Hamano
2022-12-21  0:42             ` Jacob Abel
2022-12-28  6:16         ` [PATCH v6 0/4] worktree: Support `--orphan` when creating new worktrees Jacob Abel
2022-12-28  6:16           ` [PATCH v6 1/4] worktree add: include -B in usage docs Jacob Abel
2022-12-28  6:16           ` [PATCH v6 2/4] worktree add: refactor opt exclusion tests Jacob Abel
2022-12-28 12:54             ` Junio C Hamano
2022-12-29  6:51               ` Jacob Abel
2022-12-29 10:07                 ` Junio C Hamano
2022-12-29 20:48                   ` Jacob Abel
2023-01-06  6:31                   ` Jacob Abel
2023-01-06 12:34                     ` Junio C Hamano
2023-01-07  4:45                       ` Jacob Abel
2022-12-28  6:17           ` [PATCH v6 3/4] worktree add: add --orphan flag Jacob Abel
2022-12-28  6:17           ` [PATCH v6 4/4] worktree add: add hint to direct users towards --orphan Jacob Abel
2023-01-06 14:19             ` Phillip Wood
2022-12-28  8:01           ` [PATCH v6 0/4] worktree: Support `--orphan` when creating new worktrees Ævar Arnfjörð Bjarmason
2022-12-29  6:38             ` Jacob Abel
2022-12-29 10:42               ` Ævar Arnfjörð Bjarmason
2022-12-29 21:22                 ` Jacob Abel
2023-01-07  4:58           ` [PATCH v7 " Jacob Abel
2023-01-07  4:59             ` [PATCH v7 1/4] worktree add: include -B in usage docs Jacob Abel
2023-01-07  4:59             ` [PATCH v7 2/4] worktree add: refactor opt exclusion tests Jacob Abel
2023-01-08  7:13               ` Junio C Hamano
2023-01-08 15:08                 ` Jacob Abel
2023-01-07  4:59             ` [PATCH v7 3/4] worktree add: add --orphan flag Jacob Abel
2023-01-07  4:59             ` [PATCH v7 4/4] worktree add: add hint to direct users towards --orphan Jacob Abel
2023-01-09 12:26             ` [PATCH v7 0/4] worktree: Support `--orphan` when creating new worktrees Ævar Arnfjörð Bjarmason
2023-01-09 17:11               ` Jacob Abel
2023-01-09 17:21                 ` Ævar Arnfjörð Bjarmason
2023-01-09 17:26                   ` Jacob Abel
2023-01-09 17:32             ` [PATCH v8 " Jacob Abel
2023-01-09 17:32               ` [PATCH v8 1/4] worktree add: include -B in usage docs Jacob Abel
2023-01-09 17:33               ` [PATCH v8 2/4] worktree add: refactor opt exclusion tests Jacob Abel
2023-01-09 17:33               ` [PATCH v8 3/4] worktree add: add --orphan flag Jacob Abel
2023-01-13 10:20                 ` Phillip Wood
2023-01-13 17:32                   ` Junio C Hamano
2023-01-14 22:47                   ` Jacob Abel
2023-01-15  3:09                     ` Junio C Hamano
2023-01-15  3:41                       ` rsbecker
2023-01-15  3:49                         ` Junio C Hamano
2023-01-18 22:46                           ` 'Jacob Abel'
2023-01-18 22:18                       ` Jacob Abel
2023-01-19 15:32                         ` Ævar Arnfjörð Bjarmason
2023-01-19 16:32                           ` Junio C Hamano
2023-01-16 10:47                     ` Phillip Wood
2023-01-18 22:40                       ` Jacob Abel
2023-01-19 16:18                         ` Phillip Wood
2023-01-19 22:20                           ` Jacob Abel
2023-01-09 17:33               ` [PATCH v8 4/4] worktree add: add hint to direct users towards --orphan Jacob Abel
2023-01-09 19:20               ` [PATCH v8 0/4] worktree: Support `--orphan` when creating new worktrees Ævar Arnfjörð Bjarmason
2023-01-13 17:34                 ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221104010242.11555-4-jacobabel@nullpo.dev \
    --to=jacobabel@nullpo.dev \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.