git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Glen Choo <chooglen@google.com>
To: git@vger.kernel.org
Cc: "Glen Choo" <chooglen@google.com>,
	"Jonathan Tan" <jonathantanmy@google.com>,
	"Josh Steadmon" <steadmon@google.com>,
	"Emily Shaffer" <emilyshaffer@google.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Philippe Blain" <levraiphilippeblain@gmail.com>,
	"Junio C Hamano" <gitster@pobox.com>
Subject: [PATCH v4 0/5] implement branch --recurse-submodules
Date: Wed, 15 Dec 2021 16:32:08 -0800	[thread overview]
Message-ID: <20211216003213.99135-1-chooglen@google.com> (raw)
In-Reply-To: <20211209184928.71413-1-chooglen@google.com>

Submodule branching RFC:
https://lore.kernel.org/git/kl6lv912uvjv.fsf@chooglen-macbookpro.roam.corp.google.com/

Original Submodule UX RFC/Discussion:
https://lore.kernel.org/git/YHofmWcIAidkvJiD@google.com/

Contributor Summit submodules Notes:
https://lore.kernel.org/git/nycvar.QRO.7.76.6.2110211148060.56@tvgsbejvaqbjf.bet/

Submodule UX overhaul updates:
https://lore.kernel.org/git/?q=Submodule+UX+overhaul+update

This series implements branch --recurse-submodules as laid out in the
Submodule branching RFC (linked above). If there are concerns about the
UX/behavior, I would appreciate feedback on the RFC thread as well :)

This series is based off js/branch-track-inherit.

Future work:
* `git branch -d --recurse-submodules` so that users can clean up
  extraneous branches.
* `git [checkout | switch] --recurse-submodules` +
  submodule.propagateBranches so that users can actually checkout the
  branches.
* After [1], it seems clear that --recurse-submodules parsing could
  really benefit from some standardization. It's not obvious which
  RECURSE_SUBMODULE_* enums are applicable to which commands, and there
  is no way to distinguish between an explicit --recurse-submodules from
  argv vs submodule.recurse from the config.

  I chose not to use them in this series because their usage is already
  inconsistent (grep.c doesn't use them either), and it would be _more_
  confusing to use the enum (handling RECURSE_SUBMODULES_DEFAULT = 1 is
  trickier than boolean 0 and 1).

  At this point, I think it would be too noisy to introduce the enum,
  but this would be a nice cleanup to do later.
* As documented in branch.c, we create branches using a child process
  only because install_branch_config() does not support submodules.
  It should be possible to remove the child process once we make the
  appropriate changes to config.c. I attempted this in [2] but chose to
  punt it because it was too time-consuming at the time.

Changes since v3:
* Split up the old patch 1. Patch 1 had a big diff because it used to
  move lines, remove dead code and introduce repo_* functions (thanks
  Jonathan!)
** repo_* functions have been dropped; they added noise and are not
   necessary for correctness.
* Use a new, harder-to-misuse function in --set-upstream-to,
  dwim_and_setup_tracking(). Now, setup_tracking() never does DWIM and
  dwim_and_setup_tracking() always does DWIM.
* Move create_branch() dry_run to its own patch.
* Fix an oversight where submodules in subtrees were ignored. This was
  because submodules_of_tree() and tree_entry() didn't recurse into
  subtrees. Test this accordingly (thanks Jonathan!).
* cmd_branch() possible actions are more consistently ordered.
* Documentation fixes (thanks Philippe!).
* Additional comments and explanation.
* Drop patch 5 (optional cleanup).
* Rebase onto js/branch-track-inherit v6.

Changes since v2:
* Rebase onto js/branch-track-inherit. This series should continue to be
  the case going forward.
* Patch 1 has a smaller diff because the introduction of
  validate_branch_start() no longer changes the function order thanks to a
  forward declaration. This artificial forward declaration is removed in a
  patch 2 (which can just be squashed into patch 1).
* Optional cleanup: fix questionable exit codes in patch 5.

Changes since v1:
* Move the functionality of "git branch --dry-run" into "git submodule-helper create-branch --dry-run"
* Add more fields to the submodules_of_tree() struct to reduce the
  number of allocations made by the caller. Move this functionality
  to patch 3 (formerly patch 4) and drop patch 1.
* Make submodules_of_tree() ignore inactive submodules
* Structure the output of the submodules a bit better by adding prefixes
  to the child process' output (instead of inconsistently indenting the
  output).
