Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ You can use this component with the following options:
- `AC_GIT_SUBMODULE`: Used to specify whether the submodule should be cloned.
- `AC_GIT_CACHE_CREDENTIALS`: If this set to true, the credentials will be cached to memory. This can be useful if the same credentials are used for multiple repositories.
- `AC_GIT_EXTRA_PARAMS`: If this set, sends extra parameter for git requests.
- `AC_GIT_COMMIT_FETCH_DEEPEN_STEPS`: Advanced. Space separated fetch depths that are tried, in order, when a specific commit has to be reached through its branch because the Git server does not serve arbitrary commits. Defaults to `50 500 5000`.

## Fetching a Specific Commit

When both a branch and a commit are given, the component first tries to fetch only that commit with `--depth=1`. This works when the Git server allows it (`uploadpack.allowReachableSHA1InWant` / `uploadpack.allowAnySHA1InWant`). If the server refuses, the branch is fetched with progressively larger depths (`AC_GIT_COMMIT_FETCH_DEEPEN_STEPS`), and only if the commit is still not reachable, the full history of the branch is fetched. The requested commit is always checked out.

## Output Variables

Expand Down
41 changes: 40 additions & 1 deletion git_clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ LFS=true
REFERENCE=''
IS_SPECIFIC_COMMIT=false
GIT_EXTRA_PARAMS=''
# Depths tried, in order, when a specific commit has to be reached through its branch.
COMMIT_FETCH_DEEPEN_STEPS="${AC_GIT_COMMIT_FETCH_DEEPEN_STEPS:-50 500 5000}"
for i in "$@"
do
case $i in
Expand Down Expand Up @@ -102,6 +104,43 @@ fi
"$@"
}

# Succeeds when the requested commit object already exists in the local repository.
function hasCommit(){
git cat-file -e "${COMMIT}^{commit}" 2>/dev/null
}

# Fetches only what is needed to check out ${COMMIT} instead of the whole history of
# ${BRANCH}. Three stages, cheapest first, each one guaranteeing the commit is present
# before it returns.
function fetchSpecificCommit(){
# 1) Ask the server for the single commit. Supported when the remote enables
# uploadpack.allowReachableSHA1InWant / uploadpack.allowAnySHA1InWant.
if runCommand git fetch --prune --progress --no-recurse-submodules --depth=1 origin "${COMMIT}" && hasCommit; then
return 0
fi

echo "Remote did not serve ${COMMIT} directly, deepening ${BRANCH} progressively."

# 2) Deepen the branch step by step. Builds almost always target a recent commit,
# so a few hundred commits are enough and still far cheaper than full history.
for depth in ${COMMIT_FETCH_DEEPEN_STEPS}; do
if ! runCommand git fetch --prune --progress --no-recurse-submodules --depth="${depth}" origin "${BRANCH}"; then
break
fi
if hasCommit; then
return 0
fi
done

# 3) Last resort: the full history fetch of the branch, the previous behavior.
echo "${COMMIT} is not within the deepened history, fetching the full history of ${BRANCH}."
if [ -f .git/shallow ]; then
runCommand git fetch --unshallow origin "${BRANCH}"
else
runCommand git fetch origin "${BRANCH}"
fi
}
Comment on lines +135 to +142

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Verify the commit after the full-history fetch.

A full fetch of ${BRANCH} can succeed when ${COMMIT} is not reachable from that branch. fetchSpecificCommit then returns success without the requested commit. The later checkout can fail.

  • git_clone.sh#L135-L142: Run hasCommit after the full-history fetch. Return nonzero if the commit is still unavailable.
  • README.md#L29-L29: Keep the “always checked out” statement only after the final validation exists.
Proposed fix
         if [ -f .git/shallow ]; then
             runCommand git fetch --unshallow origin "${BRANCH}"
         else
             runCommand git fetch origin "${BRANCH}"
         fi
+        hasCommit
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# 3) Last resort: the full history fetch of the branch, the previous behavior.
echo "${COMMIT} is not within the deepened history, fetching the full history of ${BRANCH}."
if [ -f .git/shallow ]; then
runCommand git fetch --unshallow origin "${BRANCH}"
else
runCommand git fetch origin "${BRANCH}"
fi
}
# 3) Last resort: the full history fetch of the branch, the previous behavior.
echo "${COMMIT} is not within the deepened history, fetching the full history of ${BRANCH}."
if [ -f .git/shallow ]; then
runCommand git fetch --unshallow origin "${BRANCH}"
else
runCommand git fetch origin "${BRANCH}"
fi
hasCommit
}
📍 Affects 2 files
  • git_clone.sh#L135-L142 (this comment)
  • README.md#L29-L29
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@git_clone.sh` around lines 135 - 142, The full-history fallback in
git_clone.sh, within fetchSpecificCommit, must validate the requested commit
after fetching: call hasCommit and return nonzero if ${COMMIT} remains
unavailable. In README.md at line 29, retain the “always checked out” statement
only once this final validation is enforced.


runCommand git --version
runCommand git lfs --version
runCommand git init
Expand Down Expand Up @@ -135,7 +174,7 @@ fi

if [ "$IS_SPECIFIC_COMMIT" = true ]; then
if [ ! -z "${BRANCH}" ]; then
runCommand git fetch origin "${BRANCH}"
fetchSpecificCommit
else
runCommand git fetch
fi
Expand Down