git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 0/3] git for-each-ref: is-base atom and base branches

From
Derrick Stolee via GitGitGadget <gitgitgadget@gmail.com>
Date
Aug 11, 2024, 17:34 UTC
Message-ID
<pull.1768.v2.git.1723397687.gitgitgadget@gmail.com>
In-Reply-To
<pull.1768.git.1722550226.gitgitgadget@gmail.com>

This change introduces a new 'git for-each-ref' atom, 'is-base', in a very similar way to the 'ahead-behind' atom. As detailed carefully in the first change, this is motivated by the need to detect the concept of a "base branch" in a repository with multiple long-lived branches.

This change is motivated by a third-party tool created to make this detection with the same optimization mechanism, but using a much slower technique due to the limitations of the Git CLI not presenting this information. The existing algorithm involves using git rev-list --first-parent -<N> in batches for the collection of considered references, comparing those lists, and increasing <N> as needed until finding a collision. This new use of 'git for-each-ref' will allow determining this mechanism within a single process and walking a minimal number of commits.

There are benefits to users both on client-side and server-side. In an internal monorepo, this base branch detection algorithm is used to determine a long-lived branch based on the HEAD commit, mapping to a group within the organizational structure of the repository, which determines a set of projects that the user will likely need to build; this leads to automatically selecting an initial sparse-checkout definition based on the build dependencies required. An upcoming feature in Azure Repos will use this algorithm to automatically create a pull request against the correct target branch, reducing user pain from needing to select a different branch after a large commit diff is rendered against the default branch. This atom unlocks that ability for Git hosting services that use Git in their backend.

Thanks, -Stolee

Updates in v2 =============

 * I had forgotten to include a documentation change in v1. My attempt to
   create a succinct doc change in a follow-up hunk continued to be
   confusing. This version includes a more expanded version of the
   documentation blurb for the is-base token.
Derrick Stolee (3):
  commit-reach: add get_branch_base_for_tip
  for-each-ref: add 'is-base' token
  p1500: add is-base performance tests
 Documentation/git-for-each-ref.txt |  42 ++++++++++
 commit-reach.c                     | 118 +++++++++++++++++++++++++++++
 commit-reach.h                     |  17 +++++
 ref-filter.c                       |  78 ++++++++++++++++++-
 ref-filter.h                       |  15 ++++
 t/helper/test-reach.c              |   2 +
 t/perf/p1500-graph-walks.sh        |  31 ++++++++
 t/t6600-test-reach.sh              |  94 +++++++++++++++++++++++
 8 files changed, 396 insertions(+), 1 deletion(-)
base-commit: bea9ecd24b0c3bf06cab4a851694fe09e7e51408
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1768%2Fderrickstolee%2Ftarget-ref-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1768/derrickstolee/target-ref-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1768
Range-diff vs v1:
 1:  580026f910d = 1:  580026f910d commit-reach: add get_branch_base_for_tip
 2:  a1fbdca374f ! 2:  13341e7e512 for-each-ref: add 'is-base' token
     @@ Commit message
      
          Signed-off-by: Derrick Stolee <stolee@gmail.com>
      
     + ## Documentation/git-for-each-ref.txt ##
     +@@ Documentation/git-for-each-ref.txt: ahead-behind:<committish>::
     + 	commits ahead and behind, respectively, when comparing the output
     + 	ref to the `<committish>` specified in the format.
     + 
     ++is-base:<committish>::
     ++	In at most one row, `(<committish>)` will appear to indicate the ref
     ++	that is most likely the ref used as a starting point for the branch
     ++	that produced `<committish>`. This choice is made using a heuristic:
     ++	choose the ref that minimizes the number of commits in the
     ++	first-parent history of `<committish>` and not in the first-parent
     ++	history of the ref.
     +++
     ++For example, consider the following figure of first-parent histories of
     ++several refs:
     +++
     ++----
     ++*--*--*--*--*--* refs/heads/A
     ++\
     ++ \
     ++  *--*--*--* refs/heads/B
     ++   \     \
     ++    \     \
     ++     *     * refs/heads/C
     ++      \
     ++       \
     ++	*--* refs/heads/D
     ++----
     +++
     ++Here, if `A`, `B`, and `C` are the filtered references, and the format
     ++string is `%(refname):%(is-base:D)`, then the output would be
     +++
     ++----
     ++refs/heads/A:
     ++refs/heads/B:(D)
     ++refs/heads/C:
     ++----
     +++
     ++This is because the first-parent history of `D` has its earliest
     ++intersection with the first-parent histories of the filtered refs at a
     ++common first-parent ancestor of `B` and `C` and ties are broken by the
     ++earliest ref in the sorted order.
     +++
     ++Note that this token will not appear if the first-parent history of
     ++`<committish>` does not intersect the first-parent histories of the
     ++filtered refs.
     ++
     + describe[:options]::
     + 	A human-readable name, like linkgit:git-describe[1];
     + 	empty string for undescribable commits. The `describe` string may
     +
       ## ref-filter.c ##
      @@ ref-filter.c: enum atom_type {
       	ATOM_ELSE,
 3:  db87434e146 = 3:  757c20090db p1500: add is-base performance tests
-- 
gitgitgadget
Previous: Junio C HamanoNext: Derrick Stolee via GitGitGadget
Message 9 of 23 in “git for-each-ref: is-base atom and base branches”
  1. 0/3 git for-each-ref: is-base atom and base branchesDerrick Stolee via GitGitGadget, Aug 1, 2024
  2. 2/3 for-each-ref: add 'is-base' tokenDerrick Stolee via GitGitGadget, Aug 1, 2024
  3. 1/3 commit-reach: add get_branch_base_for_tipDerrick Stolee via GitGitGadget, Aug 1, 2024
  4. 3/3 p1500: add is-base performance testsDerrick Stolee via GitGitGadget, Aug 1, 2024
  5. Junio C HamanoAug 1, 2024
  6. Derrick StoleeAug 2, 2024
  7. Junio C HamanoAug 2, 2024
  8. Junio C HamanoAug 2, 2024
  9. 0/3 git for-each-ref: is-base atom and base branchesDerrick Stolee via GitGitGadget, Aug 11, 2024
  10. 2/3 for-each-ref: add 'is-base' tokenDerrick Stolee via GitGitGadget, Aug 11, 2024
  11. Junio C HamanoAug 12, 2024
  12. Derrick StoleeAug 13, 2024
  13. 1/3 commit-reach: add get_branch_base_for_tipDerrick Stolee via GitGitGadget, Aug 11, 2024
  14. Junio C HamanoAug 12, 2024
  15. Derrick StoleeAug 13, 2024
  16. 3/3 p1500: add is-base performance testsDerrick Stolee via GitGitGadget, Aug 11, 2024
  17. 0/4 git for-each-ref: is-base atom and base branchesDerrick Stolee via GitGitGadget, Aug 14, 2024
  18. 1/4 commit-reach: add get_branch_base_for_tipDerrick Stolee via GitGitGadget, Aug 14, 2024
  19. 2/4 commit: add gentle reference lookup methodDerrick Stolee via GitGitGadget, Aug 14, 2024
  20. 3/4 for-each-ref: add 'is-base' tokenDerrick Stolee via GitGitGadget, Aug 14, 2024
  21. 4/4 p1500: add is-base performance testsDerrick Stolee via GitGitGadget, Aug 14, 2024
  22. Junio C HamanoAug 19, 2024
  23. Derrick StoleeAug 20, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.