All of lore.kernel.org
 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 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.