fix(gitextractor): keep deepening shallow clones past merge boundaries - #9190
Open
chenwei791129 wants to merge 1 commit into
Open
chenwei791129 wants to merge 1 commit into
chenwei791129 wants to merge 1 commit into
Conversation
--shallow-since makes a merge commit shallow when any of its parents is older than since, which hides newer commits on its other parent. A single --deepen=1 can leave them without their first parent, so the collectors skip them and later incremental runs never fetch them again. After --deepen=1, keep deepening (1, 2, 4, ... generations, at most 10 extra rounds) while the newest shallow boundary commit is newer than since. Boundary commits that were not fetched are filtered with cat-file, lazy fetches are disabled where git supports GIT_NO_LAZY_FETCH, and failures are only logged as warnings. Closes apache#9189
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a silent, permanent data gap in
gitextractorincremental collection. Commits that are clearly inside the collection window can be dropped when a merge request brings in a branch whose head is older than the previous run. After that, no later incremental run picks them up. Details and a standalone reproduction are in #9189.What goes wrong today
History on the default branch; the previous run started at 12:00, so this run fetches with
since = 12:00:This run should store
Q,PandM. What actually happens:git fetch --shallow-since=12:00stops atM. Git decides "shallow or not" per commit: since one parent ofM(F) is older than 12:00, git cutsMoff from all its parents, soPandQare not fetched even though they are newer than 12:00.The single
git fetch --deepen=1adds one generation:Parrives, but its parentQdoes not.CollectCommits()skips any commit whose first parent is not in the local clone (skip commit ... because it has no parent commit), soPis not stored.Qwas never fetched.The next run starts from this run's start time, so
PandQare now "old" and are never fetched again.When a lost commit is a deployment head,
refdiffcompares the next deployment against an incomplete graph and old PRs inflate DORA Lead Time for Changes.The change
After the existing
--deepen=1, keep fetching more history for as long as the newest shallow boundary commit is still newer thansince. Each extra round deepens by twice as many generations as the previous one (1, 2, 4, ...), with a cap of 10 extra rounds.When the loop ends, every boundary commit is older than
since, so it was either stored by an earlier run or is outside the collection window (first sync withtimeAfter). The existing "no parent commit" skip then only affects those commits, which is the case #7720 introduced it for. The first sync withtimeAftergoes through the same path and benefits as well.Details:
shallowfile. Git can list boundary commits there that it did not fetch, andgit logfails on those (--ignore-missingdoes not help for full object ids), so the commits are first filtered withgit cat-file --batch-check.SkipCommitStat, the clone uses--filter=blob:none. In such a clone, looking up a missing object makes git fetch it from origin. The boundary lookup setsGIT_NO_LAZY_FETCH=1to prevent that where git supports it (git 2.45+ and some backports, for example Debian's 2.39.5). With older git (such as 2.30.2 in the CI builder image) the lookup may trigger that fetch, which uses the same auth and proxy settings as the other fetches.Not changed
--shallow-sincewindow. That is a separate limitation.NoShallowCloneare not covered.doubleCloneremoves the intermediate clone, which is the fetch remote, before the deepen steps run. This is pre-existing and also affects the existing--deepen=1.Does this close any open issues?
Closes #9189
Screenshots
N/A. New unit tests (they need the
gitCLI, which the CI builder image has):TestIncrementalCloneKeepsCommitsBehindMergeBoundarybuilds the history above and checks thatQ,P,MandQ's parent are all fetched. It fails without the fix (Q should be fetched).TestNewestShallowCommitTimeIgnoresMissingCommitscovers a shallow file that lists a commit that was not fetched, and a repo without ashallowfile (like a full clone).Other Information
apache/devlake:v1.0.3-beta15image) and 2.56.0. The new tests pass with git 2.30.2 (CI builder image) and 2.39.5 (with-raceon 2.39.5).