From: Glen Choo <chooglen@google.com>
To: git@vger.kernel.org
Cc: Jonathan Tan <jonathantanmy@google.com>,
Josh Steadmon <steadmon@google.com>,
Emily Shaffer <emilyshaffer@google.com>,
Glen Choo <chooglen@google.com>
Subject: [PATCH 3/4] branch: add --dry-run option to branch
Date: Mon, 22 Nov 2021 14:32:51 -0800 [thread overview]
Message-ID: <20211122223252.19922-4-chooglen@google.com> (raw)
In-Reply-To: <20211122223252.19922-1-chooglen@google.com>
When running "git branch --recurse-submodules topic", it would be useful
to know whether or not 'topic' is a valid branch for all repositories.
Currently there is no way to test this without actually creating the
branch.
Add a --dry-run option to branch creation that can check whether or not
a branch name and start point would be valid for a repository without
creating a branch. Refactor cmd_branch() to make the chosen action more
obvious.
Incidentally, fix an incorrect usage string that combined the 'list'
usage of git branch (-l) with the 'create' usage; this string has been
incorrect since its inception, a8dfd5eac4 (Make builtin-branch.c use
parse_options., 2007-10-07).
Signed-off-by: Glen Choo <chooglen@google.com>
---
The --dry-run option is motivated mainly by --recurse-submodules. To my
knowledge, there isn't a strong existing demand, but this might be
mildly useful to some users.
Documentation/git-branch.txt | 8 ++++++-
branch.c | 6 ++---
branch.h | 22 ++++++++++++++++++
builtin/branch.c | 44 ++++++++++++++++++++++++++----------
t/t3200-branch.sh | 13 +++++++++++
5 files changed, 77 insertions(+), 16 deletions(-)
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 5449767121..8cdc33c097 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -16,7 +16,7 @@ SYNOPSIS
[--points-at <object>] [--format=<format>]
[(-r | --remotes) | (-a | --all)]
[--list] [<pattern>...]
-'git branch' [--track | --no-track] [-f] <branchname> [<start-point>]
+'git branch' [--track | --no-track] [-f] [--dry-run | -n] <branchname> [<start-point>]
'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
'git branch' --unset-upstream [<branchname>]
'git branch' (-m | -M) [<oldbranch>] <newbranch>
@@ -205,6 +205,12 @@ This option is only applicable in non-verbose mode.
--no-abbrev::
Display the full sha1s in the output listing rather than abbreviating them.
+-n::
+--dry-run::
+ Can only be used when creating a branch. If the branch creation
+ would fail, show the relevant error message. If the branch
+ creation would succeed, show nothing.
+
-t::
--track::
When creating a new branch, set up `branch.<name>.remote` and
diff --git a/branch.c b/branch.c
index f8b755513f..528cb2d639 100644
--- a/branch.c
+++ b/branch.c
@@ -206,9 +206,9 @@ N_("\n"
"will track its remote counterpart, you may want to use\n"
"\"git push -u\" to set the upstream config as you push.");
-static void validate_branch_start(struct repository *r, const char *start_name,
- enum branch_track track,
- struct object_id *oid, char **full_ref)
+void validate_branch_start(struct repository *r, const char *start_name,
+ enum branch_track track, struct object_id *oid,
+ char **full_ref)
{
struct commit *commit;
int explicit_tracking = 0;
diff --git a/branch.h b/branch.h
index 75cefcdcbd..d8e5ff4e28 100644
--- a/branch.h
+++ b/branch.h
@@ -3,6 +3,7 @@
struct repository;
struct strbuf;
+struct object_id;
enum branch_track {
BRANCH_TRACK_UNSPECIFIED = -1,
@@ -17,6 +18,27 @@ extern enum branch_track git_branch_track;
/* Functions for acting on the information about branches. */
+/*
+ * Validates whether a ref is a valid starting point for a branch, where:
+ *
+ * - r is the repository to validate the branch for
+ *
+ * - start_name is the ref that we would like to test
+ *
+ * - track is the tracking mode of the new branch. If tracking is
+ * explicitly requested, start_name must be a branch (because
+ * otherwise start_name cannot be tracked)
+ *
+ * - oid is an out parameter containing the object_id of start_name
+ *
+ * - full_ref is an out parameter containing the 'full' form of
+ * start_name e.g. refs/heads/main instead of main
+ *
+ */
+void validate_branch_start(struct repository *r, const char *start_name,
+ enum branch_track track, struct object_id *oid,
+ char **full_ref);
+
/*
* This sets the branch.<new_ref>.{remote,merge} config settings so that
* branch 'new_ref' tracks 'orig_ref'. This is called when branches are
diff --git a/builtin/branch.c b/builtin/branch.c
index eb5c117a6e..5d4b9c82b4 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -27,7 +27,8 @@
static const char * const builtin_branch_usage[] = {
N_("git branch [<options>] [-r | -a] [--merged] [--no-merged]"),
- N_("git branch [<options>] [-l] [-f] <branch-name> [<start-point>]"),
+ N_("git branch [<options>] [-l] [<pattern>...]"),
+ N_("git branch [<options>] [-f] [--dry-run | -n] <branch-name> [<start-point>]"),
N_("git branch [<options>] [-r] (-d | -D) <branch-name>..."),
N_("git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"),
N_("git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"),
@@ -616,14 +617,14 @@ static int edit_branch_description(const char *branch_name)
int cmd_branch(int argc, const char **argv, const char *prefix)
{
- int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
- int show_current = 0;
- int reflog = 0, edit_description = 0;
- int quiet = 0, unset_upstream = 0;
+ /* possible actions */
+ int delete = 0, rename = 0, copy = 0, force = 0, list = 0, create = 0,
+ unset_upstream = 0, show_current = 0, edit_description = 0;
+ /* possible options */
+ int reflog = 0, quiet = 0, dry_run = 0, icase = 0;
const char *new_upstream = NULL;
enum branch_track track;
struct ref_filter filter;
- int icase = 0;
static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
struct ref_format format = REF_FORMAT_INIT;
@@ -670,6 +671,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
N_("print only branches of the object"), parse_opt_object_name),
OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
+ OPT__DRY_RUN(&dry_run, N_("show whether the branch would be created")),
OPT_END(),
};
@@ -705,10 +707,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
filter.reachable_from || filter.unreachable_from || filter.points_at.nr)
list = 1;
- if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current +
- list + edit_description + unset_upstream > 1)
+ create = 1 - (!!delete + !!rename + !!copy + !!new_upstream +
+ !!show_current + !!list + !!edit_description +
+ !!unset_upstream);
+ if (create < 0)
usage_with_options(builtin_branch_usage, options);
+ if (dry_run && !create)
+ die(_("--dry-run can only be used when creating branches"));
+
if (filter.abbrev == -1)
filter.abbrev = DEFAULT_ABBREV;
filter.ignore_case = icase;
@@ -844,7 +851,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
strbuf_addf(&buf, "branch.%s.merge", branch->name);
git_config_set_multivar(buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE);
strbuf_release(&buf);
- } else if (argc > 0 && argc <= 2) {
+ } else if (create && argc > 0 && argc <= 2) {
+ const char *branch_name = argv[0];
+ const char *start_name = (argc == 2) ? argv[1] : head;
+
if (filter.kind != FILTER_REFS_BRANCHES)
die(_("The -a, and -r, options to 'git branch' do not take a branch name.\n"
"Did you mean to use: -a|-r --list <pattern>?"));
@@ -852,10 +862,20 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (track == BRANCH_TRACK_OVERRIDE)
die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead."));
- create_branch(the_repository,
- argv[0], (argc == 2) ? argv[1] : head,
- force, 0, reflog, quiet, track);
+ if (dry_run) {
+ struct strbuf buf = STRBUF_INIT;
+ char *unused_full_ref;
+ struct object_id unused_oid;
+ validate_new_branchname(branch_name, &buf, force);
+ validate_branch_start(the_repository, start_name, track,
+ &unused_oid, &unused_full_ref);
+ strbuf_release(&buf);
+ FREE_AND_NULL(unused_full_ref);
+ return 0;
+ }
+ create_branch(the_repository, branch_name, start_name, force, 0,
+ reflog, quiet, track);
} else
usage_with_options(builtin_branch_usage, options);
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 6bf95a1707..653891736a 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -59,6 +59,19 @@ test_expect_success 'git branch --force abc should succeed when abc exists' '
test_cmp expect actual
'
+test_expect_success 'git branch --dry-run abc should fail when abc exists' '
+ test_must_fail git branch --dry-run abc
+'
+
+test_expect_success 'git branch --dry-run --force abc should succeed when abc exists' '
+ git branch --dry-run --force abc
+'
+
+test_expect_success 'git branch --dry-run def should not create a branch' '
+ git branch --dry-run def &&
+ test_must_fail git rev-parse def
+'
+
test_expect_success 'git branch a/b/c should create a branch' '
git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c
'
--
2.33.GIT
next prev parent reply other threads:[~2021-11-22 22:33 UTC|newest]
Thread overview: 110+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-22 22:32 [PATCH 0/4] implement branch --recurse-submodules Glen Choo
2021-11-22 22:32 ` [PATCH 1/4] submodule-config: add submodules_of_tree() helper Glen Choo
2021-11-23 2:12 ` Jonathan Tan
2021-11-23 19:48 ` Glen Choo
2021-11-23 10:53 ` Ævar Arnfjörð Bjarmason
2021-11-23 18:35 ` Glen Choo
2021-11-23 22:46 ` Junio C Hamano
2021-11-22 22:32 ` [PATCH 2/4] branch: refactor out branch validation from create_branch() Glen Choo
2021-11-22 22:32 ` Glen Choo [this message]
2021-11-23 10:42 ` [PATCH 3/4] branch: add --dry-run option to branch Ævar Arnfjörð Bjarmason
2021-11-23 18:42 ` Glen Choo
2021-11-23 23:10 ` Jonathan Tan
2021-11-24 0:52 ` Glen Choo
2021-11-22 22:32 ` [PATCH 4/4] branch: add --recurse-submodules option for branch creation Glen Choo
2021-11-23 10:45 ` Ævar Arnfjörð Bjarmason
2021-11-23 18:56 ` Glen Choo
2021-11-23 19:41 ` Philippe Blain
2021-11-23 23:43 ` Glen Choo
2021-11-24 1:31 ` Jonathan Tan
2021-11-24 18:18 ` Glen Choo
2021-11-29 21:01 ` Jonathan Tan
2021-12-06 21:55 ` [PATCH v2 0/3] implement branch --recurse-submodules Glen Choo
2021-12-06 21:55 ` [PATCH v2 1/3] branch: move --set-upstream-to behavior to setup_tracking() Glen Choo
2021-12-06 22:48 ` Junio C Hamano
2021-12-08 18:48 ` Glen Choo
2021-12-06 23:28 ` Junio C Hamano
2021-12-08 17:09 ` Glen Choo
2021-12-06 21:55 ` [PATCH v2 2/3] builtin/branch: clean up action-picking logic in cmd_branch() Glen Choo
2021-12-06 21:55 ` [PATCH v2 3/3] branch: add --recurse-submodules option for branch creation Glen Choo
2021-12-09 18:49 ` [PATCH v3 0/5] implement branch --recurse-submodules Glen Choo
2021-12-09 18:49 ` [PATCH v3 1/5] branch: move --set-upstream-to behavior to setup_tracking() Glen Choo
2021-12-09 21:19 ` Jonathan Tan
2021-12-09 22:16 ` Glen Choo
2021-12-09 18:49 ` [PATCH v3 2/5] branch: remove forward declaration of validate_branch_start() Glen Choo
2021-12-09 18:49 ` [PATCH v3 3/5] builtin/branch: clean up action-picking logic in cmd_branch() Glen Choo
2021-12-09 21:23 ` Jonathan Tan
2021-12-09 21:57 ` Glen Choo
2021-12-09 18:49 ` [PATCH v3 4/5] branch: add --recurse-submodules option for branch creation Glen Choo
2021-12-11 18:08 ` Philippe Blain
2021-12-14 20:08 ` Glen Choo
2021-12-09 18:49 ` [PATCH v3 5/5] branch.c: replace questionable exit() codes Glen Choo
2021-12-10 2:21 ` Ævar Arnfjörð Bjarmason
2021-12-10 17:43 ` Glen Choo
2021-12-13 9:02 ` Junio C Hamano
2021-12-13 9:19 ` Ævar Arnfjörð Bjarmason
2021-12-13 19:26 ` Junio C Hamano
2021-12-09 21:59 ` [PATCH v3 0/5] implement branch --recurse-submodules Jonathan Tan
2021-12-09 22:21 ` Glen Choo
2021-12-13 23:20 ` Jonathan Tan
2021-12-14 18:47 ` Glen Choo
2021-12-16 0:32 ` [PATCH v4 " Glen Choo
2021-12-16 0:32 ` [PATCH v4 1/5] branch: move --set-upstream-to behavior to dwim_and_setup_tracking() Glen Choo
2021-12-16 0:32 ` [PATCH v4 2/5] branch: make create_branch() always create a branch Glen Choo
2021-12-16 0:32 ` [PATCH v4 3/5] branch: add a dry_run parameter to create_branch() Glen Choo
2021-12-16 0:32 ` [PATCH v4 4/5] builtin/branch: clean up action-picking logic in cmd_branch() Glen Choo
2021-12-16 0:32 ` [PATCH v4 5/5] branch: add --recurse-submodules option for branch creation Glen Choo
2021-12-16 23:33 ` [PATCH v5 0/5] implement branch --recurse-submodules Glen Choo
2021-12-16 23:33 ` [PATCH v5 1/5] branch: move --set-upstream-to behavior to dwim_and_setup_tracking() Glen Choo
2021-12-16 23:33 ` [PATCH v5 2/5] branch: make create_branch() always create a branch Glen Choo
2021-12-16 23:33 ` [PATCH v5 3/5] branch: add a dry_run parameter to create_branch() Glen Choo
2021-12-16 23:33 ` [PATCH v5 4/5] builtin/branch: clean up action-picking logic in cmd_branch() Glen Choo
2021-12-16 23:33 ` [PATCH v5 5/5] branch: add --recurse-submodules option for branch creation Glen Choo
2021-12-17 0:34 ` [PATCH v5 0/5] implement branch --recurse-submodules Junio C Hamano
2021-12-17 0:45 ` Junio C Hamano
2021-12-20 19:09 ` Glen Choo
2021-12-20 19:50 ` Junio C Hamano
2021-12-20 20:25 ` Glen Choo
2021-12-20 23:34 ` [PATCH v6 " Glen Choo
2021-12-20 23:34 ` [PATCH v6 1/5] branch: move --set-upstream-to behavior to dwim_and_setup_tracking() Glen Choo
2022-01-11 2:09 ` Jonathan Tan
2022-01-11 17:29 ` Glen Choo
2022-01-11 20:03 ` Jonathan Tan
2021-12-20 23:34 ` [PATCH v6 2/5] branch: make create_branch() always create a branch Glen Choo
2022-01-11 2:19 ` Jonathan Tan
2022-01-11 17:51 ` Glen Choo
2021-12-20 23:34 ` [PATCH v6 3/5] branch: add a dry_run parameter to create_branch() Glen Choo
2021-12-20 23:34 ` [PATCH v6 4/5] builtin/branch: clean up action-picking logic in cmd_branch() Glen Choo
2021-12-20 23:34 ` [PATCH v6 5/5] branch: add --recurse-submodules option for branch creation Glen Choo
2021-12-26 4:09 ` Junio C Hamano
2022-01-11 3:28 ` Jonathan Tan
2022-01-11 18:11 ` Glen Choo
2022-01-11 20:15 ` Jonathan Tan
2022-01-11 23:22 ` Glen Choo
2021-12-20 23:36 ` [PATCH v6 0/5] implement branch --recurse-submodules Glen Choo
2021-12-21 1:07 ` Junio C Hamano
2021-12-21 17:51 ` Glen Choo
2022-01-24 20:44 ` [PATCH v7 0/6] " Glen Choo
2022-01-24 20:44 ` [PATCH v7 1/6] branch: move --set-upstream-to behavior to dwim_and_setup_tracking() Glen Choo
2022-01-24 20:44 ` [PATCH v7 2/6] branch: make create_branch() always create a branch Glen Choo
2022-01-24 20:44 ` [PATCH v7 3/6] branch: add a dry_run parameter to create_branch() Glen Choo
2022-01-24 20:44 ` [PATCH v7 4/6] builtin/branch: consolidate action-picking logic in cmd_branch() Glen Choo
2022-01-24 20:44 ` [PATCH v7 5/6] branch: add --recurse-submodules option for branch creation Glen Choo
2022-01-27 20:29 ` Jonathan Tan
2022-01-27 21:32 ` Glen Choo
2022-01-27 22:42 ` Glen Choo
2022-01-24 20:44 ` [PATCH v7 6/6] branch.c: use 'goto cleanup' in setup_tracking() to fix memory leaks Glen Choo
2022-01-27 22:15 ` Junio C Hamano
2022-01-28 19:44 ` Glen Choo
2022-01-29 0:04 ` [PATCH v8 0/6] implement branch --recurse-submodules Glen Choo
2022-01-29 0:04 ` [PATCH v8 1/6] branch: move --set-upstream-to behavior to dwim_and_setup_tracking() Glen Choo
2022-01-29 0:04 ` [PATCH v8 2/6] branch: make create_branch() always create a branch Glen Choo
2022-02-01 22:20 ` Junio C Hamano
2022-01-29 0:04 ` [PATCH v8 3/6] branch: add a dry_run parameter to create_branch() Glen Choo
2022-01-29 0:04 ` [PATCH v8 4/6] builtin/branch: consolidate action-picking logic in cmd_branch() Glen Choo
2022-01-29 0:04 ` [PATCH v8 5/6] branch: add --recurse-submodules option for branch creation Glen Choo
2022-02-04 1:10 ` Glen Choo
2022-02-04 16:15 ` Junio C Hamano
2022-02-04 18:10 ` Glen Choo
2022-01-29 0:04 ` [PATCH v8 6/6] branch.c: use 'goto cleanup' in setup_tracking() to fix memory leaks Glen Choo
2022-02-01 17:43 ` [PATCH v8 0/6] implement branch --recurse-submodules Jonathan Tan
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
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211122223252.19922-4-chooglen@google.com \
--to=chooglen@google.com \
--cc=emilyshaffer@google.com \
--cc=git@vger.kernel.org \
--cc=jonathantanmy@google.com \
--cc=steadmon@google.com \
/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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
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 read-only IMAP folder(s) and NNTP newsgroup(s).