mbox series

[0/6] clone, submodule update: check out submodule branches

Message ID pull.1321.git.git.1661806456.gitgitgadget@gmail.com (mailing list archive)
Headers show
Series clone, submodule update: check out submodule branches | expand

Message

John Cai via GitGitGadget Aug. 29, 2022, 8:54 p.m. UTC
= Description

This series teaches "git clone --recurse-submodules" and "git submodule
update" to understand "submodule.propagateBranches" (see Further Reading for
context), i.e. if the superproject has a branch checked out and a submodule
is cloned, the submodule will have the same branch checked out.

To do this, "git submodule update" checks if "submodule.propagateBranches"
is true, and if so, gets the current superproject branch and updates the
submodule by running "git checkout -b my-superproject-branch". Since "git
clone --recurse-submodules" is implemented using "git submodule update", it
also learns this trick.

The main challenges with this approach are:

 * If the remote HEAD points to a branch, "git clone" always creates that
   branch in the clone. But with "submodule.propagateBranches", we want
   submodules to use the branch names of their superproject, not their
   upstream.
   
   This is solved by adding a new flag to "git clone", "--detach", which
   detaches the clone's HEAD at the branch and does not create it.

 * When "git submodule update" recurses into submodules, the parent process
   has to propagate the value of "submodule.propagateBranches" to child
   processes, otherwise the behavior will be inconsistent if the submodule
   has the config unset.
   
   This is solved by adding an internal GIT_* environment variable and
   passing it down via prepare_submodule_repo_env(). This is cleaner than
   passing "-c submodule.propagateBranches=true", but an even cleaner
   solution would be for submodules to read "submodule.propagateBranches"
   from their superproject config. This would also be useful for
   "submodule.alternateLocation" and "submodule.alternateErrorStrategy", as
   we wouldn't have to set those values in newly-cloned submodules. This
   requires teaching Git to treat submodules differently, which was the
   subject of some WIP in [1]. That topic has stalled, but I don't mind
   restarting it if others prefer that.

[1]
https://lore.kernel.org/git/20220310004423.2627181-1-emilyshaffer@google.com/

= Patch organization

 * Patch 1/6 adds "--detach" to "git clone"
 * Patch 2/6 creates the environment variable and repository setting for
   "submodule.propagateBranches"
 * Patches 3-5/6 are prep work, and 6/6 adds the actual
   "submodule.propagateBranches" behavior

= Future work

 * Patch 4, which refactors resolve_gitlink_ref(), notes that a better
   interface would be to return the refname instead of using an "out"
   parameter, but we use an "out" parameter so that any new callers trying
   to use the old function signature will get stopped by the compiler. The
   refactor can be finished at a later time.

= Further reading

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

"git branch --recurse-submodules":
https://lore.kernel.org/git/20220129000446.99261-1-chooglen@google.com/

Glen Choo (6):
  clone: teach --detach option
  repo-settings: add submodule_propagate_branches
  t5617: drop references to remote-tracking branches
  submodule: return target of submodule symref
  submodule--helper: refactor up-to-date criterion
  clone, submodule update: check out branches

 Documentation/git-clone.txt                   |  7 +++-
 builtin/branch.c                              | 11 ++----
 builtin/clone.c                               | 12 ++++--
 builtin/submodule--helper.c                   | 37 +++++++++++++++++--
 builtin/update-index.c                        |  4 +-
 cache.h                                       |  1 +
 combine-diff.c                                |  3 +-
 diff-lib.c                                    |  2 +-
 dir.c                                         |  2 +-
 object-file.c                                 |  2 +-
 read-cache.c                                  |  4 +-
 refs.c                                        | 10 +++--
 refs.h                                        |  5 ++-
 repo-settings.c                               | 11 +++---
 repository.h                                  |  1 +
 submodule.c                                   |  2 +
 t/t5601-clone.sh                              | 22 +++++++++++
 ...es-remote.sh => t5617-clone-submodules.sh} | 36 +++++++++++++++++-
 t/t7406-submodule-update.sh                   | 22 +++++++++++
 unpack-trees.c                                |  3 +-
 20 files changed, 161 insertions(+), 36 deletions(-)
 rename t/{t5617-clone-submodules-remote.sh => t5617-clone-submodules.sh} (72%)


base-commit: 9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1321%2Fchooglen%2Fsubmodule%2Fclone-recursive-with-branch-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1321/chooglen/submodule/clone-recursive-with-branch-v1
Pull-Request: https://github.com/git/git/pull/1321