** I wasn't able to find a good way to interleave stdout/stderr
   correctly, so a less-than-desirable workaround was to route the child
   process output to stdout/stderr depending on the exit code.
** Eventually, I would like to structure the output of submodules in a
   report, as Ævar suggested. But at this stage, I think that it's
   better to spend time getting user feedback on the submodules
   branching UX and it'll be easier to standardize the output when we've
   implemented more of the UX :)

[1] https://lore.kernel.org/git/kl6lbl1p9zjf.fsf@chooglen-macbookpro.roam.corp.google.com/
[2] https://lore.kernel.org/git/kl6lv90ytd4v.fsf@chooglen-macbookpro.roam.corp.google.com/

Glen Choo (5):
  branch: move --set-upstream-to behavior to dwim_and_setup_tracking()
  branch: make create_branch() always create a branch
  branch: add a dry_run parameter to create_branch()
  builtin/branch: clean up action-picking logic in cmd_branch()
  branch: add --recurse-submodules option for branch creation

 Documentation/config/advice.txt    |   3 +
 Documentation/config/submodule.txt |  24 ++-
 Documentation/git-branch.txt       |  11 +-
 advice.c                           |   1 +
 advice.h                           |   1 +
 branch.c                           | 257 ++++++++++++++++++++-----
 branch.h                           |  57 +++++-
 builtin/branch.c                   |  70 +++++--
 builtin/checkout.c                 |   3 +-
 builtin/submodule--helper.c        |  38 ++++
 submodule-config.c                 |  60 ++++++
 submodule-config.h                 |  34 ++++
 submodule.c                        |  11 +-
 submodule.h                        |   3 +
 t/t3200-branch.sh                  |  17 ++
 t/t3207-branch-submodule.sh        | 291 +++++++++++++++++++++++++++++
 16 files changed, 805 insertions(+), 76 deletions(-)
 create mode 100755 t/t3207-branch-submodule.sh

Range-diff against v3:
1:  8241c0b51a < -:  ---------- branch: move --set-upstream-to behavior to setup_tracking()
2:  b74bcbaade < -:  ---------- branch: remove forward declaration of validate_branch_start()
-:  ---------- > 1:  dfdbbaaca5 branch: move --set-upstream-to behavior to dwim_and_setup_tracking()
-:  ---------- > 2:  e22a177cb7 branch: make create_branch() always create a branch
-:  ---------- > 3:  8a895aa401 branch: add a dry_run parameter to create_branch()
3:  235173efc9 ! 4:  971c53ec85 builtin/branch: clean up action-picking logic in cmd_branch()
    @@ Commit message
         Such an option does not exist yet, but one will be introduced in a
         subsequent commit.
     
    -    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>
     
      ## builtin/branch.c ##
    -@@
    - 
    - 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>] [-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>"),
     @@ builtin/branch.c: static int edit_branch_description(const char *branch_name)
      
      int cmd_branch(int argc, const char **argv, const char *prefix)
    @@ builtin/branch.c: static int edit_branch_description(const char *branch_name)
     -	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,
    ++	int delete = 0, rename = 0, copy = 0, list = 0,
     +	    unset_upstream = 0, show_current = 0, edit_description = 0;
    + 	const char *new_upstream = NULL;
     +	int noncreate_actions = 0;
     +	/* possible options */
    -+	int reflog = 0, quiet = 0, icase = 0;
    - 	const char *new_upstream = NULL;
    ++	int reflog = 0, quiet = 0, icase = 0, force = 0;
      	enum branch_track track;
      	struct ref_filter filter;
     -	int icase = 0;
4:  3dabb8e2fa ! 5:  cd88f3ad92 branch: add --recurse-submodules option for branch creation
    @@ Commit message
         * add the "submoduleNotUpdated" advice to advise users to update the
           submodules in their trees
     
    -    Other changes
    -
    -    * add a "dry_run" parameter to create_branch() in order to support
    -      `git submodule--helper create-branch --dry-run`
    +    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>
     
    @@ Documentation/config/advice.txt: advice.*::
      		configured to "die" causes a fatal error.
     +	submodulesNotUpdated::
     +		Advice shown when a user runs a submodule command that fails
    -+		because `git submodule update` was not run.
    ++		because `git submodule update --init` was not run.
      	addIgnoredFile::
      		Advice shown if a user attempts to add an ignored file to
      		the index.
     
      ## Documentation/config/submodule.txt ##
    +@@ Documentation/config/submodule.txt: submodule.active::
    + 
    + submodule.recurse::
    + 	A boolean indicating if commands should enable the `--recurse-submodules`
    +-	option by default.
    +-	Applies to all commands that support this option
    +-	(`checkout`, `fetch`, `grep`, `pull`, `push`, `read-tree`, `reset`,
    +-	`restore` and `switch`) except `clone` and `ls-files`.
    +-	Defaults to false.
    ++	option by default. Defaults to false.
    ++	+
    + 	When set to true, it can be deactivated via the
    + 	`--no-recurse-submodules` option. Note that some Git commands
    + 	lacking this option may call some of the above commands affected by
     @@ Documentation/config/submodule.txt: submodule.recurse::
    + 	`git fetch` but does not have a `--no-recurse-submodules` option.
      	For these commands a workaround is to temporarily change the
      	configuration value by using `git -c submodule.recurse=0`.
    - 
    ++	+
    ++	The following list shows the commands that accept
    ++	`--recurse-submodules` and whether they are supported by this
    ++	setting.
    ++	* `checkout`, `fetch`, `grep`, `pull`, `push`, `read-tree`,
    ++	`reset`, `restore` and `switch` are always supported.
    ++	* `clone` and `ls-files` are not supported.
    ++	* `branch` is supported only if `submodule.propagateBranches` is
    ++	enabled
    ++
     +submodule.propagateBranches::
     +	[EXPERIMENTAL] A boolean that enables branching support when
     +	using `--recurse-submodules` or `submodule.recurse=true`.
    @@ Documentation/config/submodule.txt: submodule.recurse::
     +	`--recurse-submodules` and certain commands that already accept
     +	`--recurse-submodules` will now consider branches.
     +	Defaults to false.
    -+
    + 
      submodule.fetchJobs::
      	Specifies how many submodules are fetched/cloned at the same time.
    - 	A positive integer allows up to that number of submodules fetched
    +
    + ## Documentation/git-branch.txt ##
    +@@ Documentation/git-branch.txt: SYNOPSIS
    + 	[--points-at <object>] [--format=<format>]
    + 	[(-r | --remotes) | (-a | --all)]
    + 	[--list] [<pattern>...]
    +-'git branch' [--track [direct|inherit] | --no-track] [-f] <branchname> [<start-point>]
    ++'git branch' [--track [direct|inherit] | --no-track] [-f]
    ++	[--recurse-submodules] <branchname> [<start-point>]
    + 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
    + 'git branch' --unset-upstream [<branchname>]
    + 'git branch' (-m | -M) [<oldbranch>] <newbranch>
    +@@ Documentation/git-branch.txt: how the `branch.<name>.remote` and `branch.<name>.merge` options are used.
    + 	Do not set up "upstream" configuration, even if the
    + 	branch.autoSetupMerge configuration variable is set.
    + 
    ++--recurse-submodules::
    ++	THIS OPTION IS EXPERIMENTAL! Causes the current command to
    ++	recurse into submodules if `submodule.propagateBranches` is
    ++	enabled. See `submodule.propagateBranches` in
    ++	linkgit:git-config[1].
    ++	+
    ++	Currently, only branch creation is supported.
    ++
    + --set-upstream::
    + 	As this option had confusing syntax, it is no longer supported.
    + 	Please use `--track` or `--set-upstream-to` instead.
     
      ## advice.c ##
     @@ advice.c: static struct {
    @@ branch.c
      
      struct tracking {
      	struct refspec_item spec;
    -@@ branch.c: void setup_tracking(const char *new_ref, const char *orig_ref,
    - 
    - void create_branch(struct repository *r, const char *name,
    - 		   const char *start_name, int force, int clobber_head_ok,
    --		   int reflog, int quiet, enum branch_track track)
    -+		   int reflog, int quiet, enum branch_track track, int dry_run)
    - {
    - 	struct object_id oid;
    - 	char *real_ref;
    -@@ branch.c: void create_branch(struct repository *r, const char *name,
    - 	}
    - 
    - 	validate_branch_start(r, start_name, track, &oid, &real_ref);
    -+	if (dry_run)
    -+		goto cleanup;
    - 
    - 	if (reflog)
    - 		log_all_ref_updates = LOG_REFS_NORMAL;
    -@@ branch.c: void create_branch(struct repository *r, const char *name,
    - 	if (real_ref && track)
    - 		setup_tracking(ref.buf + 11, real_ref, track, quiet, 0);
    - 
    -+cleanup:
    - 	strbuf_release(&ref);
    - 	free(real_ref);
    +@@ branch.c: void dwim_and_setup_tracking(struct repository *r, const char *new_ref,
    + 	setup_tracking(new_ref, real_orig_ref, track, quiet);
      }
      
    ++/**
    ++ * Creates a branch in a submodule by calling
    ++ * create_branches_recursively() in a child process. The child process
    ++ * is necessary because install_branch_config() (and its variants) do
    ++ * not support writing configs to submodules.
    ++ */
     +static int submodule_create_branch(struct repository *r,
     +				   const struct submodule *submodule,
     +				   const char *name, const char *start_oid,
    @@ branch.c: void create_branch(struct repository *r, const char *name,
     +	struct submodule_entry_list submodule_entry_list;
     +
     +	/* Perform dwim on start_name to get super_oid and branch_point. */
    -+	validate_branch_start(r, start_name, BRANCH_TRACK_NEVER, &super_oid,
    -+			      &branch_point);
    ++	dwim_branch_start(r, start_name, BRANCH_TRACK_NEVER, &branch_point,
    ++			  &super_oid);
     +
     +	/*
     +	 * If we were not given an explicit name to track, then assume we are at
    @@ branch.c: void create_branch(struct repository *r, const char *name,
     +	 * tedious to determine whether or not tracking was set up in the
     +	 * superproject.
     +	 */
    -+	setup_tracking(name, tracking_name, track, quiet, 0);
    ++	setup_tracking(name, tracking_name, track, quiet);
     +
     +	for (i = 0; i < submodule_entry_list.entry_nr; i++) {
     +		if (submodule_create_branch(
    @@ branch.c: void create_branch(struct repository *r, const char *name,
      	unlink(git_path_merge_head(r));
     
      ## branch.h ##
    -@@ branch.h: void setup_tracking(const char *new_ref, const char *orig_ref,
    -  *   - track causes the new branch to be configured to merge the remote branch
    -  *     that start_name is a tracking branch for (if any).
    -  *
    -+ *   - dry_run causes the branch to be validated but not created.
    -+ *
    -  */
    --void create_branch(struct repository *r,
    --		   const char *name, const char *start_name,
    --		   int force, int clobber_head_ok,
    --		   int reflog, int quiet, enum branch_track track);
    -+void create_branch(struct repository *r, const char *name,
    -+		   const char *start_name, int force, int clobber_head_ok,
    -+		   int reflog, int quiet, enum branch_track track, int dry_run);
    +@@ branch.h: void create_branch(struct repository *r, const char *name,
    + 		   const char *start_name, int force, int clobber_head_ok,
    + 		   int reflog, int quiet, enum branch_track track, int dry_run);
      
     +/*
     + * Creates a new branch in repository and its submodules (and its
    @@ branch.h: void setup_tracking(const char *new_ref, const char *orig_ref,
       * Return 1 if the named branch already exists; return 0 otherwise.
     
      ## builtin/branch.c ##
    +@@
    + 
    + 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>] [-f] [--recurse-submodules] <branch-name> [<start-point>]"),
    ++	N_("git branch [<options>] [-l] [<pattern>...]"),
    + 	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>"),
     @@ builtin/branch.c: static const char * const builtin_branch_usage[] = {
      
      static const char *head;
    @@ builtin/branch.c: static int git_branch_config(const char *var, const char *valu
      }
      
     @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix)
    - 	    unset_upstream = 0, show_current = 0, edit_description = 0;
    + 	const char *new_upstream = NULL;
      	int noncreate_actions = 0;
      	/* possible options */
    --	int reflog = 0, quiet = 0, icase = 0;
    -+	int reflog = 0, quiet = 0, icase = 0, recurse_submodules_explicit = 0;
    - 	const char *new_upstream = NULL;
    +-	int reflog = 0, quiet = 0, icase = 0, force = 0;
    ++	int reflog = 0, quiet = 0, icase = 0, force = 0,
    ++	    recurse_submodules_explicit = 0;
      	enum branch_track track;
      	struct ref_filter filter;
    + 	static struct ref_sorting *sorting;
     @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix)
      		OPT_CALLBACK(0, "points-at", &filter.points_at, N_("object"),
      			N_("print only branches of the object"), parse_opt_object_name),
    @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix
      
     -		create_branch(the_repository,
     -			      argv[0], (argc == 2) ? argv[1] : head,
    --			      force, 0, reflog, quiet, track);
    +-			      force, 0, reflog, quiet, track, 0);
     -
     +		if (recurse_submodules) {
     +			create_branches_recursively(the_repository, branch_name,
    @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix
      		usage_with_options(builtin_branch_usage, options);
      
     
    - ## builtin/checkout.c ##
    -@@ builtin/checkout.c: static void update_refs_for_switch(const struct checkout_opts *opts,
    - 				      opts->new_branch_force ? 1 : 0,
    - 				      opts->new_branch_log,
    - 				      opts->quiet,
    --				      opts->track);
    -+				      opts->track,
    -+				      0);
    - 		new_branch_info->name = opts->new_branch;
    - 		setup_branch_path(new_branch_info);
    - 	}
    -
      ## builtin/submodule--helper.c ##
     @@
      #include "diff.h"
    @@ submodule-config.c: const struct submodule *submodule_from_path(struct repositor
      	return config_from(r->submodule_cache, treeish_name, path, lookup_path);
      }
      
    -+void submodules_of_tree(struct repository *r,
    -+			const struct object_id *treeish_name,
    -+			struct submodule_entry_list *out)
    ++/**
    ++ * Used internally by submodules_of_tree(). Recurses into 'treeish_name'
    ++ * and appends submodule entries to 'out'. The submodule_cache expects
    ++ * a root-level treeish_name and paths, so keep track of these values
    ++ * with 'root_tree' and 'prefix'.
    ++ */
    ++static void traverse_tree_submodules(struct repository *r,
    ++				     const struct object_id *root_tree,
    ++				     char *prefix,
    ++				     const struct object_id *treeish_name,
    ++				     struct submodule_entry_list *out)
     +{
     +	struct tree_desc tree;
     +	struct submodule_tree_entry *st_entry;
     +	struct name_entry *name_entry;
    ++	char *tree_path = NULL;
     +
     +	name_entry = xmalloc(sizeof(*name_entry));
     +
    ++	fill_tree_descriptor(r, &tree, treeish_name);
    ++	while (tree_entry(&tree, name_entry)) {
    ++		if (prefix)
    ++			tree_path =
    ++				mkpathdup("%s/%s", prefix, name_entry->path);
    ++		else
    ++			tree_path = xstrdup(name_entry->path);
    ++
    ++		if (S_ISGITLINK(name_entry->mode) &&
    ++		    is_tree_submodule_active(r, root_tree, tree_path)) {
    ++			st_entry = xmalloc(sizeof(*st_entry));
    ++			st_entry->name_entry = name_entry;
    ++			st_entry->submodule =
    ++				submodule_from_path(r, root_tree, tree_path);
    ++			st_entry->repo = xmalloc(sizeof(*st_entry->repo));
    ++			if (repo_submodule_init(st_entry->repo, r, tree_path,
    ++						root_tree))
    ++				FREE_AND_NULL(st_entry->repo);
    ++
    ++			ALLOC_GROW(out->entries, out->entry_nr + 1,
    ++				   out->entry_alloc);
    ++			out->entries[out->entry_nr++] = *st_entry;
    ++		} else if (S_ISDIR(name_entry->mode))
    ++			traverse_tree_submodules(r, root_tree, tree_path,
    ++						 &name_entry->oid, out);
    ++		free(tree_path);
    ++	}
    ++}
    ++
    ++void submodules_of_tree(struct repository *r,
    ++			const struct object_id *treeish_name,
    ++			struct submodule_entry_list *out)
    ++{
     +	CALLOC_ARRAY(out->entries, 0);
     +	out->entry_nr = 0;
     +	out->entry_alloc = 0;
     +
    -+	fill_tree_descriptor(r, &tree, treeish_name);
    -+	while (tree_entry(&tree, name_entry)) {
    -+		if (!S_ISGITLINK(name_entry->mode) || !is_tree_submodule_active(r, treeish_name, name_entry->path)) {
    -+			continue;
    -+		}
    -+
    -+		st_entry = xmalloc(sizeof(*st_entry));
    -+		st_entry->name_entry = name_entry;
    -+		st_entry->submodule =
    -+			submodule_from_path(r, treeish_name, name_entry->path);
    -+		st_entry->repo = xmalloc(sizeof(*st_entry->repo));
    -+		if (repo_submodule_init(st_entry->repo, r, name_entry->path,
    -+					treeish_name))
    -+			FREE_AND_NULL(st_entry->repo);
    -+
    -+		ALLOC_GROW(out->entries, out->entry_nr + 1, out->entry_alloc);
    -+		out->entries[out->entry_nr++] = *st_entry;
    -+	}
    ++	traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out);
     +}
     +
      void submodule_free(struct repository *r)
    @@ submodule-config.h: int check_submodule_name(const char *name);
     +};
     +
     +/**
    -+ * Given a treeish, return all submodules in the tree. This only reads
    -+ * one level of the tree, so it will not return nested submodules;
    -+ * callers that require nested submodules are expected to handle the
    -+ * recursion themselves.
    ++ * Given a treeish, return all submodules in the tree and its subtrees,
    ++ * but excluding nested submodules. Callers that require nested
    ++ * submodules are expected to recurse into the submodules themselves.
     + */
     +void submodules_of_tree(struct repository *r,
     +			const struct object_id *treeish_name,
    @@ t/t3207-branch-submodule.sh (new)
     +	git init sub-sub-upstream &&
     +	test_commit -C sub-sub-upstream foo &&
     +	git init sub-upstream &&
    ++	# Submodule in a submodule
     +	git -C sub-upstream submodule add "$TRASH_DIRECTORY/sub-sub-upstream" sub-sub &&
     +	git -C sub-upstream commit -m "add submodule" &&
    ++	# Regular submodule
     +	git -C super submodule add "$TRASH_DIRECTORY/sub-upstream" sub &&
    ++	# Submodule in a subdirectory
    ++	git -C super submodule add "$TRASH_DIRECTORY/sub-sub-upstream" second/sub &&
     +	git -C super commit -m "add submodule" &&
     +	git -C super config submodule.propagateBranches true &&
     +	git -C super/sub submodule update --init
    @@ t/t3207-branch-submodule.sh (new)
     +		git branch --recurse-submodules branch-a &&
     +		git rev-parse branch-a &&
     +		git -C sub rev-parse branch-a &&
    -+		git -C sub/sub-sub rev-parse branch-a
    ++		git -C sub/sub-sub rev-parse branch-a &&
    ++		git -C second/sub rev-parse branch-a
     +	)
     +'
     +
    @@ t/t3207-branch-submodule.sh (new)
     +	)
     +'
     +
    -+test_expect_success 'should create branch when submodule is not in HEAD .gitmodules' '
    ++test_expect_success 'should create branch when submodule is not in HEAD:.gitmodules' '
     +	test_when_finished "cleanup_branches super branch-a branch-b branch-c" &&
     +	(
     +		cd super &&
    @@ t/t3207-branch-submodule.sh (new)
     +		git branch --recurse-submodules branch-c branch-b &&
     +		git rev-parse branch-c &&
     +		git -C sub rev-parse branch-c &&
    ++		git -C second/sub rev-parse branch-c &&
     +		git checkout --recurse-submodules branch-c &&
    -+		git -C sub2 rev-parse branch-c
    ++		git -C sub2 rev-parse branch-c &&
    ++		git -C sub2/sub-sub rev-parse branch-c
     +	)
     +'
     +
5:  70fb03f882 < -:  ---------- branch.c: replace questionable exit() codes
-- 
2.33.GIT


  parent reply	other threads:[~2021-12-16  0:32 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 ` [PATCH 3/4] branch: add --dry-run option to branch Glen Choo
2021-11-23 10:42   ` Æ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     ` Glen Choo [this message]
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

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

  git send-email \
    --in-reply-to=20211216003213.99135-1-chooglen@google.com \
    --to=chooglen@google.com \
    --cc=avarab@gmail.com \
    --cc=emilyshaffer@google.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jonathantanmy@google.com \
    --cc=levraiphilippeblain@gmail.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.
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).